Last active: 2 years ago
Zego redux slice
import { Message } from '@/projects/court/hooks/zego/useMessage';
import { FileListData, FileListDatum } from '@/utils/api/chat';
import { createSelector, createSlice, PayloadAction } from '@reduxjs/toolkit';
import { nanoid } from 'nanoid';
import { ZegoStreamList } from 'zego-express-engine-webrtc/sdk/code/zh/ZegoExpressEntity.web';
import { ZegoUser } from 'zego-express-engine-webrtc/sdk/src/common/zego.entity';
import { ZegoBroadcastMessageInfo } from 'zego-express-engine-webrtm/sdk/code/zh/ZegoExpressEntity';
import { RootState } from '..';
export type RoomState = {
// 即构 APP ID
appID: number;
// 当前房间 ID
roomId: string;
// 即构当前用户 ID 与参展商手机号相同
userId: string;
// 用户名
userName: string;
// 用户角色
userType: '' | 'judege' | 'normal';
// 即构房间 token
token: string;
id: string;
// 当前房间类型 未登录时为空
roomType: '' | 'lobby' | 'mediation';
};
export const initRoomState: RoomState = {
appID: 0,
roomId: '',
// 用户 id 为当前登陆展台的手机号,必须先登陆
userId: '',
userName: '',
userType: '',
token: '',
id: '',
roomType: '',
};
export type RoomUserMsg = {
type: 'ADD' | 'DELETE';
user: ZegoUser;
};
export interface ZegoState {
// 房间状态
roomState: RoomState;
// 当前房间内用户
userList: ZegoUser[];
// 当前房间推流用户
currentUsers: ZegoStreamList[];
// 房间内消息
messageList: Message[];
// 房间内未读消息
unreadMsgs: number;
// 用户进入或离开消息
roomUserMsg: RoomUserMsg[];
// 文件列表
fileList: {
page: number;
pageCount: number;
// 文件类型 0 普通文件 1 调解文件
type: 1 | 0;
total: number;
loading: boolean;
files: FileListDatum[];
// 通过提交状态,手动触发文件列表刷新 为 true 时才会刷新
toggleRefresh: boolean;
};
}
const initialState: ZegoState = {
roomState: initRoomState,
userList: [],
currentUsers: [],
messageList: [],
unreadMsgs: 0,
roomUserMsg: [],
fileList: {
page: 1,
pageCount: 10,
// 文件类型 0 普通文件 1 调解文件
type: 1 as const,
total: 0,
loading: false,
toggleRefresh: false,
files: [],
},
};
export const zegoSlice = createSlice({
name: 'zego',
initialState,
reducers: {
logout() {
return initialState;
},
setList(s, action: PayloadAction<Partial<ZegoState>>) {
return {
...s,
...action.payload,
};
},
// 房间状态
updateRoom(s, action: PayloadAction<Partial<RoomState>>) {
s.roomState = {
...s.roomState,
...action.payload,
};
},
// 用户列表
addUser(s, action: PayloadAction<ZegoUser[]>) {
s.userList = s.userList.concat(action.payload);
},
removeUser(s, action: PayloadAction<ZegoUser[]>) {
action.payload.forEach((user) => {
const index = s.userList.findIndex(
(duser) => duser.userID === user.userID
);
if (!~index) return;
s.userList.splice(index, 1);
});
},
// 用户进入或离开房间 参数是全部用户
updateRoomMsg(s, action: PayloadAction<RoomUserMsg[]>) {
const list = action.payload;
if (list.length > 0) {
s.roomUserMsg = [...s.roomUserMsg, ...action.payload];
} else {
s.roomUserMsg = list;
}
},
// 消息列表
addMessage(s, action: PayloadAction<Message>) {
s.messageList.push(action.payload);
},
receiveMessage(s, action: PayloadAction<ZegoBroadcastMessageInfo[]>) {
const cleanDup = (msg: ZegoBroadcastMessageInfo) => {
const messages = s.messageList.filter((m) => m.content.type === 'msg');
const duplicateMsg = messages.find(
(m) => m.content.messageID === msg.messageID
);
if (duplicateMsg) return;
const message: Message = {
id: nanoid(),
sending: false,
content: {
type: 'msg',
...msg,
},
};
s.messageList.push(message);
// 新收到的消息为未读消息
s.unreadMsgs += 1;
};
action.payload.forEach(cleanDup);
},
cleanUnread(s) {
s.unreadMsgs = 0;
},
// 文件列表
updateFileList(s, action: PayloadAction<FileListData>) {
s.fileList.total = action.payload.total;
s.fileList.files = action.payload.data;
},
changePage(s, action: PayloadAction<{ page: number; pageSize: number }>) {
const { page, pageSize } = action.payload;
s.fileList.page = page;
s.fileList.pageCount = pageSize;
},
toggleFile(
s,
action: PayloadAction<{
[key in string]: boolean;
}>
) {
s.fileList = {
...s.fileList,
...action.payload,
};
},
},
});
export const {
logout,
setList,
removeUser,
addUser,
addMessage,
receiveMessage,
cleanUnread,
updateRoom,
updateRoomMsg,
updateFileList,
changePage,
toggleFile,
} = zegoSlice.actions;
export default zegoSlice.reducer;
export const selectRoomState = (s: RootState) => s.zego.roomState;
export const selectMessageList = (s: RootState) => s.zego.messageList;
export const selectUserList = (s: RootState) => s.zego.userList;
export const selectFileList = (s: RootState) => s.zego.fileList.files;
export const selectFilePage = (s: RootState) => s.zego.fileList.page;
export const selectFileCount = (s: RootState) => s.zego.fileList.pageCount;
export const selectFileType = (s: RootState) => s.zego.fileList.type;
export const selectFilePages = createSelector(
[selectFilePage, selectFileCount, selectFileType],
(page, pageCount, type) => {
return {
page,
pageCount,
type,
};
}
);