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.
session-desktop/ts/data/opengroups.ts

147 lines
4.4 KiB
TypeScript

import { cloneDeep, isNumber, uniq } from 'lodash';
import { channels } from './channels';
import { OpenGroupRequestCommonType, OpenGroupV2Room } from './types';
import { isOpenGroupV2 } from '../session/apis/open_group_api/utils/OpenGroupUtils';
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 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)) || [];
}