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;
 | 
						|
}
 |