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 Model from '@nozbe/watermelondb/Model';
|
||||||
|
import { MarkdownAST } from '@rocket.chat/message-parser';
|
||||||
|
|
||||||
|
import { IAttachment } from './IAttachment';
|
||||||
import { IMessage } from './IMessage';
|
import { IMessage } from './IMessage';
|
||||||
import { IServedBy } from './IServedBy';
|
import { IServedBy } from './IServedBy';
|
||||||
import { SubscriptionType } from './ISubscription';
|
import { SubscriptionType } from './ISubscription';
|
||||||
|
@ -101,3 +103,52 @@ export interface IOmnichannelRoom extends Omit<IRoom, 'default' | 'featured' | '
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TRoomModel = IRoom & Model;
|
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 {
|
export interface ISubscription {
|
||||||
_id: string; // _id belongs watermelonDB
|
_id: string; // _id belongs watermelonDB
|
||||||
id: string; // id from server
|
id: string; // id from server
|
||||||
|
_updatedAt?: string; // from server
|
||||||
|
v?: IVisitor;
|
||||||
f: boolean;
|
f: boolean;
|
||||||
t: SubscriptionType;
|
t: SubscriptionType;
|
||||||
ts: Date;
|
ts: Date;
|
||||||
|
@ -38,12 +40,14 @@ export interface ISubscription {
|
||||||
alert: boolean;
|
alert: boolean;
|
||||||
roles?: string[];
|
roles?: string[];
|
||||||
unread: number;
|
unread: number;
|
||||||
|
lm: string;
|
||||||
|
lr: string;
|
||||||
userMentions: number;
|
userMentions: number;
|
||||||
groupMentions: number;
|
groupMentions: number;
|
||||||
tunread?: string[];
|
tunread?: string[];
|
||||||
tunreadUser?: string[];
|
tunreadUser?: string[];
|
||||||
tunreadGroup?: string[];
|
tunreadGroup?: string[];
|
||||||
roomUpdatedAt: Date;
|
roomUpdatedAt: Date | number;
|
||||||
ro: boolean;
|
ro: boolean;
|
||||||
lastOpen?: Date;
|
lastOpen?: Date;
|
||||||
description?: string;
|
description?: string;
|
||||||
|
@ -88,3 +92,30 @@ export interface ISubscription {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TSubscriptionModel = ISubscription & Model;
|
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 { Q } from '@nozbe/watermelondb';
|
||||||
|
|
||||||
|
import { IServerSubscriptionItem, IServerRoomItem } from '../../../definitions';
|
||||||
import database from '../../database';
|
import database from '../../database';
|
||||||
|
|
||||||
export default async (subscriptions = [], rooms = []) => {
|
export default async (subscriptions: IServerSubscriptionItem[], rooms: IServerRoomItem[]) => {
|
||||||
|
let sub = subscriptions;
|
||||||
|
let room = rooms;
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const subCollection = db.get('subscriptions');
|
const subCollection = db.get('subscriptions');
|
||||||
|
|
||||||
const roomIds = rooms.filter(r => !subscriptions.find(s => s.rid === r._id)).map(r => r._id);
|
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();
|
const existingSubs = await subCollection.query(Q.where('rid', Q.oneOf(roomIds))).fetch();
|
||||||
existingSubs = existingSubs.map(s => ({
|
const mappedExistingSubs = existingSubs.map(s => ({
|
||||||
_id: s._id,
|
_id: s._id,
|
||||||
f: s.f,
|
f: s.f,
|
||||||
t: s.t,
|
t: s.t,
|
||||||
|
@ -55,11 +58,12 @@ export default async (subscriptions = [], rooms = []) => {
|
||||||
E2EKey: s.E2EKey,
|
E2EKey: s.E2EKey,
|
||||||
avatarETag: s.avatarETag
|
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);
|
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();
|
const existingRooms = await subCollection.query(Q.where('id', Q.oneOf(subsIds))).fetch();
|
||||||
existingRooms = existingRooms.map(r => ({
|
const mappedExistingRooms = existingRooms.map(r => ({
|
||||||
_updatedAt: r._updatedAt,
|
_updatedAt: r._updatedAt,
|
||||||
lastMessage: r.lastMessage,
|
lastMessage: r.lastMessage,
|
||||||
description: r.description,
|
description: r.description,
|
||||||
|
@ -84,13 +88,14 @@ export default async (subscriptions = [], rooms = []) => {
|
||||||
e2eKeyId: r.e2eKeyId,
|
e2eKeyId: r.e2eKeyId,
|
||||||
avatarETag: r.avatarETag
|
avatarETag: r.avatarETag
|
||||||
}));
|
}));
|
||||||
rooms = rooms.concat(existingRooms);
|
// Assign
|
||||||
|
room = rooms.concat(mappedExistingRooms as unknown as IServerRoomItem);
|
||||||
} catch {
|
} catch {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscriptions,
|
subscriptions: sub,
|
||||||
rooms
|
rooms: room
|
||||||
};
|
};
|
||||||
};
|
};
|
|
@ -5,17 +5,18 @@ import { store as reduxStore } from '../../auxStore';
|
||||||
import { compareServerVersion } from '../../utils';
|
import { compareServerVersion } from '../../utils';
|
||||||
import findSubscriptionsRooms from './findSubscriptionsRooms';
|
import findSubscriptionsRooms from './findSubscriptionsRooms';
|
||||||
import normalizeMessage from './normalizeMessage';
|
import normalizeMessage from './normalizeMessage';
|
||||||
|
import { ISubscription, IServerRoom, IServerSubscription, IServerSubscriptionItem, IServerRoomItem } from '../../../definitions';
|
||||||
// TODO: delete and update
|
// TODO: delete and update
|
||||||
|
|
||||||
export const merge = (subscription, room) => {
|
export const merge = (
|
||||||
const serverVersion = reduxStore.getState().server.version;
|
subscription: ISubscription | IServerSubscriptionItem,
|
||||||
subscription = EJSON.fromJSONValue(subscription);
|
room?: ISubscription | IServerRoomItem
|
||||||
room = EJSON.fromJSONValue(room);
|
): ISubscription => {
|
||||||
|
const serverVersion = reduxStore.getState().server.version as string;
|
||||||
|
subscription = EJSON.fromJSONValue(subscription) as ISubscription;
|
||||||
|
|
||||||
if (!subscription) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (room) {
|
if (room) {
|
||||||
|
room = EJSON.fromJSONValue(room) as ISubscription;
|
||||||
if (room._updatedAt) {
|
if (room._updatedAt) {
|
||||||
subscription.lastMessage = normalizeMessage(room.lastMessage);
|
subscription.lastMessage = normalizeMessage(room.lastMessage);
|
||||||
subscription.description = room.description;
|
subscription.description = room.description;
|
||||||
|
@ -28,15 +29,21 @@ export const merge = (subscription, room) => {
|
||||||
subscription.usernames = room.usernames;
|
subscription.usernames = room.usernames;
|
||||||
subscription.uids = room.uids;
|
subscription.uids = room.uids;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compareServerVersion(serverVersion, 'lowerThan', '3.7.0')) {
|
if (compareServerVersion(serverVersion, 'lowerThan', '3.7.0')) {
|
||||||
const updatedAt = room?._updatedAt ? new Date(room._updatedAt) : null;
|
const updatedAt = room?._updatedAt ? new Date(room._updatedAt) : null;
|
||||||
const lastMessageTs = subscription?.lastMessage?.ts ? new Date(subscription.lastMessage.ts) : 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);
|
subscription.roomUpdatedAt = Math.max(updatedAt, lastMessageTs);
|
||||||
} else {
|
} else {
|
||||||
// https://github.com/RocketChat/Rocket.Chat/blob/develop/app/ui-sidenav/client/roomList.js#L180
|
// https://github.com/RocketChat/Rocket.Chat/blob/develop/app/ui-sidenav/client/roomList.js#L180
|
||||||
const lastRoomUpdate = room.lm || subscription.ts || subscription._updatedAt;
|
const lastRoomUpdate = room.lm || subscription.ts || subscription._updatedAt;
|
||||||
|
// @ts-ignore Same as above scenario
|
||||||
subscription.roomUpdatedAt = subscription.lr
|
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;
|
: lastRoomUpdate;
|
||||||
}
|
}
|
||||||
subscription.ro = room.ro;
|
subscription.ro = room.ro;
|
||||||
|
@ -76,7 +83,7 @@ export const merge = (subscription, room) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subscription.name) {
|
if (!subscription.name) {
|
||||||
subscription.name = subscription.fname;
|
subscription.name = subscription.fname as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subscription.autoTranslate) {
|
if (!subscription.autoTranslate) {
|
||||||
|
@ -88,29 +95,24 @@ export const merge = (subscription, room) => {
|
||||||
return subscription;
|
return subscription;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async (subscriptions = [], rooms = []) => {
|
export default async (serverSubscriptions: IServerSubscription, serverRooms: IServerRoom): Promise<ISubscription[]> => {
|
||||||
if (subscriptions.update) {
|
const subscriptions = serverSubscriptions.update;
|
||||||
subscriptions = subscriptions.update;
|
const rooms = serverRooms.update;
|
||||||
rooms = rooms.update;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find missing rooms/subscriptions on local database
|
// 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
|
// Merge each subscription into a room
|
||||||
subscriptions = subscriptions.map(s => {
|
const mergedSubscriptions = findData.subscriptions.map(subscription => {
|
||||||
const index = rooms.findIndex(({ _id }) => _id === s.rid);
|
const index = findData.rooms.findIndex(({ _id }) => _id === subscription.rid);
|
||||||
// Room not found
|
// Room not found
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return merge(s);
|
return merge(subscription);
|
||||||
}
|
}
|
||||||
const [room] = rooms.splice(index, 1);
|
const [room] = rooms.splice(index, 1);
|
||||||
return merge(s, room);
|
return merge(subscription, room);
|
||||||
});
|
});
|
||||||
// Decrypt all subscriptions missing decryption
|
// Decrypt all subscriptions missing decryption
|
||||||
subscriptions = await Encryption.decryptSubscriptions(subscriptions);
|
const decryptedSubscriptions = (await Encryption.decryptSubscriptions(mergedSubscriptions)) as ISubscription[];
|
||||||
|
|
||||||
return {
|
return decryptedSubscriptions;
|
||||||
subscriptions,
|
|
||||||
rooms
|
|
||||||
};
|
|
||||||
};
|
};
|
|
@ -127,8 +127,11 @@ const createOrUpdateSubscription = async (subscription, room) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tmp = merge(subscription, room);
|
let tmp;
|
||||||
tmp = await Encryption.decryptSubscription(tmp);
|
if (subscription) {
|
||||||
|
tmp = merge(subscription, room);
|
||||||
|
tmp = await Encryption.decryptSubscription(tmp);
|
||||||
|
}
|
||||||
let sub;
|
let sub;
|
||||||
try {
|
try {
|
||||||
sub = await subCollection.find(tmp.rid);
|
sub = await subCollection.find(tmp.rid);
|
||||||
|
|
|
@ -57,8 +57,7 @@ const handleRoomsRequest = function* handleRoomsRequest({ params }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt);
|
const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt);
|
||||||
const { subscriptions } = yield mergeSubscriptionsRooms(subscriptionsResult, roomsResult);
|
const subscriptions = yield mergeSubscriptionsRooms(subscriptionsResult, roomsResult);
|
||||||
|
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const subCollection = db.get('subscriptions');
|
const subCollection = db.get('subscriptions');
|
||||||
const messagesCollection = db.get('messages');
|
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