diff --git a/shared/api/socket.ts b/shared/api/socket.ts index fd12f56d..0d109e0f 100644 --- a/shared/api/socket.ts +++ b/shared/api/socket.ts @@ -147,13 +147,6 @@ export function createSocket(token: string): Promise { // 连接成功 const appSocket = new AppSocket(socket); appSocket.setupSocketStatusTip(); - appSocket.request('chat.converse.findAndJoinRoom').catch((err) => { - console.error(err); - showToasts( - t('无法加入房间, 您将无法获取到最新的信息, 请刷新页面后重试'), - 'error' - ); - }); // 立即请求加入房间 resolve(appSocket); }); socket.once('error', () => { diff --git a/shared/model/converse.ts b/shared/model/converse.ts index b7df3f98..bbb52b09 100644 --- a/shared/model/converse.ts +++ b/shared/model/converse.ts @@ -45,3 +45,18 @@ export async function fetchConverseInfo( export async function updateAck(converseId: string, lastMessageId: string) { await request.post('/api/chat/ack/update', { converseId, lastMessageId }); } + +interface AckInfo { + userId: string; + converseId: string; + lastMessageId: string; +} + +/** + * 获取用户存储在远程的会话信息 + */ +export async function fetchUserAck(): Promise { + const { data } = await request.get('/api/chat/ack/all'); + + return data; +} diff --git a/shared/model/message.ts b/shared/model/message.ts index 3581a2df..2b3f76b8 100644 --- a/shared/model/message.ts +++ b/shared/model/message.ts @@ -54,3 +54,19 @@ export async function sendMessage( return data; } + +/** + * 基于会话id获取会话最后一条消息的id + */ +export async function fetchConverseLastMessages( + converseIds: string[] +): Promise<{ converseId: string; lastMessageId: string }[]> { + const { data } = await request.post( + '/api/chat/message/fetchConverseLastMessages', + { + converseIds, + } + ); + + return data; +} diff --git a/shared/redux/setup.ts b/shared/redux/setup.ts index d792060b..0570cbd8 100644 --- a/shared/redux/setup.ts +++ b/shared/redux/setup.ts @@ -4,8 +4,11 @@ import { chatActions, groupActions, userActions } from './slices'; import type { FriendRequest } from '../model/friend'; import { getCachedConverseInfo } from '../cache/cache'; import type { GroupInfo } from '../model/group'; -import type { ChatMessage } from '../model/message'; +import { ChatMessage, fetchConverseLastMessages } from '../model/message'; import { socketEventListeners } from '../manager/socket'; +import { showToasts } from '../manager/ui'; +import { t } from '../i18n'; +import { fetchUserAck } from '../model/converse'; /** * 初始化 Redux 上下文 @@ -22,6 +25,46 @@ export function setupRedux(socket: AppSocket, store: AppStore) { function initial(socket: AppSocket, store: AppStore) { console.log('初始化Redux上下文...'); + // 立即请求加入房间 + const conversesP = socket + .request<{ + dmConverseIds: string[]; + groupIds: string[]; + panelIds: string[]; + }>('chat.converse.findAndJoinRoom') + .catch((err) => { + console.error(err); + showToasts( + t('无法加入房间, 您将无法获取到最新的信息, 请刷新页面后重试'), + 'error' + ); + throw new Error('findAndJoinRoom failed'); + }); + + Promise.all([conversesP, fetchUserAck()]).then( + ([{ dmConverseIds, panelIds }, acks]) => { + /** + * TODO: 这里的逻辑还需要优化 + * 可能ack和lastMessageMap可以无关? + */ + + // 设置已读消息 + acks.forEach((ackInfo) => { + store.dispatch( + chatActions.setConverseAck({ + converseId: ackInfo.converseId, + lastMessageId: ackInfo.lastMessageId, + }) + ); + }); + + const converseIds = [...dmConverseIds, ...panelIds]; + fetchConverseLastMessages(converseIds).then((list) => { + store.dispatch(chatActions.setLastMessageMap(list)); + }); + } + ); + // 获取好友列表 socket.request('friend.getAllFriends').then((data) => { store.dispatch(userActions.setFriendList(data)); @@ -42,6 +85,9 @@ function initial(socket: AppSocket, store: AppStore) { }); }); + /** + * 获取用户群组列表 + */ socket.request('group.getUserGroups').then((groups) => { store.dispatch(groupActions.appendGroups(groups)); }); diff --git a/shared/redux/slices/chat.ts b/shared/redux/slices/chat.ts index 7e30efa0..4e05c68e 100644 --- a/shared/redux/slices/chat.ts +++ b/shared/redux/slices/chat.ts @@ -10,13 +10,15 @@ export interface ChatConverseState extends ChatConverseInfo { } interface ChatState { - converses: Record; - ack: Record; + converses: Record; // <会话Id, 会话信息> + ack: Record; // <会话Id, 本地最后一条会话Id> + lastMessageMap: Record; // <会话Id, 远程最后一条会话Id> } const initialState: ChatState = { converses: {}, ack: {}, + lastMessageMap: {}, }; const chatSlice = createSlice({ @@ -101,6 +103,25 @@ const chatSlice = createSlice({ const { converseId, lastMessageId } = action.payload; state.ack[converseId] = lastMessageId; }, + + /** + * 设置远程的最后一条会话的id + */ + setLastMessageMap( + state, + action: PayloadAction< + { + converseId: string; + lastMessageId: string; + }[] + > + ) { + const list = action.payload; + + list.forEach((item) => { + state.lastMessageMap[item.converseId] = item.lastMessageId; + }); + }, }, });