You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.5 KiB
TypeScript
111 lines
3.5 KiB
TypeScript
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
|
import { isFinite, sortBy, uniq, xor } from 'lodash';
|
|
import {
|
|
getCanWriteOutsideRedux,
|
|
getCurrentSubscriberCountOutsideRedux,
|
|
} from '../selectors/sogsRoomInfo';
|
|
|
|
type RoomInfo = {
|
|
canWrite: boolean;
|
|
subscriberCount: number;
|
|
moderators: Array<string>;
|
|
};
|
|
|
|
export type SogsRoomInfoState = {
|
|
rooms: Record<string, RoomInfo>;
|
|
};
|
|
|
|
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<string> }>) {
|
|
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) {
|
|
if (subscriberCount === getCurrentSubscriberCountOutsideRedux(convoId)) {
|
|
return;
|
|
}
|
|
window.inboxStore?.dispatch(setSubscriberCount({ convoId, subscriberCount }));
|
|
}
|
|
|
|
function setCanWriteOutsideRedux(convoId: string, canWrite: boolean) {
|
|
if (getCanWriteOutsideRedux(convoId) === canWrite) {
|
|
return;
|
|
}
|
|
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<string>) {
|
|
window.inboxStore?.dispatch(
|
|
setModerators({
|
|
convoId,
|
|
moderators,
|
|
})
|
|
);
|
|
return undefined;
|
|
}
|