diff --git a/app/definitions/IRoom.ts b/app/definitions/IRoom.ts index 2ea2f1824..1f943cdb3 100644 --- a/app/definitions/IRoom.ts +++ b/app/definitions/IRoom.ts @@ -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 { +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 }; }; diff --git a/app/lib/methods/helpers/mergeSubscriptionsRooms.js b/app/lib/methods/helpers/mergeSubscriptionsRooms.ts similarity index 65% rename from app/lib/methods/helpers/mergeSubscriptionsRooms.js rename to app/lib/methods/helpers/mergeSubscriptionsRooms.ts index e4541a426..a0fc7c4dd 100644 --- a/app/lib/methods/helpers/mergeSubscriptionsRooms.js +++ b/app/lib/methods/helpers/mergeSubscriptionsRooms.ts @@ -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 => { + 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; }; diff --git a/app/lib/methods/subscriptions/rooms.js b/app/lib/methods/subscriptions/rooms.js index 9e1cf8519..14cf75d5c 100644 --- a/app/lib/methods/subscriptions/rooms.js +++ b/app/lib/methods/subscriptions/rooms.js @@ -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); diff --git a/app/sagas/rooms.js b/app/sagas/rooms.js index 56d6c6c42..9102be9f3 100644 --- a/app/sagas/rooms.js +++ b/app/sagas/rooms.js @@ -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'); diff --git a/patches/@types+ejson+2.1.3.patch b/patches/@types+ejson+2.1.3.patch new file mode 100644 index 000000000..cf404b43f --- /dev/null +++ b/patches/@types+ejson+2.1.3.patch @@ -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;