import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { isFinite, sortBy, uniq, xor } from 'lodash'; type RoomInfo = { canWrite: boolean; subscriberCount: number; moderators: Array; }; export type SogsRoomInfoState = { rooms: Record; }; export const initialSogsRoomInfoState: SogsRoomInfoState = { rooms: {}, }; function addEmptyEntryIfNeeded(state: any, convoId: string) { if (!state.rooms[convoId]) { state.rooms[convoId] = { canWrite: true, subscriberCount: 0, moderators: [] }; } } /** * This slice is the one holding the memory-only infos of sogs room. This includes * - writeCapability * - subscriberCount * - moderators * * Note: moderators are almost never used for sogs. We mostly rely on admins, which are tracked through the conversationModel.groupAdmins attributes (and saved to DB) */ const sogsRoomInfosSlice = createSlice({ name: 'sogsRoomInfos', initialState: initialSogsRoomInfoState, reducers: { setSubscriberCount(state, action: PayloadAction<{ convoId: string; subscriberCount: number }>) { addEmptyEntryIfNeeded(state, action.payload.convoId); if (isFinite(action.payload.subscriberCount)) { state.rooms[action.payload.convoId].subscriberCount = action.payload.subscriberCount; } return state; }, setCanWrite(state, action: PayloadAction<{ convoId: string; canWrite: boolean }>) { addEmptyEntryIfNeeded(state, action.payload.convoId); state.rooms[action.payload.convoId].canWrite = !!action.payload.canWrite; return state; }, setModerators(state, action: PayloadAction<{ convoId: string; moderators: Array }>) { addEmptyEntryIfNeeded(state, action.payload.convoId); const existing = state.rooms[action.payload.convoId].moderators; const newMods = sortBy(uniq(action.payload.moderators)); // check if there is any changes (order excluded) between those two arrays const xord = xor(existing, newMods); if (!xord.length) { return state; } state.rooms[action.payload.convoId].moderators = newMods; return state; }, }, }); const { actions, reducer } = sogsRoomInfosSlice; const { setSubscriberCount, setCanWrite, setModerators } = actions; export const ReduxSogsRoomInfos = { setSubscriberCountOutsideRedux, setCanWriteOutsideRedux, setModeratorsOutsideRedux, sogsRoomInfoReducer: reducer, }; function setSubscriberCountOutsideRedux(convoId: string, subscriberCount: number) { window.inboxStore?.dispatch(setSubscriberCount({ convoId, subscriberCount })); } function setCanWriteOutsideRedux(convoId: string, canWrite: boolean) { window.inboxStore?.dispatch(setCanWrite({ convoId, canWrite })); } /** * Update the redux slice for that community's moderators list * if we are a moderator that room and the room is blinded, this update needs to contain our unblinded pubkey, NOT the blinded one. * * @param convoId the convoId of the room to set the moderators * @param moderators the updated list of moderators */ function setModeratorsOutsideRedux(convoId: string, moderators: Array) { window.inboxStore?.dispatch( setModerators({ convoId, moderators, }) ); return undefined; }