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.
		
		
		
		
		
			
		
			
				
	
	
		
			177 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			177 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
| import { cloneDeep, isNumber, uniq } from 'lodash';
 | |
| import { OpenGroupRequestCommonType } from '../session/apis/open_group_api/opengroupV2/ApiUtil';
 | |
| import { isOpenGroupV2 } from '../session/apis/open_group_api/utils/OpenGroupUtils';
 | |
| import { channels } from './channels';
 | |
| 
 | |
| export type OpenGroupV2RoomWithImageID = {
 | |
|   serverUrl: string;
 | |
| 
 | |
|   /** this is actually shared for all this server's room */
 | |
|   serverPublicKey: string;
 | |
|   roomId: string;
 | |
| 
 | |
|   /** the fileId to the group room's image */
 | |
|   imageID?: string;
 | |
| };
 | |
| 
 | |
| export type OpenGroupV2Room = {
 | |
|   serverUrl: string;
 | |
| 
 | |
|   /** this is actually shared for all this server's room */
 | |
|   serverPublicKey: string;
 | |
|   roomId: string;
 | |
| 
 | |
|   /** a user displayed name */
 | |
|   roomName?: string;
 | |
| 
 | |
|   /** the fileId of the group room's image */
 | |
|   imageID?: string;
 | |
| 
 | |
|   /** the linked ConversationModel.id */
 | |
|   conversationId?: string;
 | |
|   maxMessageFetchedSeqNo?: number;
 | |
|   lastInboxIdFetched?: number;
 | |
|   lastOutboxIdFetched?: number;
 | |
| 
 | |
|   /**
 | |
|    * This value is set with the current timestamp whenever we get new messages.
 | |
|    */
 | |
|   lastFetchTimestamp?: number;
 | |
| 
 | |
|   /**
 | |
|    * This is shared across all rooms in a server.
 | |
|    */
 | |
|   capabilities?: Array<string>;
 | |
| };
 | |
| 
 | |
| export const OpenGroupData = {
 | |
|   getAllV2OpenGroupRoomsMap,
 | |
|   opengroupRoomsLoad,
 | |
|   getV2OpenGroupRoom,
 | |
|   getV2OpenGroupRoomsByServerUrl,
 | |
|   saveV2OpenGroupRoom,
 | |
|   saveV2OpenGroupRooms,
 | |
|   getV2OpenGroupRoomByRoomId,
 | |
|   removeV2OpenGroupRoom,
 | |
|   getAllOpengroupsServerPubkeys,
 | |
|   getAllV2OpenGroupRooms,
 | |
| };
 | |
| 
 | |
| /**
 | |
|  *
 | |
|  * @returns a map containing as key the conversationId of the opengroup room and as value the OpenGroupV2Room details
 | |
|  */
 | |
