From 09f73aee3d5c0cb6716ce2cb3b4480ffaa3c13e8 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Tue, 8 Mar 2022 13:25:27 -0300 Subject: [PATCH 1/3] Chore: Create IServerRoom and IServerSubscription (#3782) --- app/definitions/IRocketChatRecord.ts | 2 +- app/definitions/IRoom.ts | 148 ++++++++++++------ app/definitions/IServedBy.ts | 4 +- app/definitions/ISpotlight.ts | 4 +- app/definitions/ISubscription.ts | 85 ++++++---- app/definitions/ITeam.ts | 8 +- app/definitions/rest/v1/channels.ts | 12 +- app/definitions/rest/v1/chat.ts | 6 +- app/definitions/rest/v1/dm.ts | 4 +- app/definitions/rest/v1/groups.ts | 8 +- app/definitions/rest/v1/im.ts | 13 +- app/definitions/rest/v1/invites.ts | 12 +- app/definitions/rest/v1/omnichannel.ts | 4 +- app/definitions/rest/v1/rooms.ts | 16 +- app/definitions/rest/v1/teams.ts | 8 +- app/lib/methods/canOpenRoom.ts | 6 +- app/lib/methods/getRoomInfo.ts | 15 +- .../methods/helpers/findSubscriptionsRooms.ts | 8 +- .../helpers/mergeSubscriptionsRooms.ts | 125 +++++++-------- app/lib/methods/subscriptions/rooms.ts | 13 +- app/views/ForwardLivechatView.tsx | 6 +- app/views/RoomView/index.tsx | 2 +- app/views/SearchMessagesView/index.tsx | 7 +- 23 files changed, 302 insertions(+), 214 deletions(-) diff --git a/app/definitions/IRocketChatRecord.ts b/app/definitions/IRocketChatRecord.ts index 8a933059a..e5f72a01d 100644 --- a/app/definitions/IRocketChatRecord.ts +++ b/app/definitions/IRocketChatRecord.ts @@ -1,5 +1,5 @@ export interface IRocketChatRecord { - _id?: string; + _id: string; _updatedAt?: Date; } diff --git a/app/definitions/IRoom.ts b/app/definitions/IRoom.ts index 6ebb88e0b..378e7b798 100644 --- a/app/definitions/IRoom.ts +++ b/app/definitions/IRoom.ts @@ -1,8 +1,7 @@ import Model from '@nozbe/watermelondb/Model'; -import { MarkdownAST } from '@rocket.chat/message-parser'; -import { IAttachment } from './IAttachment'; import { IMessage } from './IMessage'; +import { IRocketChatRecord } from './IRocketChatRecord'; import { IServedBy } from './IServedBy'; import { IVisitor, SubscriptionType } from './ISubscription'; import { IUser } from './IUser'; @@ -15,8 +14,8 @@ interface IRequestTranscript { } export interface IRoom { - _id: string; fname?: string; + _id: string; id: string; rid: string; prid: string; @@ -37,11 +36,25 @@ export interface IRoom { e2eKeyId?: string; avatarETag?: string; latest?: string; - default?: true; - featured?: true; + default?: boolean; + featured?: boolean; muted?: string[]; teamId?: string; ignored?: string; + + _updatedAt?: Date; + archived?: boolean; + announcement?: string; + description?: string; + lastMessage?: IMessage; + topic?: string; + reactWhenReadOnly?: boolean; + joinCodeRequired?: boolean; + jitsiTimeout?: Date; + usernames?: string[]; + uids: Array; + lm?: Date; + sysMes?: string[]; } export enum OmnichannelSourceType { @@ -108,51 +121,84 @@ export interface IOmnichannelRoom extends Partial; + uids: Array; + + lastMessage?: IMessage; + lm?: Date; + usersCount: number; + jitsiTimeout?: Date; + webRtcCallStartTime?: Date; + servedBy?: { + _id: string; + }; + + streamingOptions?: { + id?: string; + type: string; + }; + + prid?: string; + avatarETag?: string; + tokenpass?: { + require: string; + tokens: { + token: string; + balance: number; + }[]; + }; + + teamMain?: boolean; + teamId?: string; + teamDefault?: boolean; + open?: boolean; + + autoTranslateLanguage: string; + autoTranslate?: boolean; + unread?: number; + alert?: boolean; + hideUnreadStatus?: boolean; + + sysMes?: string[]; + muted?: string[]; + unmuted?: string[]; + + usernames?: string[]; + ts?: Date; + + cl?: boolean; + ro?: boolean; + favorite?: boolean; + archived?: boolean; + announcement?: string; + description?: string; + + reactWhenReadOnly?: boolean; + joinCodeRequired?: boolean; + e2eKeyId?: string; + v?: { + _id?: string; + token?: string; + status: 'online' | 'busy' | 'away' | 'offline'; + }; + departmentId?: string; + livechatData?: any; + tags?: string[]; } diff --git a/app/definitions/IServedBy.ts b/app/definitions/IServedBy.ts index 4bf31aad2..cc40aeedf 100644 --- a/app/definitions/IServedBy.ts +++ b/app/definitions/IServedBy.ts @@ -1,5 +1,5 @@ export interface IServedBy { _id: string; - username: string; - ts: Date; + username?: string; + ts?: Date; } diff --git a/app/definitions/ISpotlight.ts b/app/definitions/ISpotlight.ts index 8a0557756..1744297a2 100644 --- a/app/definitions/ISpotlight.ts +++ b/app/definitions/ISpotlight.ts @@ -1,9 +1,9 @@ -import { IServerRoomItem } from './IRoom'; +import { IServerRoom } from './IRoom'; import { IUser } from './IUser'; export type TSpotlightUser = Pick & { outside: boolean }; -export type ISpotlightRoom = Pick & Partial>; +export type ISpotlightRoom = Pick & Partial>; export interface ISpotlight { users: TSpotlightUser[]; diff --git a/app/definitions/ISubscription.ts b/app/definitions/ISubscription.ts index d54718a41..6f13a040c 100644 --- a/app/definitions/ISubscription.ts +++ b/app/definitions/ISubscription.ts @@ -2,10 +2,13 @@ import Model from '@nozbe/watermelondb/Model'; import Relation from '@nozbe/watermelondb/Relation'; import { ILastMessage, TMessageModel } from './IMessage'; +import { IRocketChatRecord } from './IRocketChatRecord'; +import { RoomID, RoomType } from './IRoom'; import { IServedBy } from './IServedBy'; import { TThreadModel } from './IThread'; import { TThreadMessageModel } from './IThreadMessage'; import { TUploadModel } from './IUpload'; +import { IUser } from './IUser'; export enum SubscriptionType { GROUP = 'p', @@ -33,9 +36,9 @@ export enum ERoomTypes { type RelationModified = { fetch(): Promise } & Relation; export interface ISubscription { - _id: string; // _id belongs watermelonDB - id: string; // id from server - _updatedAt?: string; // from server + _id: string; + id: string; + _updatedAt?: string; v?: IVisitor; f: boolean; t: SubscriptionType; // TODO: we need to review this type later @@ -73,7 +76,7 @@ export interface ISubscription { prid?: string; draftMessage?: string | null; lastThreadSync?: Date; - jitsiTimeout?: number; + jitsiTimeout?: Date; autoTranslate?: boolean; autoTranslateLanguage?: string; lastMessage?: ILastMessage | null; // TODO: we need to use IMessage here @@ -104,29 +107,57 @@ 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; +// https://github.com/RocketChat/Rocket.Chat/blob/a88a96fcadd925b678ff27ada37075e029f78b5e/definition/ISubscription.ts#L8 +export interface IServerSubscription extends IRocketChatRecord { + u: Pick; + v?: Pick; + rid: RoomID; open: boolean; - t: string; - unread: number; - userMentions: number; - ls: string; - lr: string; - tunread: number[] | []; -} + ts: Date; -export interface IServerSubscription { - update: IServerSubscriptionItem[]; - remove: IServerSubscriptionItem[]; - success: boolean; + name: string; + + alert?: boolean; + unread: number; + t: RoomType; + ls: Date; + f?: true; + lr: Date; + hideUnreadStatus?: true; + teamMain?: boolean; + teamId?: string; + + userMentions: number; + groupMentions: number; + + tunread?: Array; + tunreadGroup?: Array; + tunreadUser?: Array; + + prid?: RoomID; + + roles?: string[]; + + onHold?: boolean; + encrypted?: boolean; + E2EKey?: string; + unreadAlert?: 'default' | 'all' | 'mentions' | 'nothing'; + + fname?: unknown; + + code?: unknown; + archived?: unknown; + audioNotificationValue?: unknown; + desktopNotifications?: unknown; + mobilePushNotifications?: unknown; + emailNotifications?: unknown; + blocked?: unknown; + blocker?: unknown; + autoTranslate?: unknown; + autoTranslateLanguage?: unknown; + disableNotifications?: unknown; + muteGroupMentions?: unknown; + ignored?: unknown; + + department?: unknown; } diff --git a/app/definitions/ITeam.ts b/app/definitions/ITeam.ts index ae5f9544c..2e9525fdb 100644 --- a/app/definitions/ITeam.ts +++ b/app/definitions/ITeam.ts @@ -1,6 +1,6 @@ import { IRocketChatRecord } from './IRocketChatRecord'; import { IUser } from './IUser'; -import { IServerRoomItem } from './IRoom'; +import { IServerRoom } from './IRoom'; export enum TEAM_TYPE { PUBLIC = 0, @@ -50,13 +50,9 @@ export interface ITeamStats { export interface IServerTeamUpdateRoom extends Omit< - IServerRoomItem, + IServerRoom, 'topic' | 'joinCodeRequired' | 'description' | 'jitsiTimeout' | 'usersCount' | 'e2eKeyId' | 'avatarETag' > { - broadcast: boolean; - msgs: number; - default: boolean; - sysMes: boolean; teamId: string; teamDefault: boolean; } diff --git a/app/definitions/rest/v1/channels.ts b/app/definitions/rest/v1/channels.ts index 1c5dc09a6..3e0c72e8a 100644 --- a/app/definitions/rest/v1/channels.ts +++ b/app/definitions/rest/v1/channels.ts @@ -1,12 +1,12 @@ import { ITeam } from '../../ITeam'; import type { IMessage, IMessageFromServer } from '../../IMessage'; -import type { IRoom, IServerRoomItem } from '../../IRoom'; +import type { IServerRoom } from '../../IRoom'; import type { IUser } from '../../IUser'; export type ChannelsEndpoints = { 'channels.files': { GET: (params: { - roomId: IRoom['_id']; + roomId: IServerRoom['_id']; offset: number; count: number; sort: string | { uploadedAt: number }; @@ -17,7 +17,7 @@ export type ChannelsEndpoints = { }; }; 'channels.members': { - GET: (params: { roomId: IRoom['_id']; offset?: number; count?: number; filter?: string; status?: string[] }) => { + GET: (params: { roomId: IServerRoom['_id']; offset?: number; count?: number; filter?: string; status?: string[] }) => { count: number; offset: number; members: IUser[]; @@ -46,14 +46,14 @@ export type ChannelsEndpoints = { teamId?: string; }; }) => { - group: Partial; + group: Partial; }; }; 'channels.convertToTeam': { POST: (params: { channelId: string; channelName: string }) => { team: ITeam }; }; 'channels.info': { - GET: (params: { roomId: string }) => { channel: IServerRoomItem }; + GET: (params: { roomId: string }) => { channel: IServerRoom }; }; 'channels.counters': { GET: (params: { roomId: string }) => { @@ -67,7 +67,7 @@ export type ChannelsEndpoints = { }; }; 'channels.join': { - POST: (params: { roomId: string; joinCode: string | null }) => { channel: IServerRoomItem }; + POST: (params: { roomId: string; joinCode: string | null }) => { channel: IServerRoom }; }; 'channels.close': { POST: (params: { roomId: string }) => {}; diff --git a/app/definitions/rest/v1/chat.ts b/app/definitions/rest/v1/chat.ts index 98c25df9a..8481f78db 100644 --- a/app/definitions/rest/v1/chat.ts +++ b/app/definitions/rest/v1/chat.ts @@ -1,5 +1,5 @@ import type { IMessage } from '../../IMessage'; -import type { IRoom } from '../../IRoom'; +import type { IServerRoom } from '../../IRoom'; import { PaginatedResult } from '../helpers/PaginatedResult'; export type ChatEndpoints = { @@ -30,14 +30,14 @@ export type ChatEndpoints = { POST: (params: { messageId: IMessage['_id']; description: string }) => void; }; 'chat.getDiscussions': { - GET: (params: { roomId: IRoom['_id']; text?: string; offset: number; count: number }) => { + GET: (params: { roomId: IServerRoom['_id']; text?: string; offset: number; count: number }) => { messages: IMessage[]; total: number; }; }; 'chat.getThreadsList': { GET: (params: { - rid: IRoom['_id']; + rid: IServerRoom['_id']; type: 'unread' | 'following' | 'all'; text?: string; offset: number; diff --git a/app/definitions/rest/v1/dm.ts b/app/definitions/rest/v1/dm.ts index 6783cbc07..18ece05d5 100644 --- a/app/definitions/rest/v1/dm.ts +++ b/app/definitions/rest/v1/dm.ts @@ -1,4 +1,4 @@ -import type { IRoom } from '../../IRoom'; +import type { IServerRoom } from '../../IRoom'; import type { IUser } from '../../IUser'; export type DmEndpoints = { @@ -15,7 +15,7 @@ export type DmEndpoints = { excludeSelf?: boolean; } ) => { - room: IRoom & { rid: IRoom['_id'] }; + room: IServerRoom & { rid: IServerRoom['_id'] }; }; }; }; diff --git a/app/definitions/rest/v1/groups.ts b/app/definitions/rest/v1/groups.ts index 68c609558..22ff41495 100644 --- a/app/definitions/rest/v1/groups.ts +++ b/app/definitions/rest/v1/groups.ts @@ -1,17 +1,17 @@ import { ITeam } from '../../ITeam'; import type { IMessage, IMessageFromServer } from '../../IMessage'; -import type { IRoom, IServerRoomItem } from '../../IRoom'; +import type { IServerRoom } from '../../IRoom'; import type { IUser } from '../../IUser'; export type GroupsEndpoints = { 'groups.files': { - GET: (params: { roomId: IRoom['_id']; count: number; sort: string | { uploadedAt: number }; query: string }) => { + GET: (params: { roomId: IServerRoom['_id']; count: number; sort: string | { uploadedAt: number }; query: string }) => { files: IMessage[]; total: number; }; }; 'groups.members': { - GET: (params: { roomId: IRoom['_id']; offset?: number; count?: number; filter?: string; status?: string[] }) => { + GET: (params: { roomId: IServerRoom['_id']; offset?: number; count?: number; filter?: string; status?: string[] }) => { count: number; offset: number; members: IUser[]; @@ -40,7 +40,7 @@ export type GroupsEndpoints = { teamId?: string; }; }) => { - group: Partial; + group: Partial; }; }; 'groups.convertToTeam': { diff --git a/app/definitions/rest/v1/im.ts b/app/definitions/rest/v1/im.ts index cdd46bd12..9b2de6c60 100644 --- a/app/definitions/rest/v1/im.ts +++ b/app/definitions/rest/v1/im.ts @@ -1,5 +1,5 @@ import type { IMessage, IMessageFromServer } from '../../IMessage'; -import type { IRoom } from '../../IRoom'; +import type { IServerRoom, RoomID, RoomType } from '../../IRoom'; import type { IUser } from '../../IUser'; export type ImEndpoints = { @@ -16,17 +16,22 @@ export type ImEndpoints = { excludeSelf?: boolean; } ) => { - room: IRoom; + room: { + t: RoomType; + rid: RoomID; + _id: RoomID; + usernames: IServerRoom['usernames']; + }; }; }; 'im.files': { - GET: (params: { roomId: IRoom['_id']; count: number; sort: string | { uploadedAt: number }; query: string }) => { + GET: (params: { roomId: IServerRoom['_id']; count: number; sort: string | { uploadedAt: number }; query: string }) => { files: IMessage[]; total: number; }; }; 'im.members': { - GET: (params: { roomId: IRoom['_id']; offset?: number; count?: number; filter?: string; status?: string[] }) => { + GET: (params: { roomId: IServerRoom['_id']; offset?: number; count?: number; filter?: string; status?: string[] }) => { count: number; offset: number; members: IUser[]; diff --git a/app/definitions/rest/v1/invites.ts b/app/definitions/rest/v1/invites.ts index 6682c9e32..e77791984 100644 --- a/app/definitions/rest/v1/invites.ts +++ b/app/definitions/rest/v1/invites.ts @@ -1,5 +1,5 @@ import type { IInvite } from '../../IInvite'; -import type { IRoom } from '../../IRoom'; +import type { IServerRoom } from '../../IRoom'; export type InvitesEndpoints = { listInvites: { @@ -11,11 +11,11 @@ export type InvitesEndpoints = { '/v1/useInviteToken': { POST: (params: { token: string }) => { room: { - rid: IRoom['_id']; - prid: IRoom['prid']; - fname: IRoom['fname']; - name: IRoom['name']; - t: IRoom['t']; + rid: IServerRoom['_id']; + prid: IServerRoom['prid']; + fname: IServerRoom['fname']; + name: IServerRoom['name']; + t: IServerRoom['t']; }; }; }; diff --git a/app/definitions/rest/v1/omnichannel.ts b/app/definitions/rest/v1/omnichannel.ts index 028b76d92..b18ea77a2 100644 --- a/app/definitions/rest/v1/omnichannel.ts +++ b/app/definitions/rest/v1/omnichannel.ts @@ -6,7 +6,7 @@ import { ILivechatMonitor } from '../../ILivechatMonitor'; import { ILivechatTag } from '../../ILivechatTag'; import { ILivechatVisitor, ILivechatVisitorDTO } from '../../ILivechatVisitor'; import { IMessage } from '../../IMessage'; -import { IOmnichannelRoom, IRoom } from '../../IRoom'; +import { IOmnichannelRoom, IServerRoom } from '../../IRoom'; import { ISetting } from '../../ISetting'; import { PaginatedRequest } from '../helpers/PaginatedRequest'; import { PaginatedResult } from '../helpers/PaginatedResult'; @@ -25,7 +25,7 @@ export type OmnichannelEndpoints = { }; }; 'livechat/room.onHold': { - POST: (params: { roomId: IRoom['_id'] }) => void; + POST: (params: { roomId: IServerRoom['_id'] }) => void; }; 'livechat/monitors.list': { GET: (params: PaginatedRequest<{ text: string }>) => PaginatedResult<{ diff --git a/app/definitions/rest/v1/rooms.ts b/app/definitions/rest/v1/rooms.ts index 8306cd68f..d4bb971bc 100644 --- a/app/definitions/rest/v1/rooms.ts +++ b/app/definitions/rest/v1/rooms.ts @@ -1,16 +1,16 @@ import type { IMessage } from '../../IMessage'; -import type { IRoom } from '../../IRoom'; +import type { IServerRoom } from '../../IRoom'; import type { IUser } from '../../IUser'; export type RoomsEndpoints = { 'rooms.autocomplete.channelAndPrivate': { GET: (params: { selector: string }) => { - items: IRoom[]; + items: IServerRoom[]; }; }; 'rooms.autocomplete.channelAndPrivate.withPagination': { GET: (params: { selector: string; offset?: number; count?: number; sort?: string }) => { - items: IRoom[]; + items: IServerRoom[]; count: number; offset: number; total: number; @@ -18,24 +18,24 @@ export type RoomsEndpoints = { }; 'rooms.autocomplete.availableForTeams': { GET: (params: { name: string }) => { - items: IRoom[]; + items: IServerRoom[]; }; }; 'rooms.info': { GET: (params: { roomId: string } | { roomName: string }) => { - room: IRoom; + room: IServerRoom; }; }; 'rooms.createDiscussion': { POST: (params: { - prid: IRoom['_id']; + prid: IServerRoom['_id']; pmid?: IMessage['_id']; - t_name: IRoom['fname']; + t_name: IServerRoom['fname']; users?: IUser['username'][]; encrypted?: boolean; reply?: string; }) => { - discussion: IRoom; + discussion: IServerRoom; }; }; 'rooms.favorite': { diff --git a/app/definitions/rest/v1/teams.ts b/app/definitions/rest/v1/teams.ts index e32c5252a..971b4abcb 100644 --- a/app/definitions/rest/v1/teams.ts +++ b/app/definitions/rest/v1/teams.ts @@ -1,13 +1,13 @@ -import { IRoom, IServerRoomItem } from '../../IRoom'; +import { IServerRoom } from '../../IRoom'; import { IServerTeamUpdateRoom, ITeam, TEAM_TYPE } from '../../ITeam'; export type TeamsEndpoints = { 'teams.removeRoom': { - POST: (params: { roomId: string; teamId: string }) => { room: IServerRoomItem }; + POST: (params: { roomId: string; teamId: string }) => { room: IServerRoom }; }; 'teams.listRoomsOfUser': { GET: (params: { teamId: string; userId: string }) => { - rooms: IServerRoomItem[]; + rooms: IServerRoom[]; total: number; count: number; offset: number; @@ -23,7 +23,7 @@ export type TeamsEndpoints = { POST: (params: { teamId: string; userId: string; rooms?: string[] }) => {}; }; 'teams.addRooms': { - POST: (params: { teamId: string; rooms: string[] }) => { rooms: IRoom[] }; + POST: (params: { teamId: string; rooms: string[] }) => { rooms: IServerRoom[] }; }; 'teams.create': { POST: (params: { diff --git a/app/lib/methods/canOpenRoom.ts b/app/lib/methods/canOpenRoom.ts index f9a567689..93f297180 100644 --- a/app/lib/methods/canOpenRoom.ts +++ b/app/lib/methods/canOpenRoom.ts @@ -20,8 +20,10 @@ async function open({ type, rid, name }: { type: ERoomTypes; rid: string; name: const result = await RocketChat.createDirectMessage(name); if (result.success) { const { room } = result; - room.rid = room._id as string; - return room; + return { + ...room, + rid: room._id + }; } } diff --git a/app/lib/methods/getRoomInfo.ts b/app/lib/methods/getRoomInfo.ts index ae2a87a48..142d59177 100644 --- a/app/lib/methods/getRoomInfo.ts +++ b/app/lib/methods/getRoomInfo.ts @@ -1,8 +1,15 @@ -import { IRoom, SubscriptionType } from '../../definitions'; +import { IServerSubscription, RoomType } from '../../definitions'; import { getSubscriptionByRoomId } from '../database/services/Subscription'; import RocketChat from '../rocketchat'; -const getRoomInfo = async (rid: string): Promise | null> => { +export interface IRoomInfoResult { + rid: IServerSubscription['rid']; + name: IServerSubscription['name']; + fname: IServerSubscription['fname']; + t: IServerSubscription['t']; +} + +const getRoomInfo = async (rid: string): Promise => { let result; result = await getSubscriptionByRoomId(rid); if (result) { @@ -10,7 +17,7 @@ const getRoomInfo = async (rid: string): Promise { +export default async (subscriptions: IServerSubscription[], rooms: IServerRoom[]) => { let sub = subscriptions; let room = rooms; try { @@ -59,7 +59,7 @@ export default async (subscriptions: IServerSubscriptionItem[], rooms: IServerRo avatarETag: s.avatarETag })); // Assign - sub = subscriptions.concat(mappedExistingSubs as unknown as IServerSubscriptionItem); + sub = subscriptions.concat(mappedExistingSubs as unknown as IServerSubscription); const subsIds = subscriptions.filter(s => !rooms.find(r => s.rid === r._id)).map(s => s._id); const existingRooms = await subCollection.query(Q.where('id', Q.oneOf(subsIds))).fetch(); @@ -89,7 +89,7 @@ export default async (subscriptions: IServerSubscriptionItem[], rooms: IServerRo avatarETag: r.avatarETag })); // Assign - room = rooms.concat(mappedExistingRooms as unknown as IServerRoomItem); + room = rooms.concat(mappedExistingRooms as unknown as IServerRoom); } catch { // do nothing } diff --git a/app/lib/methods/helpers/mergeSubscriptionsRooms.ts b/app/lib/methods/helpers/mergeSubscriptionsRooms.ts index da2485ee8..628546d4a 100644 --- a/app/lib/methods/helpers/mergeSubscriptionsRooms.ts +++ b/app/lib/methods/helpers/mergeSubscriptionsRooms.ts @@ -5,104 +5,105 @@ import { store as reduxStore } from '../../auxStore'; import { compareServerVersion } from '../../utils'; import findSubscriptionsRooms from './findSubscriptionsRooms'; import normalizeMessage from './normalizeMessage'; -import { - ISubscription, - IServerRoom, - IServerSubscription, - IServerSubscriptionItem, - IServerRoomItem, - IRoom -} from '../../../definitions'; -// TODO: delete and update +import { ISubscription, IServerSubscription, IServerRoom, IRoom } from '../../../definitions'; -export const merge = ( - subscription: ISubscription | IServerSubscriptionItem, - room?: ISubscription | IServerRoomItem | IRoom -): ISubscription => { +export const merge = (subscription: ISubscription | IServerSubscription, room?: IRoom | IServerRoom): ISubscription => { const serverVersion = reduxStore.getState().server.version as string; - subscription = EJSON.fromJSONValue(subscription) as ISubscription; + const mergedSubscription: ISubscription = EJSON.fromJSONValue(subscription); if (room) { - room = EJSON.fromJSONValue(room) as ISubscription; - if (room._updatedAt) { - subscription.lastMessage = normalizeMessage(room.lastMessage); - subscription.description = room.description; - subscription.topic = room.topic; - subscription.announcement = room.announcement; - subscription.reactWhenReadOnly = room.reactWhenReadOnly; - subscription.archived = room.archived || false; - subscription.joinCodeRequired = room.joinCodeRequired; - subscription.jitsiTimeout = room.jitsiTimeout; - subscription.usernames = room.usernames; - subscription.uids = room.uids; + room = EJSON.fromJSONValue(room); + if (room?._updatedAt) { + mergedSubscription.lastMessage = normalizeMessage(room.lastMessage); + mergedSubscription.description = room.description; + mergedSubscription.topic = room.topic; + mergedSubscription.announcement = room.announcement; + mergedSubscription.reactWhenReadOnly = room.reactWhenReadOnly; + mergedSubscription.archived = room.archived || false; + mergedSubscription.joinCodeRequired = room.joinCodeRequired; + mergedSubscription.jitsiTimeout = room.jitsiTimeout; + mergedSubscription.usernames = room.usernames; + mergedSubscription.uids = room.uids; } if (compareServerVersion(serverVersion, 'lowerThan', '3.7.0')) { const updatedAt = room?._updatedAt ? new Date(room._updatedAt) : null; + // @ts-ignore 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); + mergedSubscription.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; + const lastRoomUpdate = room?.lm || subscription.ts || subscription._updatedAt; // @ts-ignore Same as above scenario - subscription.roomUpdatedAt = subscription.lr + mergedSubscription.roomUpdatedAt = subscription.lr ? // @ts-ignore Same as above scenario Math.max(new Date(subscription.lr), new Date(lastRoomUpdate)) : lastRoomUpdate; } - subscription.ro = room.ro; - subscription.broadcast = room.broadcast; - subscription.encrypted = room.encrypted; - subscription.e2eKeyId = room.e2eKeyId; - subscription.avatarETag = room.avatarETag; - subscription.teamId = room.teamId; - subscription.teamMain = room.teamMain; - if (!subscription.roles || !subscription.roles.length) { - subscription.roles = []; + mergedSubscription.ro = room?.ro ?? false; + mergedSubscription.broadcast = room?.broadcast; + mergedSubscription.encrypted = room?.encrypted; + mergedSubscription.e2eKeyId = room?.e2eKeyId; + mergedSubscription.avatarETag = room?.avatarETag; + mergedSubscription.teamId = room?.teamId; + mergedSubscription.teamMain = room?.teamMain; + if (!mergedSubscription.roles || !mergedSubscription.roles.length) { + mergedSubscription.roles = []; } - if (!subscription.ignored?.length) { - subscription.ignored = []; + if (!mergedSubscription.ignored?.length) { + mergedSubscription.ignored = []; } - if (room.muted && room.muted.length) { - subscription.muted = room.muted.filter(muted => !!muted); + if (room?.muted?.length) { + mergedSubscription.muted = room.muted.filter(muted => !!muted); } else { - subscription.muted = []; + mergedSubscription.muted = []; } - if (room.v) { - subscription.visitor = room.v; + if (room?.v) { + mergedSubscription.visitor = room.v; } - if (room.departmentId) { - subscription.departmentId = room.departmentId; + if (room?.departmentId) { + mergedSubscription.departmentId = room.departmentId; } - if (room.servedBy) { - subscription.servedBy = room.servedBy; + if (room?.servedBy) { + mergedSubscription.servedBy = room.servedBy; } - if (room.livechatData) { - subscription.livechatData = room.livechatData; + if (room?.livechatData) { + mergedSubscription.livechatData = room.livechatData; } - if (room.tags) { - subscription.tags = room.tags; + if (room?.tags) { + mergedSubscription.tags = room.tags; } - subscription.sysMes = room.sysMes; + mergedSubscription.sysMes = room?.sysMes; } - if (!subscription.name) { - subscription.name = subscription.fname as string; + if (!mergedSubscription.name) { + mergedSubscription.name = mergedSubscription.fname as string; } - if (!subscription.autoTranslate) { - subscription.autoTranslate = false; + if (!mergedSubscription.autoTranslate) { + mergedSubscription.autoTranslate = false; } - subscription.blocker = !!subscription.blocker; - subscription.blocked = !!subscription.blocked; - return subscription; + mergedSubscription.blocker = !!mergedSubscription.blocker; + mergedSubscription.blocked = !!mergedSubscription.blocked; + return mergedSubscription; }; -export default async (serverSubscriptions: IServerSubscription, serverRooms: IServerRoom): Promise => { +export default async ( + serverSubscriptions: { + update: IServerSubscription[]; + remove: IServerSubscription[]; + success: boolean; + }, + serverRooms: { + update: IServerRoom[]; + remove: IServerRoom[]; + success: boolean; + } +): Promise => { const subscriptions = serverSubscriptions.update; const rooms = serverRooms.update; diff --git a/app/lib/methods/subscriptions/rooms.ts b/app/lib/methods/subscriptions/rooms.ts index 3e45b74c9..f6af324b9 100644 --- a/app/lib/methods/subscriptions/rooms.ts +++ b/app/lib/methods/subscriptions/rooms.ts @@ -21,6 +21,7 @@ import { E2E_MESSAGE_TYPE } from '../../encryption/constants'; import updateMessages from '../updateMessages'; import { IMessage, + IServerRoom, IRoom, ISubscription, TMessageModel, @@ -37,11 +38,11 @@ const removeListener = (listener: { stop: () => void }) => listener.stop(); let streamListener: Promise | false; let subServer: string; -let queue: { [key: string]: ISubscription } = {}; +let queue: { [key: string]: ISubscription | IRoom } = {}; let subTimer: number | null | false = null; const WINDOW_TIME = 500; -const createOrUpdateSubscription = async (subscription: ISubscription, room: IRoom | ISubscription) => { +const createOrUpdateSubscription = async (subscription: ISubscription, room: IServerRoom | IRoom) => { try { const db = database.active; const subCollection = db.get('subscriptions'); @@ -243,15 +244,15 @@ const debouncedUpdate = (subscription: ISubscription) => { InteractionManager.runAfterInteractions(() => { if (batch[key]) { if (/SUB/.test(key)) { - const sub = batch[key]; + const sub = batch[key] as ISubscription; const roomQueueId = getRoomQueueId(sub.rid); - const room = batch[roomQueueId]; + const room = batch[roomQueueId] as IRoom; delete batch[roomQueueId]; createOrUpdateSubscription(sub, room); } else { - const room = batch[key]; + const room = batch[key] as IRoom; const subQueueId = getSubQueueId(room._id); - const sub = batch[subQueueId]; + const sub = batch[subQueueId] as ISubscription; delete batch[subQueueId]; createOrUpdateSubscription(sub, room); } diff --git a/app/views/ForwardLivechatView.tsx b/app/views/ForwardLivechatView.tsx index 178e0767a..9361e45f5 100644 --- a/app/views/ForwardLivechatView.tsx +++ b/app/views/ForwardLivechatView.tsx @@ -7,7 +7,7 @@ import { forwardRoom, ITransferData } from '../actions/room'; import { themes } from '../constants/colors'; import OrSeparator from '../containers/OrSeparator'; import Input from '../containers/UIKit/MultiSelect/Input'; -import { IBaseScreen, IRoom } from '../definitions'; +import { IBaseScreen, IServerRoom } from '../definitions'; import I18n from '../i18n'; import RocketChat from '../lib/rocketchat'; import { ChatsStackParamList } from '../stacks/types'; @@ -34,7 +34,7 @@ const ForwardLivechatView = ({ navigation, route, theme }: IBaseScreen([]); const [userId, setUser] = useState(); - const [room, setRoom] = useState({} as IRoom); + const [room, setRoom] = useState({} as IServerRoom); const dispatch = useDispatch(); const rid = route.params?.rid; @@ -82,7 +82,7 @@ const ForwardLivechatView = ({ navigation, route, theme }: IBaseScreen { const { room } = this.state; if ('id' in room) { const { jitsiTimeout } = room; - if (jitsiTimeout && jitsiTimeout < Date.now()) { + if (jitsiTimeout && jitsiTimeout < new Date()) { showErrorAlert(I18n.t('Call_already_ended')); } else { RocketChat.callJitsi(room); diff --git a/app/views/SearchMessagesView/index.tsx b/app/views/SearchMessagesView/index.tsx index e41728711..417b240c8 100644 --- a/app/views/SearchMessagesView/index.tsx +++ b/app/views/SearchMessagesView/index.tsx @@ -27,12 +27,11 @@ import * as HeaderButton from '../../containers/HeaderButton'; import database from '../../lib/database'; import { sanitizeLikeString } from '../../lib/database/utils'; import getThreadName from '../../lib/methods/getThreadName'; -import getRoomInfo from '../../lib/methods/getRoomInfo'; +import getRoomInfo, { IRoomInfoResult } from '../../lib/methods/getRoomInfo'; import { isIOS } from '../../utils/deviceInfo'; import { compareServerVersion } from '../../lib/utils'; import styles from './styles'; import { InsideStackParamList, ChatsStackParamList } from '../../stacks/types'; -import { IRoom } from '../../definitions'; import { IEmoji } from '../../definitions/IEmoji'; const QUERY_SIZE = 50; @@ -82,7 +81,7 @@ class SearchMessagesView extends React.Component | null | undefined; + private room?: IRoomInfoResult; static navigationOptions = ({ navigation, route }: INavigationOption) => { const options: StackNavigationOptions = { @@ -109,7 +108,7 @@ class SearchMessagesView extends React.Component Date: Tue, 8 Mar 2022 14:09:45 -0300 Subject: [PATCH 2/3] Chore: Server API types - chat.getDiscussions (#3776) * chore: implementing type for test api - getDiscussions * Fix DiscussionDetails count usage * chore: update getDiscussions to use IMessageFromServer Co-authored-by: Diego Mello --- app/definitions/IMessage.ts | 4 ++++ app/definitions/rest/v1/chat.ts | 4 ++-- app/views/DiscussionsView/DiscussionDetails.tsx | 4 ++-- app/views/DiscussionsView/Item.tsx | 4 ++-- app/views/DiscussionsView/index.tsx | 10 +++++----- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/app/definitions/IMessage.ts b/app/definitions/IMessage.ts index 7085d1218..d836400f7 100644 --- a/app/definitions/IMessage.ts +++ b/app/definitions/IMessage.ts @@ -83,6 +83,10 @@ export interface IMessageFromServer { files?: IMessageFile[]; groupable?: boolean; attachments?: IAttachment[]; + t?: MessageType; + drid?: string; + dcount?: number; + dml: string | Date; } export interface ILoadMoreMessage { diff --git a/app/definitions/rest/v1/chat.ts b/app/definitions/rest/v1/chat.ts index 8481f78db..417d54a29 100644 --- a/app/definitions/rest/v1/chat.ts +++ b/app/definitions/rest/v1/chat.ts @@ -1,4 +1,4 @@ -import type { IMessage } from '../../IMessage'; +import type { IMessage, IMessageFromServer } from '../../IMessage'; import type { IServerRoom } from '../../IRoom'; import { PaginatedResult } from '../helpers/PaginatedResult'; @@ -31,7 +31,7 @@ export type ChatEndpoints = { }; 'chat.getDiscussions': { GET: (params: { roomId: IServerRoom['_id']; text?: string; offset: number; count: number }) => { - messages: IMessage[]; + messages: IMessageFromServer[]; total: number; }; }; diff --git a/app/views/DiscussionsView/DiscussionDetails.tsx b/app/views/DiscussionsView/DiscussionDetails.tsx index 06d245c81..9ef19bbe9 100644 --- a/app/views/DiscussionsView/DiscussionDetails.tsx +++ b/app/views/DiscussionsView/DiscussionDetails.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; -import { TThreadModel } from '../../definitions/IThread'; import { CustomIcon } from '../../lib/Icons'; import { themes } from '../../constants/colors'; import sharedStyles from '../Styles'; import { useTheme } from '../../theme'; +import { IMessageFromServer } from '../../definitions'; const styles = StyleSheet.create({ container: { @@ -31,7 +31,7 @@ const styles = StyleSheet.create({ }); interface IDiscussionDetails { - item: TThreadModel; + item: IMessageFromServer; date: string; } diff --git a/app/views/DiscussionsView/Item.tsx b/app/views/DiscussionsView/Item.tsx index 171f613b3..2fa90d185 100644 --- a/app/views/DiscussionsView/Item.tsx +++ b/app/views/DiscussionsView/Item.tsx @@ -10,7 +10,7 @@ import { themes } from '../../constants/colors'; import { MarkdownPreview } from '../../containers/markdown'; import { formatDateThreads, makeThreadName } from '../../utils/room'; import DiscussionDetails from './DiscussionDetails'; -import { TThreadModel } from '../../definitions/IThread'; +import { IMessageFromServer } from '../../definitions'; const styles = StyleSheet.create({ container: { @@ -48,7 +48,7 @@ const styles = StyleSheet.create({ }); interface IItem { - item: TThreadModel; + item: IMessageFromServer; onPress: { (...args: any[]): void; stop(): void; diff --git a/app/views/DiscussionsView/index.tsx b/app/views/DiscussionsView/index.tsx index 015701006..8a977a36e 100644 --- a/app/views/DiscussionsView/index.tsx +++ b/app/views/DiscussionsView/index.tsx @@ -5,7 +5,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { HeaderBackButton, StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack'; import { RouteProp } from '@react-navigation/core'; -import { IApplicationState } from '../../definitions'; +import { IApplicationState, IMessageFromServer } from '../../definitions'; import { ChatsStackParamList } from '../../stacks/types'; import ActivityIndicator from '../../containers/ActivityIndicator'; import I18n from '../../i18n'; @@ -47,8 +47,8 @@ const DiscussionsView = ({ navigation, route }: IDiscussionsViewProps): JSX.Elem const isMasterDetail = useSelector((state: IApplicationState) => state.app?.isMasterDetail); const [loading, setLoading] = useState(false); - const [discussions, setDiscussions] = useState([]); - const [search, setSearch] = useState([]); + const [discussions, setDiscussions] = useState([]); + const [search, setSearch] = useState([]); const [isSearching, setIsSearching] = useState(false); const [total, setTotal] = useState(0); const [searchTotal, setSearchTotal] = useState(0); @@ -63,7 +63,7 @@ const DiscussionsView = ({ navigation, route }: IDiscussionsViewProps): JSX.Elem setLoading(true); try { - const result: any = await RocketChat.getDiscussions({ + const result = await RocketChat.getDiscussions({ roomId: rid, offset: isSearching ? search.length : discussions.length, count: API_FETCH_COUNT, @@ -171,7 +171,7 @@ const DiscussionsView = ({ navigation, route }: IDiscussionsViewProps): JSX.Elem true ); - const renderItem = ({ item }: { item: TThreadModel }) => ( + const renderItem = ({ item }: { item: IMessageFromServer }) => ( Date: Tue, 8 Mar 2022 13:59:17 -0400 Subject: [PATCH 3/3] Chore: Migrate REST API - getTeamListRoom to TS (#3840) * add: `teams.listRooms` types * add: `PaginatedResult` to `teams.ts` --- app/definitions/rest/v1/teams.ts | 17 +++++++++++------ app/lib/rocketchat/services/restApi.ts | 4 +--- app/views/TeamChannelsView.tsx | 2 ++ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/app/definitions/rest/v1/teams.ts b/app/definitions/rest/v1/teams.ts index 971b4abcb..e282e630f 100644 --- a/app/definitions/rest/v1/teams.ts +++ b/app/definitions/rest/v1/teams.ts @@ -1,17 +1,13 @@ import { IServerRoom } from '../../IRoom'; import { IServerTeamUpdateRoom, ITeam, TEAM_TYPE } from '../../ITeam'; +import { PaginatedResult } from '../helpers/PaginatedResult'; export type TeamsEndpoints = { 'teams.removeRoom': { POST: (params: { roomId: string; teamId: string }) => { room: IServerRoom }; }; 'teams.listRoomsOfUser': { - GET: (params: { teamId: string; userId: string }) => { - rooms: IServerRoom[]; - total: number; - count: number; - offset: number; - }; + GET: (params: { teamId: string; userId: string }) => PaginatedResult<{ rooms: IServerRoom[] }>; }; 'teams.updateRoom': { POST: (params: { roomId: string; isDefault: boolean }) => { room: IServerTeamUpdateRoom }; @@ -33,4 +29,13 @@ export type TeamsEndpoints = { room: { readOnly: boolean; extraData: { broadcast: boolean; encrypted: boolean } }; }) => { team: ITeam }; }; + 'teams.listRooms': { + GET: (params: { + teamId: string; + count: number; + offset: number; + type: string; + filter?: any; + }) => PaginatedResult<{ rooms: IServerTeamUpdateRoom[] }>; + }; }; diff --git a/app/lib/rocketchat/services/restApi.ts b/app/lib/rocketchat/services/restApi.ts index e5a795b03..aa3e40142 100644 --- a/app/lib/rocketchat/services/restApi.ts +++ b/app/lib/rocketchat/services/restApi.ts @@ -319,7 +319,7 @@ export const getTeamListRoom = ({ offset: number; type: string; filter: any; -}): any => { +}) => { const params: any = { teamId, count, @@ -331,8 +331,6 @@ export const getTeamListRoom = ({ params.filter = filter; } // RC 3.13.0 - // TODO: missing definitions from server - // @ts-ignore return sdk.get('teams.listRooms', params); }; diff --git a/app/views/TeamChannelsView.tsx b/app/views/TeamChannelsView.tsx index a76c18ba8..5740f078d 100644 --- a/app/views/TeamChannelsView.tsx +++ b/app/views/TeamChannelsView.tsx @@ -187,8 +187,10 @@ class TeamChannelsView extends React.Component