Chore: Migrate to Typescript mergeSubscriptionRooms and findSubscriptionsRooms (#3747)
* fix fromJSONValue type * migrate findSubscription and mergeSubscription to typescript * chore: fix subscription param returning null
This commit is contained in:
parent
f27ddf2e22
commit
753dec9e27
|
@ -1,5 +1,7 @@
|
|||
import Model from '@nozbe/watermelondb/Model';
|
||||
import { MarkdownAST } from '@rocket.chat/message-parser';
|
||||
|
||||
import { IAttachment } from './IAttachment';
|
||||
import { IMessage } from './IMessage';
|
||||
import { IServedBy } from './IServedBy';
|
||||
import { SubscriptionType } from './ISubscription';
|
||||
|
@ -101,3 +103,52 @@ export interface IOmnichannelRoom extends Omit<IRoom, 'default' | 'featured' | '
|
|||
}
|
||||
|
||||
export type TRoomModel = IRoom & Model;
|
||||
|
||||
export interface IServerRoomItem {
|
||||
_id: string;
|
||||
name: string;
|
||||
fname: string;
|
||||
t: SubscriptionType;
|
||||
u: {
|
||||
_id: string;
|
||||
username: string;
|
||||
};
|
||||
customFields: {};
|
||||
ts: string;
|
||||
ro: boolean;
|
||||
_updatedAt: string;
|
||||
lm: string;
|
||||
lastMessage: {
|
||||
alias: string;
|
||||
msg: string;
|
||||
attachments: IAttachment[];
|
||||
parseUrls: boolean;
|
||||
bot: {
|
||||
i: string;
|
||||
};
|
||||
groupable: boolean;
|
||||
avatar: string;
|
||||
ts: string;
|
||||
u: IUser;
|
||||
rid: string;
|
||||
_id: string;
|
||||
_updatedAt: string;
|
||||
mentions: [];
|
||||
channels: [];
|
||||
md: MarkdownAST;
|
||||
};
|
||||
topic: string;
|
||||
joinCodeRequired: boolean;
|
||||
description: string;
|
||||
jitsiTimeout: string;
|
||||
usersCount: number;
|
||||
e2eKeyId: string;
|
||||
avatarETag: string;
|
||||
encrypted: boolean;
|
||||
}
|
||||
|
||||
export interface IServerRoom {
|
||||
update: IServerRoomItem[];
|
||||
remove: IServerRoomItem[];
|
||||
success: boolean;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ export interface IVisitor {
|
|||
export interface ISubscription {
|
||||
_id: string; // _id belongs watermelonDB
|
||||
id: string; // id from server
|
||||
_updatedAt?: string; // from server
|
||||
v?: IVisitor;
|
||||
f: boolean;
|
||||
t: SubscriptionType;
|
||||
ts: Date;
|
||||
|
@ -38,12 +40,14 @@ export interface ISubscription {
|
|||
alert: boolean;
|
||||
roles?: string[];
|
||||
unread: number;
|
||||
lm: string;
|
||||
lr: string;
|
||||
userMentions: number;
|
||||
groupMentions: number;
|
||||
tunread?: string[];
|
||||
tunreadUser?: string[];
|
||||
tunreadGroup?: string[];
|
||||
roomUpdatedAt: Date;
|
||||
roomUpdatedAt: Date | number;
|
||||
ro: boolean;
|
||||
lastOpen?: Date;
|
||||
description?: string;
|
||||
|
@ -88,3 +92,30 @@ export interface ISubscription {
|
|||
}
|
||||
|
||||
export type TSubscriptionModel = ISubscription & Model;
|
||||
|
||||
export interface IServerSubscriptionItem {
|
||||
_id: string;
|
||||
rid: string;
|
||||
u: {
|
||||
_id: string;
|
||||
username: string;
|
||||
};
|
||||
_updatedAt: string;
|
||||
alert: boolean;
|
||||
fname: string;
|
||||
groupMentions: number;
|
||||
name: string;
|
||||
open: boolean;
|
||||
t: string;
|
||||
unread: number;
|
||||
userMentions: number;
|
||||
ls: string;
|
||||
lr: string;
|
||||
tunread: number[] | [];
|
||||
}
|
||||
|
||||
export interface IServerSubscription {
|
||||
update: IServerSubscriptionItem[];
|
||||
remove: IServerSubscriptionItem[];
|
||||
success: boolean;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
import { Q } from '@nozbe/watermelondb';
|
||||
|
||||
import { IServerSubscriptionItem, IServerRoomItem } from '../../../definitions';
|
||||
import database from '../../database';
|
||||
|
||||
export default async (subscriptions = [], rooms = []) => {
|
||||
export default async (subscriptions: IServerSubscriptionItem[], rooms: IServerRoomItem[]) => {
|
||||
let sub = subscriptions;
|
||||
let room = rooms;
|
||||
try {
|
||||
const db = database.active;
|
||||
const subCollection = db.get('subscriptions');
|
||||
|
||||
const roomIds = rooms.filter(r => !subscriptions.find(s => s.rid === r._id)).map(r => r._id);
|
||||
let existingSubs = await subCollection.query(Q.where('rid', Q.oneOf(roomIds))).fetch();
|
||||
existingSubs = existingSubs.map(s => ({
|
||||
const existingSubs = await subCollection.query(Q.where('rid', Q.oneOf(roomIds))).fetch();
|
||||
const mappedExistingSubs = existingSubs.map(s => ({
|
||||
_id: s._id,
|
||||
f: s.f,
|
||||
t: s.t,
|
||||
|
@ -55,11 +58,12 @@ export default async (subscriptions = [], rooms = []) => {
|
|||
E2EKey: s.E2EKey,
|
||||
avatarETag: s.avatarETag
|
||||
}));
|
||||
subscriptions = subscriptions.concat(existingSubs);
|
||||
// Assign
|
||||
sub = subscriptions.concat(mappedExistingSubs as unknown as IServerSubscriptionItem);
|
||||
|
||||
const subsIds = subscriptions.filter(s => !rooms.find(r => s.rid === r._id)).map(s => s._id);
|
||||
let existingRooms = await subCollection.query(Q.where('id', Q.oneOf(subsIds))).fetch();
|
||||
existingRooms = existingRooms.map(r => ({
|
||||
const existingRooms = await subCollection.query(Q.where('id', Q.oneOf(subsIds))).fetch();
|
||||
const mappedExistingRooms = existingRooms.map(r => ({
|
||||
_updatedAt: r._updatedAt,
|
||||
lastMessage: r.lastMessage,
|
||||
description: r.description,
|
||||
|
@ -84,13 +88,14 @@ export default async (subscriptions = [], rooms = []) => {
|
|||
e2eKeyId: r.e2eKeyId,
|
||||
avatarETag: r.avatarETag
|
||||
}));
|
||||
rooms = rooms.concat(existingRooms);
|
||||
// Assign
|
||||
room = rooms.concat(mappedExistingRooms as unknown as IServerRoomItem);
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return {
|
||||
subscriptions,
|
||||
rooms
|
||||
subscriptions: sub,
|
||||
rooms: room
|
||||
};
|
||||
};
|
|
@ -5,17 +5,18 @@ import { store as reduxStore } from '../../auxStore';
|
|||
import { compareServerVersion } from '../../utils';
|
||||
import findSubscriptionsRooms from './findSubscriptionsRooms';
|
||||
import normalizeMessage from './normalizeMessage';
|
||||
import { ISubscription, IServerRoom, IServerSubscription, IServerSubscriptionItem, IServerRoomItem } from '../../../definitions';
|
||||
// TODO: delete and update
|
||||
|
||||
export const merge = (subscription, room) => {
|
||||
const serverVersion = reduxStore.getState().server.version;
|
||||
subscription = EJSON.fromJSONValue(subscription);
|
||||
room = EJSON.fromJSONValue(room);
|
||||
export const merge = (
|
||||
subscription: ISubscription | IServerSubscriptionItem,
|
||||
room?: ISubscription | IServerRoomItem
|
||||
): ISubscription => {
|
||||
const serverVersion = reduxStore.getState().server.version as string;
|
||||
subscription = EJSON.fromJSONValue(subscription) as ISubscription;
|
||||
|
||||
if (!subscription) {
|
||||
return;
|
||||
}
|
||||
if (room) {
|
||||
room = EJSON.fromJSONValue(room) as ISubscription;
|
||||
if (room._updatedAt) {
|
||||
subscription.lastMessage = normalizeMessage(room.lastMessage);
|
||||
subscription.description = room.description;
|
||||
|
@ -28,15 +29,21 @@ export const merge = (subscription, room) => {
|
|||
subscription.usernames = room.usernames;
|
||||
subscription.uids = room.uids;
|
||||
}
|
||||
|
||||
if (compareServerVersion(serverVersion, 'lowerThan', '3.7.0')) {
|
||||
const updatedAt = room?._updatedAt ? new Date(room._updatedAt) : null;
|
||||
const lastMessageTs = subscription?.lastMessage?.ts ? new Date(subscription.lastMessage.ts) : null;
|
||||
// @ts-ignore
|
||||
// If all parameters are null it will return zero, if only one is null it will return its timestamp only.
|
||||
// "It works", but it's not the best solution. It does not accept "Date" as a parameter, but it works.
|
||||
subscription.roomUpdatedAt = Math.max(updatedAt, lastMessageTs);
|
||||
} else {
|
||||
// https://github.com/RocketChat/Rocket.Chat/blob/develop/app/ui-sidenav/client/roomList.js#L180
|
||||
const lastRoomUpdate = room.lm || subscription.ts || subscription._updatedAt;
|
||||
// @ts-ignore Same as above scenario
|
||||
subscription.roomUpdatedAt = subscription.lr
|
||||
? Math.max(new Date(subscription.lr), new Date(lastRoomUpdate))
|
||||
? // @ts-ignore Same as above scenario
|
||||
Math.max(new Date(subscription.lr), new Date(lastRoomUpdate))
|
||||
: lastRoomUpdate;
|
||||
}
|
||||
subscription.ro = room.ro;
|
||||
|
@ -76,7 +83,7 @@ export const merge = (subscription, room) => {
|
|||
}
|
||||
|
||||
if (!subscription.name) {
|
||||
subscription.name = subscription.fname;
|
||||
subscription.name = subscription.fname as string;
|
||||
}
|
||||
|
||||
if (!subscription.autoTranslate) {
|
||||
|
@ -88,29 +95,24 @@ export const merge = (subscription, room) => {
|
|||
return subscription;
|
||||
};
|
||||
|
||||
export default async (subscriptions = [], rooms = []) => {
|
||||
if (subscriptions.update) {
|
||||
subscriptions = subscriptions.update;
|
||||
rooms = rooms.update;
|
||||
}
|
||||
export default async (serverSubscriptions: IServerSubscription, serverRooms: IServerRoom): Promise<ISubscription[]> => {
|
||||
const subscriptions = serverSubscriptions.update;
|
||||
const rooms = serverRooms.update;
|
||||
|
||||
// Find missing rooms/subscriptions on local database
|
||||
({ subscriptions, rooms } = await findSubscriptionsRooms(subscriptions, rooms));
|
||||
const findData = await findSubscriptionsRooms(subscriptions, rooms);
|
||||
// Merge each subscription into a room
|
||||
subscriptions = subscriptions.map(s => {
|
||||
const index = rooms.findIndex(({ _id }) => _id === s.rid);
|
||||
const mergedSubscriptions = findData.subscriptions.map(subscription => {
|
||||
const index = findData.rooms.findIndex(({ _id }) => _id === subscription.rid);
|
||||
// Room not found
|
||||
if (index < 0) {
|
||||
return merge(s);
|
||||
return merge(subscription);
|
||||
}
|
||||
const [room] = rooms.splice(index, 1);
|
||||
return merge(s, room);
|
||||
return merge(subscription, room);
|
||||
});
|
||||
// Decrypt all subscriptions missing decryption
|
||||
subscriptions = await Encryption.decryptSubscriptions(subscriptions);
|
||||
const decryptedSubscriptions = (await Encryption.decryptSubscriptions(mergedSubscriptions)) as ISubscription[];
|
||||
|
||||
return {
|
||||
subscriptions,
|
||||
rooms
|
||||
};
|
||||
return decryptedSubscriptions;
|
||||
};
|
|
@ -127,8 +127,11 @@ const createOrUpdateSubscription = async (subscription, room) => {
|
|||
}
|
||||
}
|
||||
|
||||
let tmp = merge(subscription, room);
|
||||
tmp = await Encryption.decryptSubscription(tmp);
|
||||
let tmp;
|
||||
if (subscription) {
|
||||
tmp = merge(subscription, room);
|
||||
tmp = await Encryption.decryptSubscription(tmp);
|
||||
}
|
||||
let sub;
|
||||
try {
|
||||
sub = await subCollection.find(tmp.rid);
|
||||
|
|
|
@ -57,8 +57,7 @@ const handleRoomsRequest = function* handleRoomsRequest({ params }) {
|
|||
}
|
||||
|
||||
const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt);
|
||||
const { subscriptions } = yield mergeSubscriptionsRooms(subscriptionsResult, roomsResult);
|
||||
|
||||
const subscriptions = yield mergeSubscriptionsRooms(subscriptionsResult, roomsResult);
|
||||
const db = database.active;
|
||||
const subCollection = db.get('subscriptions');
|
||||
const messagesCollection = db.get('messages');
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
diff --git a/node_modules/@types/ejson/index.d.ts b/node_modules/@types/ejson/index.d.ts
|
||||
index 3a35636..278ef98 100755
|
||||
--- a/node_modules/@types/ejson/index.d.ts
|
||||
+++ b/node_modules/@types/ejson/index.d.ts
|
||||
@@ -17,7 +17,7 @@ export function parse(str: string): any;
|
||||
export function stringify(obj: any, options?: StringifyOptions): string;
|
||||
|
||||
export function toJSONValue(obj: any): string;
|
||||
-export function fromJSONValue(obj: string): any;
|
||||
+export function fromJSONValue(obj: Object): any;
|
||||
export function isBinary(value: any): boolean;
|
||||
export function newBinary(len: number): Uint8Array;
|
||||
export function equals(a: any, b: any, options?: CloneOptions): boolean;
|
Loading…
Reference in New Issue