| function getAllV2OpenGroupRoomsMap(): Map<string, OpenGroupV2Room> | undefined {
 | |
|   const results = new Map<string, OpenGroupV2Room>();
 | |
| 
 | |
|   throwIfNotLoaded().forEach(o => {
 | |
|     if (o.conversationId) {
 | |
|       results.set(o.conversationId, cloneDeep(o));
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   return results;
 | |
| }
 | |
| 
 | |
| // this is just to make testing and stubbing easier
 | |
| async function getAllV2OpenGroupRooms(): Promise<Array<OpenGroupV2Room> | undefined> {
 | |
|   return channels.getAllV2OpenGroupRooms();
 | |
| }
 | |
| 
 | |
| // avoid doing fetches and write too often from the db by using a cache on the renderer side.
 | |
| let cachedRooms: Array<OpenGroupV2Room> | null = null;
 | |
| 
 | |
| async function opengroupRoomsLoad() {
 | |
|   if (cachedRooms !== null) {
 | |
|     return;
 | |
|   }
 | |
|   const loadedFromDB = await OpenGroupData.getAllV2OpenGroupRooms();
 | |
| 
 | |
|   if (loadedFromDB) {
 | |
|     cachedRooms = [];
 | |
|     loadedFromDB.forEach(r => {
 | |
|       try {
 | |
|         cachedRooms?.push(r as any);
 | |
|       } catch (e) {
 | |
|         window.log.warn(e.message);
 | |
|       }
 | |
|     });
 | |
|     return;
 | |
|   }
 | |
|   cachedRooms = [];
 | |
| }
 | |
| 
 | |
| function throwIfNotLoaded() {
 | |
|   if (cachedRooms === null) {
 | |
|     throw new Error('opengroupRoomsLoad must be called first');
 | |
|   }
 | |
|   return cachedRooms;
 | |
| }
 | |
| function getV2OpenGroupRoom(conversationId: string): OpenGroupV2Room | undefined {
 | |
|   if (!isOpenGroupV2(conversationId)) {
 | |
|     throw new Error(`getV2OpenGroupRoom: this is not a valid v2 id: ${conversationId}`);
 | |
|   }
 | |
| 
 | |
|   const found = throwIfNotLoaded().find(m => m.conversationId === conversationId);
 | |
|   return (found && cloneDeep(found)) || undefined;
 | |
| }
 | |
| function getV2OpenGroupRoomsByServerUrl(serverUrl: string): Array<OpenGroupV2Room> | undefined {
 | |
|   const found = throwIfNotLoaded().filter(m => m.serverUrl === serverUrl);
 | |
| 
 | |
|   return (found && cloneDeep(found)) || undefined;
 | |
| }
 | |
| 
 | |
| function getV2OpenGroupRoomByRoomId(
 | |
|   roomInfos: OpenGroupRequestCommonType
 | |
| ): OpenGroupV2Room | undefined {
 | |
|   const found = throwIfNotLoaded().find(
 | |
|     m => m.roomId === roomInfos.roomId && m.serverUrl === roomInfos.serverUrl
 | |
|   );
 | |
| 
 | |
|   return (found && cloneDeep(found)) || undefined;
 | |
| }
 | |
| async function saveV2OpenGroupRooms(rooms: Array<OpenGroupV2Room>): Promise<void> {
 | |
|   await Promise.all(rooms.map(saveV2OpenGroupRoom));
 | |
| }
 | |
| 
 | |
| async function saveV2OpenGroupRoom(room: OpenGroupV2Room): Promise<void> {
 | |
|   if (!room.conversationId || !room.roomId || !room.serverUrl || !room.serverPublicKey) {
 | |
|     throw new Error('Cannot save v2 room, invalid data');
 | |
|   }
 | |
| 
 | |
|   const found =
 | |
|     (room.conversationId &&
 | |
|       throwIfNotLoaded().find(m => m.conversationId === room.conversationId)) ||
 | |
|     undefined;
 | |
| 
 | |
|   if (!found) {
 | |
|     await channels.saveV2OpenGroupRoom(room);
 | |
|     throwIfNotLoaded().push(cloneDeep(room));
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // because isEqual is funky with pointer being changed, we have to do this for now
 | |
|   if (JSON.stringify(room) !== JSON.stringify(found)) {
 | |
|     await channels.saveV2OpenGroupRoom(room);
 | |
|     const foundIndex =
 | |
|       room.conversationId &&
 | |
|       throwIfNotLoaded().findIndex(m => m.conversationId === room.conversationId);
 | |
|     if (isNumber(foundIndex) && foundIndex > -1) {
 | |
|       throwIfNotLoaded()[foundIndex] = cloneDeep(room);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| async function removeV2OpenGroupRoom(conversationId: string): Promise<void> {
 | |
|   await channels.removeV2OpenGroupRoom(conversationId);
 | |
|   const foundIndex =
 | |
|     conversationId && throwIfNotLoaded().findIndex(m => m.conversationId === conversationId);
 | |
|   if (isNumber(foundIndex) && foundIndex > -1) {
 | |
|     throwIfNotLoaded().splice(foundIndex, 1);
 | |
|   }
 | |
| }
 | |
| 
 | |
| function getAllOpengroupsServerPubkeys(): Array<string> {
 | |
|   return uniq(throwIfNotLoaded().map(room => room.serverPublicKey)) || [];
 | |
| }
 |