新消息闪烁提醒

dev/chat
Lei OT 1 year ago
parent f9abf66455
commit fd204762d7

@ -45,7 +45,7 @@ const websocketSlice = (set, get) => ({
setWebsocketRetrytimes: (retrytimes) => set({ websocketRetrytimes: retrytimes, websocketRetrying: retrytimes > 0 }),
connectWebsocket: (userId) => {
const { setWebsocket, setWebsocketOpened, setWebsocketRetrytimes, addError, handleMessage } = get();
const { setWebsocket, setWebsocketOpened, setWebsocketRetrytimes, addError, handleMessage, activeConversations } = get();
const realtimeAPI = new RealTimeAPI(
{
@ -56,7 +56,15 @@ const websocketSlice = (set, get) => ({
setWebsocketOpened(true);
setWebsocketRetrytimes(0);
},
() => setWebsocketOpened(false),
() => {
setWebsocketOpened(false)
const newMsgList = Object.keys(activeConversations).reduce((acc, key) => {
const newMsgList = activeConversations[key].slice(-10);
acc[key] = newMsgList;
return acc;
}, {});
set({ activeConversations: newMsgList });
},
(n) => setWebsocketRetrytimes(n)
);
@ -108,6 +116,8 @@ const websocketSlice = (set, get) => ({
if (permission === 'granted') {
const notification = new Notification(`${msgRender.senderName}`, {
body: msgRender?.text || `[ ${msgRender.type} ]`,
requireInteraction: true, // 设置手动关闭
tag: 'global-sales-notification', // 通知ID同类通知建议设置相同ID避免通知过多遮挡桌面
...(msgRender.type === 'photo' ? { image: msgRender.data.uri } : {}),
});
notification.onclick = function () {
@ -149,7 +159,8 @@ const conversationSlice = (set, get) => ({
return set((state) => ({
conversationsList: [...newConversations, ...state.conversationsList],
activeConversations: { ...activeConversations, ...newConversationsMapped }
activeConversations: { ...activeConversations, ...newConversationsMapped },
totalNotify: state.totalNotify + newConversations.map(ele => ele.unread_msg_count).reduce((acc, cur) => acc + cur, 0),
}));
},
delConversationitem: (conversation) => {
@ -158,15 +169,15 @@ const conversationSlice = (set, get) => ({
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
conversationsList.splice(targetIndex, 1);
return set((state) => ({
return set({
conversationsList: [...conversationsList],
activeConversations: { ...activeConversations, [`${targetId}`]: [] },
currentConversation: {},
}));
});
},
setCurrentConversation: (conversation) => {
// 清空未读
const { conversationsList } = get();
const { conversationsList, totalNotify } = get();
const targetId = conversation.sn;
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
targetIndex !== -1 ? conversationsList.splice(targetIndex, 1, {
@ -174,11 +185,12 @@ const conversationSlice = (set, get) => ({
unread_msg_count: 0,
}) : null;
return set({ currentConversation: conversation, referenceMsg: {}, conversationsList: [...conversationsList] });
return set({ totalNotify: totalNotify - conversation.unread_msg_count, currentConversation: conversation, referenceMsg: {}, conversationsList: [...conversationsList] });
},
});
const messageSlice = (set, get) => ({
totalNotify: 0,
msgListLoading: false,
activeConversations: {},
setMsgLoading: (msgListLoading) => set({ msgListLoading }),
@ -216,13 +228,13 @@ const messageSlice = (set, get) => ({
// });
// }
return set((state) => ({
return set({
activeConversations: { ...activeConversations, [String(targetId)]: targetMsgs },
conversationsList: [...conversationsList],
}));
// conversationsList: [...conversationsList],
});
},
sentOrReceivedNewMessage: (targetId, message) => { // msgRender:
const { activeConversations, conversationsList, currentConversation } = get();
const { activeConversations, conversationsList, currentConversation, totalNotify } = get();
const targetMsgs = activeConversations[String(targetId)] || [];
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
const lastReceivedTime = message.type !== 'system' && message.sender !== 'me' ? message.date : null;
@ -244,14 +256,15 @@ const messageSlice = (set, get) => ({
};
conversationsList.splice(targetIndex, 1);
conversationsList.unshift(newConversation);
return set((state) => ({
return set({
totalNotify: totalNotify+newConversation.unread_msg_count,
activeConversations: { ...activeConversations, [String(targetId)]: [...targetMsgs, message] },
conversationsList: [...conversationsList],
currentConversation: {
...currentConversation,
...(String(targetId) === String(currentConversation.sn) ? { last_received_time: message.date } : {}),
},
}));
});
},
});

@ -3,10 +3,10 @@ import useAuthStore from '@/stores/AuthStore'
import useConversationStore from '@/stores/ConversationStore'
import { useThemeContext } from '@/stores/ThemeContext'
import { DownOutlined } from '@ant-design/icons'
import { App as AntApp, Avatar, Col, ConfigProvider, Dropdown, Empty, Layout, Menu, Row, Space, Typography, theme } from 'antd'
import { App as AntApp, Avatar, Col, ConfigProvider, Dropdown, Empty, Layout, Menu, Row, Space, Typography, theme, Badge } from 'antd'
import zhLocale from 'antd/locale/zh_CN'
import 'dayjs/locale/zh-cn'
import { useEffect } from 'react'
import { useEffect, useState } from 'react'
import { Link, NavLink, Outlet, useHref, useNavigate } from 'react-router-dom'
import '@/assets/App.css'
@ -22,7 +22,7 @@ function AuthApp() {
const { colorPrimary, borderRadius } = useThemeContext()
const { loginUser } = useAuthStore()
const href = useHref()
useEffect(() => {
@ -32,7 +32,7 @@ function AuthApp() {
}
}, [href])
const totalNotify = useConversationStore((state) => state.totalNotify);
useEffect(() => {
if (loginUser.userId > 0) {
useConversationStore.getState().connectWebsocket(loginUser.userId);
@ -54,6 +54,44 @@ function AuthApp() {
token: { colorBgContainer },
} = theme.useToken()
// Flicker title when new message received
const [isTitleVisible, setIsTitleVisible] = useState(true);
useEffect(() => {
let interval;
if (totalNotify > 0) {
interval = setInterval(() => {
document.title = isTitleVisible ? `✉🔔🔥【${totalNotify}条新消息】` : '聊天式销售平台';
setIsTitleVisible(!isTitleVisible);
}, 600);
} else {
document.title = '聊天式销售平台';
}
return () => clearInterval(interval);
}, [totalNotify, isTitleVisible]);
// Display browser notification and change favicon when new message received
// useEffect(() => {
// if (hasNewMessage) {
// if (Notification.permission === "granted") {
// new Notification("New messages received!", {
// body: "You have new messages.",
// icon: "path-to-your-icon.png",
// });
// } else if (Notification.permission !== "denied") {
// Notification.requestPermission().then(permission => {
// if (permission === "granted") {
// new Notification("New messages received!", {
// body: "You have new messages.",
// icon: "path-to-your-icon.png",
// });
// }
// });
// }
// setFavicon('path-to-your-new-favicon.ico');
// }
// }, [hasNewMessage]);
return (
<ConfigProvider
theme={{
@ -85,7 +123,13 @@ function AuthApp() {
selectedKeys={[defaultPath]}
items={[
{ key: '/order/follow', label: <Link to='/order/follow'>订单跟踪</Link> },
{ key: '/order/chat', label: <Link to='/order/chat'>在线聊天</Link> },
{ key: '/order/chat', label: <Link to='/order/chat'>在线聊天
<Badge
count={totalNotify}
style={{
backgroundColor: '#52c41a',
}}
/></Link> },
{ key: '/chat/history', label: <Link to='/chat/history'>聊天历史</Link> },
]}
/>

Loading…
Cancel
Save