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.
		
		
		
		
		
			
		
			
				
	
	
		
			190 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			190 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			TypeScript
		
	
import { cloneDeep, isNumber, uniq } from 'lodash';
 | 
						|
import { ConversationCollection } from '../models/conversation';
 | 
						|
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,
 | 
						|
  getAllOpenGroupV2Conversations,
 | 
						|
  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() {
 | 
						|
  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()) as
 | 
						|
    | Array<OpenGroupV2Room>
 | 
						|
    | undefined;
 | 
						|
 | 
						|
  if (loadedFromDB) {
 | 
						|
    cachedRooms = new Array();
 | 
						|
    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);
 | 
						|
    }
 | 
						|
    return;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
async function getAllOpenGroupV2Conversations(): Promise<ConversationCollection> {
 | 
						|
  const conversations = await channels.getAllOpenGroupV2Conversations();
 | 
						|
 | 
						|
  const collection = new ConversationCollection();
 | 
						|
  collection.add(conversations);
 | 
						|
  return collection;
 | 
						|
}
 | 
						|
 | 
						|
function getAllOpengroupsServerPubkeys(): Array<string> {
 | 
						|
  return uniq(throwIfNotLoaded().map(room => room.serverPublicKey)) || [];
 | 
						|
}
 |