红点通知
一对一聊天
添加小红点,src/components/contact.jsx:
@@ -4,6 +4,7 @@ import "./Contact.css";
const Contact = (props) => {
return (
<div className="contact" onClick={props.onClick}>
+ {props.notify && <div className="notify-dot"></div>}
<div className="name truncate">{props.username}</div>
<div className="last-message truncate">
{props.message || "[no messages]"}
添加红点风格,src/components/Contact.css:
@@ -5,6 +5,7 @@
border-bottom: solid 1px var(--theme-color);
text-align: left;
cursor: pointer;
+ position: relative;
}
.name {
@@ -28,3 +29,13 @@
overflow: hidden;
text-overflow: ellipsis;
}
+
+.notify-dot {
+ position: absolute;
+ top: 8px;
+ right: 8px;
+ width: 8px;
+ height: 8px;
+ background-color: orangered;
+ border-radius: 50%;
+}
添加新的 state contactNotifications
,用于记住需要红点的联系人。
变更 src/App.js:
@@ -31,6 +31,7 @@ function App() {
const [groups, setGroups] = useState([]);
const [contactMessages, setContactMessages] = useState({});
const [groupMessages, setGroupMessages] = useState({});
+ const [contactNotifications, setContactNotifications] = useState({});
const [pickedContact, setPickedContact] = useState(null);
const [typedContent, setTypedContent] = useState("");
const resultEndRef = useRef(null);
@@ -53,6 +54,9 @@ function App() {
const newMessages = [...oldMessages, entry];
return { ...cm, [from]: newMessages };
});
+ setContactNotifications((cn) => {
+ return { ...cn, [from]: true };
+ });
});
socket.on("create-group", (data) => {
const { name, id } = data;
@@ -145,6 +149,11 @@ function App() {
}
return "";
};
+ const readMessage = (id) => {
+ setContactNotifications((cn) => {
+ return { ...cn, [id]: false };
+ });
+ };
return (
<>
<div className="app">
@@ -197,8 +206,16 @@ function App() {
key={e.sid}
username={e.emoji + " " + e.name}
message={lastMessage(contactMessages[e.sid])}
+ notify={
+ e.sid !== pickedContact?.sid &&
+ contactNotifications[e.sid]
+ }
onClick={() => {
setPickedContact(e);
+ if (pickedContact) {
+ readMessage(pickedContact.sid);
+ }
+ readMessage(e.sid);
}}
/>
))}
群聊天
添加红点,src/components/group.jsx:
@@ -4,6 +4,7 @@ import "./Contact.css";
const Group = (props) => {
return (
<div className="contact" onClick={props.onClick}>
+ {props.notify && <div className="notify-dot"></div>}
<div className="name truncate">{props.name}</div>
<div className="last-message truncate">
{props.message || "[no messages]"}
- 添加一个新 state
groupNotifications
,用于记住需要红点的群组。 - 为
Chat
和Groups
标签卡添加红点。当你在一个标签卡下,另一边的标签卡有新消息时会显示红点。
修改 src/App.js:
@@ -32,6 +32,7 @@ function App() {
const [contactMessages, setContactMessages] = useState({});
const [groupMessages, setGroupMessages] = useState({});
const [contactNotifications, setContactNotifications] = useState({});
+ const [groupNotifications, setGroupNotifications] = useState({});
const [pickedContact, setPickedContact] = useState(null);
const [typedContent, setTypedContent] = useState("");
const resultEndRef = useRef(null);
@@ -73,6 +74,9 @@ function App() {
const newMessages = [...oldMessages, entry];
return { ...gm, [roomId]: newMessages };
});
+ setGroupNotifications((gn) => {
+ return { ...gn, [roomId]: true };
+ });
});
socket.emit("user-join", user);
setConn(socket);
@@ -150,9 +154,24 @@ function App() {
return "";
};
const readMessage = (id) => {
- setContactNotifications((cn) => {
- return { ...cn, [id]: false };
- });
+ if (isGroupChatting) {
+ setGroupNotifications((gn) => {
+ return { ...gn, [id]: false };
+ });
+ } else {
+ setContactNotifications((cn) => {
+ return { ...cn, [id]: false };
+ });
+ }
+ };
+ const shouldNotify = () => {
+ if (isGroupChatting) {
+ // Notify for Chat Tab
+ return Object.values(contactNotifications).some((e) => e === true);
+ } else {
+ // Notify for Groups Tab
+ return Object.values(groupNotifications).some((e) => e === true);
+ }
};
return (
<>
@@ -174,6 +193,9 @@ function App() {
setPickedContact(null);
}}
>
+ {isGroupChatting && shouldNotify() && (
+ <span className="notify-dot"></span>
+ )}
Chat
</span>
<span
@@ -185,6 +207,9 @@ function App() {
setPickedContact(null);
}}
>
+ {!isGroupChatting && shouldNotify() && (
+ <span className="notify-dot"></span>
+ )}
Groups
</span>
</div>
@@ -196,8 +221,15 @@ function App() {
key={e.id}
name={e.name}
message={lastMessage(groupMessages[e.id])}
+ notify={
+ e.id !== pickedContact?.id && groupNotifications[e.id]
+ }
onClick={() => {
setPickedContact(e);
+ if (pickedContact) {
+ readMessage(pickedContact.id);
+ }
+ readMessage(e.id);
}}
/>
))
调整风格,src/App.css:
@@ -28,6 +28,12 @@ body {
background-color: var(--secondary-color);
padding: 5px 12px;
cursor: pointer;
+ position: relative;
+
+ .notify-dot {
+ top: 4px;
+ right: 4px;
+ }
}
.left-seg {
避免当前对话框误生成红点
变更 src/app.js:
@@ -92,6 +92,20 @@ function App() {
resultEndRef.current?.scrollIntoView({ behavior: "smooth" });
}, [contactMessages, groupMessages, pickedContact]);
+ useEffect(() => {
+ // Avoid red dots for the current conversation
+ if (!pickedContact) return;
+ if (isGroupChatting) {
+ setGroupNotifications((gn) => {
+ return { ...gn, [pickedContact.id]: false };
+ });
+ } else {
+ setContactNotifications((cn) => {
+ return { ...cn, [pickedContact.sid]: false };
+ });
+ }
+ }, [contactMessages, groupMessages, pickedContact, isGroupChatting]);
+
const login = (emoji, name) => {
setUser({ emoji, name });
setLogged(true);
@@ -226,9 +240,6 @@ function App() {
}
onClick={() => {
setPickedContact(e);
- if (pickedContact) {
- readMessage(pickedContact.id);
- }
readMessage(e.id);
}}
/>
@@ -244,9 +255,6 @@ function App() {
}
onClick={() => {
setPickedContact(e);
- if (pickedContact) {
- readMessage(pickedContact.sid);
- }
readMessage(e.sid);
}}
/>
我们使用 useEffect
来监测 contactMessages
和 groupMessages
的状态变化,然后相应地关闭红点。