diff --git a/apps/meteor/app/integrations/server/api/api.ts b/apps/meteor/app/integrations/server/api/api.ts index 7e72862f70588..15f664ab67fd9 100644 --- a/apps/meteor/app/integrations/server/api/api.ts +++ b/apps/meteor/app/integrations/server/api/api.ts @@ -48,7 +48,7 @@ type IntegrationThis = GenericRouteExecutionContext & { request: Request & { integration: IIncomingIntegration; }; - user: IUser & { username: RequiredField }; + user: RequiredField; }; async function createIntegration(options: IntegrationOptions, user: IUser): Promise { diff --git a/apps/meteor/app/integrations/server/lib/triggerHandler.ts b/apps/meteor/app/integrations/server/lib/triggerHandler.ts index 192419d6c2136..79886cf2770a2 100644 --- a/apps/meteor/app/integrations/server/lib/triggerHandler.ts +++ b/apps/meteor/app/integrations/server/lib/triggerHandler.ts @@ -181,7 +181,7 @@ class RocketChatIntegrationHandler { channel: tmpRoom.t === 'd' ? `@${tmpRoom._id}` : `#${tmpRoom._id}`, }; - return processWebhookMessage(message, user as IUser & { username: RequiredField }, defaultValues); + return processWebhookMessage(message, user as RequiredField, defaultValues); } eventNameArgumentsToObject(...args: unknown[]) { diff --git a/apps/meteor/app/lib/server/functions/processWebhookMessage.ts b/apps/meteor/app/lib/server/functions/processWebhookMessage.ts index 374cc091e0634..e3e9903a6527e 100644 --- a/apps/meteor/app/lib/server/functions/processWebhookMessage.ts +++ b/apps/meteor/app/lib/server/functions/processWebhookMessage.ts @@ -131,13 +131,13 @@ const buildMessage = (messageObj: Payload, defaultValues: DefaultValues) => { export function processWebhookMessage( messageObj: Payload & { separateResponse: true }, - user: IUser & { username: RequiredField }, + user: RequiredField, defaultValues?: DefaultValues, ): Promise; export function processWebhookMessage( messageObj: Payload & { separateResponse?: false | undefined }, - user: IUser & { username: RequiredField }, + user: RequiredField, defaultValues?: DefaultValues, ): Promise; @@ -148,7 +148,7 @@ export async function processWebhookMessage( */ separateResponse?: boolean; }, - user: IUser & { username: RequiredField }, + user: RequiredField, defaultValues: DefaultValues = { channel: '', alias: '', avatar: '', emoji: '' }, ) { const rooms: ({ channel: string } & ({ room: IRoom } | { room: IRoom | null; error?: any }))[] = []; diff --git a/apps/meteor/ee/server/apps/communication/uikit.ts b/apps/meteor/ee/server/apps/communication/uikit.ts index e5e851ef8f2b1..1dcd1c169d578 100644 --- a/apps/meteor/ee/server/apps/communication/uikit.ts +++ b/apps/meteor/ee/server/apps/communication/uikit.ts @@ -1,7 +1,6 @@ import { AppEvents, type IAppServerOrchestrator } from '@rocket.chat/apps'; -import type { UiKitCoreAppPayload } from '@rocket.chat/core-services'; import { UiKitCoreApp } from '@rocket.chat/core-services'; -import type { OperationParams, UrlParams } from '@rocket.chat/rest-typings'; +import type { OperationParams, OperationResult, UrlParams } from '@rocket.chat/rest-typings'; import bodyParser from 'body-parser'; import cors from 'cors'; import type { Request, Response } from 'express'; @@ -94,7 +93,7 @@ apiServer.use('/api/apps/ui.interaction/', bodyParser.json(), cors(corsOptions), type UiKitUserInteractionRequest = Request< UrlParams<'/apps/ui.interaction/:id'>, - any, + OperationResult<'POST', '/apps/ui.interaction/:id'> | { error: unknown }, OperationParams<'POST', '/apps/ui.interaction/:id'> & { visitor?: { id: string; @@ -111,81 +110,87 @@ type UiKitUserInteractionRequest = Request< } >; -const getCoreAppPayload = (req: UiKitUserInteractionRequest): UiKitCoreAppPayload => { +router.post('/:id', async (req: UiKitUserInteractionRequest, res, next) => { const { id: appId } = req.params; - if (req.body.type === 'blockAction') { - const { user } = req; - const { type, actionId, triggerId, payload, container, visitor } = req.body; - const message = 'mid' in req.body ? req.body.mid : undefined; - const room = 'rid' in req.body ? req.body.rid : undefined; - - return { - appId, - type, - actionId, - triggerId, - container, - message, - payload, - user, - visitor, - room, - }; + const isCoreApp = await UiKitCoreApp.isRegistered(appId); + if (!isCoreApp) { + return next(); } - if (req.body.type === 'viewClosed') { + try { const { user } = req; - const { - type, - payload: { view, isCleared }, - triggerId, - } = req.body; - - return { - appId, - triggerId, - type, - user, - payload: { - view, - isCleared, - }, - }; - } - if (req.body.type === 'viewSubmit') { - const { user } = req; - const { type, actionId, triggerId, payload } = req.body; - - return { - appId, - type, - actionId, - triggerId, - payload, - user, - }; - } + switch (req.body.type) { + case 'blockAction': { + const { type, actionId, triggerId, payload, container, visitor } = req.body; + const message = 'mid' in req.body ? req.body.mid : undefined; + const room = 'rid' in req.body ? req.body.rid : undefined; - throw new Error('Type not supported'); -}; + const result = await UiKitCoreApp.blockAction({ + appId, + type, + actionId, + triggerId, + container, + message, + payload, + user, + visitor, + room, + }); -router.post('/:id', async (req: UiKitUserInteractionRequest, res, next) => { - const { id: appId } = req.params; + // Using ?? to always send something in the response, even if the app had no result. + res.send(result ?? {}); - const isCoreApp = await UiKitCoreApp.isRegistered(appId); - if (!isCoreApp) { - return next(); - } + return; + } - try { - const payload = getCoreAppPayload(req); + case 'viewSubmit': { + const { type, actionId, triggerId, payload } = req.body; + + const result = await UiKitCoreApp.viewSubmit({ + appId, + type, + actionId, + triggerId, + payload, + user, + }); + + // Using ?? to always send something in the response, even if the app had no result. + res.send(result ?? {}); + + return; + } + + case 'viewClosed': { + const { + type, + payload: { view, isCleared }, + triggerId, + } = req.body; + + const result = await UiKitCoreApp.viewClosed({ + appId, + triggerId, + type, + user, + payload: { + view, + isCleared, + }, + }); + + // Using ?? to always send something in the response, even if the app had no result. + res.send(result ?? {}); - const result = await UiKitCoreApp[payload.type](payload); + return; + } - // Using ?? to always send something in the response, even if the app had no result. - res.send(result ?? {}); + default: + throw new Error('Type not supported'); + } } catch (e) { const error = e instanceof Error ? e.message : e; res.status(500).send({ error }); @@ -201,7 +206,10 @@ export class AppUIKitInteractionApi { router.post('/:id', this.routeHandler); } - private routeHandler = async (req: UiKitUserInteractionRequest, res: Response): Promise => { + private routeHandler = async ( + req: UiKitUserInteractionRequest, + res: Response | { error: unknown }>, + ): Promise => { const { orch } = this; const { id: appId } = req.params; diff --git a/apps/meteor/server/modules/core-apps/banner.module.ts b/apps/meteor/server/modules/core-apps/banner.module.ts index cf5bdebd50fe2..2af041134d065 100644 --- a/apps/meteor/server/modules/core-apps/banner.module.ts +++ b/apps/meteor/server/modules/core-apps/banner.module.ts @@ -1,12 +1,12 @@ import { Banner } from '@rocket.chat/core-services'; -import type { IUiKitCoreApp, UiKitCoreAppPayload } from '@rocket.chat/core-services'; +import type { IUiKitCoreApp, UiKitCoreAppViewClosedPayload } from '@rocket.chat/core-services'; import type * as UiKit from '@rocket.chat/ui-kit'; export class BannerModule implements IUiKitCoreApp { appId = 'banner-core'; // when banner view is closed we need to dismiss that banner for that user - async viewClosed(payload: UiKitCoreAppPayload): Promise { + async viewClosed(payload: UiKitCoreAppViewClosedPayload): Promise { const { payload: { view: { viewId: bannerId } = {} }, user: { _id: userId } = {}, diff --git a/apps/meteor/server/modules/core-apps/cloudAnnouncements.module.ts b/apps/meteor/server/modules/core-apps/cloudAnnouncements.module.ts index f13957b729813..00ce92c3b6fe1 100644 --- a/apps/meteor/server/modules/core-apps/cloudAnnouncements.module.ts +++ b/apps/meteor/server/modules/core-apps/cloudAnnouncements.module.ts @@ -1,5 +1,10 @@ import { Banner } from '@rocket.chat/core-services'; -import type { IUiKitCoreApp, UiKitCoreAppPayload } from '@rocket.chat/core-services'; +import type { + IUiKitCoreApp, + UiKitCoreAppBlockActionPayload, + UiKitCoreAppViewClosedPayload, + UiKitCoreAppViewSubmitPayload, +} from '@rocket.chat/core-services'; import type { Cloud, IUser } from '@rocket.chat/core-typings'; import { Banners } from '@rocket.chat/models'; import { serverFetch as fetch } from '@rocket.chat/server-fetch'; @@ -19,7 +24,7 @@ type CloudAnnouncementInteractant = user: Pick; } | { - visitor: Pick['visitor'], 'id' | 'username' | 'name' | 'department' | 'phone'>; + visitor: Pick, 'id' | 'username' | 'name' | 'department' | 'phone'>; }; type CloudAnnouncementInteractionRequest = UiKit.UserInteraction & CloudAnnouncementInteractant; @@ -35,15 +40,15 @@ export class CloudAnnouncementsModule implements IUiKitCoreApp { return settings.get('Cloud_Url'); } - blockAction(payload: UiKitCoreAppPayload): Promise { + blockAction(payload: UiKitCoreAppBlockActionPayload): Promise { return this.handlePayload(payload); } - viewSubmit(payload: UiKitCoreAppPayload): Promise { + viewSubmit(payload: UiKitCoreAppViewSubmitPayload): Promise { return this.handlePayload(payload); } - async viewClosed(payload: UiKitCoreAppPayload): Promise { + async viewClosed(payload: UiKitCoreAppViewClosedPayload): Promise { const { payload: { view: { viewId, id } = {} }, user: { _id: userId } = {}, @@ -86,7 +91,9 @@ export class CloudAnnouncementsModule implements IUiKitCoreApp { }; } - protected async handlePayload(payload: UiKitCoreAppPayload): Promise { + protected async handlePayload( + payload: UiKitCoreAppBlockActionPayload | UiKitCoreAppViewSubmitPayload | UiKitCoreAppViewClosedPayload, + ): Promise { const interactant = this.getInteractant(payload); const interaction = this.getInteraction(payload); @@ -104,10 +111,13 @@ export class CloudAnnouncementsModule implements IUiKitCoreApp { return serverInteraction; } catch (err) { SystemLogger.error({ err }); + return undefined; } } - protected getInteractant(payload: UiKitCoreAppPayload): CloudAnnouncementInteractant { + protected getInteractant( + payload: UiKitCoreAppBlockActionPayload | UiKitCoreAppViewSubmitPayload | UiKitCoreAppViewClosedPayload, + ): CloudAnnouncementInteractant { if (payload.user) { return { user: { @@ -118,7 +128,7 @@ export class CloudAnnouncementsModule implements IUiKitCoreApp { }; } - if (payload.visitor) { + if ('visitor' in payload && payload.visitor) { return { visitor: { id: payload.visitor.id, @@ -136,7 +146,9 @@ export class CloudAnnouncementsModule implements IUiKitCoreApp { /** * Transform the payload received from the Core App back to the format the UI sends from the client */ - protected getInteraction(payload: UiKitCoreAppPayload): UiKit.UserInteraction { + protected getInteraction( + payload: UiKitCoreAppBlockActionPayload | UiKitCoreAppViewSubmitPayload | UiKitCoreAppViewClosedPayload, + ): UiKit.UserInteraction { if (payload.type === 'blockAction' && payload.container?.type === 'message') { const { actionId, diff --git a/apps/meteor/server/modules/core-apps/cloudSubscriptionCommunication.module.ts b/apps/meteor/server/modules/core-apps/cloudSubscriptionCommunication.module.ts index e4b540416d4cc..37becfb041fab 100644 --- a/apps/meteor/server/modules/core-apps/cloudSubscriptionCommunication.module.ts +++ b/apps/meteor/server/modules/core-apps/cloudSubscriptionCommunication.module.ts @@ -1,4 +1,4 @@ -import type { UiKitCoreAppPayload } from '@rocket.chat/core-services'; +import type { UiKitCoreAppViewClosedPayload } from '@rocket.chat/core-services'; import type * as UiKit from '@rocket.chat/ui-kit'; import { CloudAnnouncementsModule } from './cloudAnnouncements.module'; @@ -6,7 +6,7 @@ import { CloudAnnouncementsModule } from './cloudAnnouncements.module'; export class CloudSubscriptionCommunication extends CloudAnnouncementsModule { override appId = 'cloud-communication-core'; - override async viewClosed(payload: UiKitCoreAppPayload): Promise { + override async viewClosed(payload: UiKitCoreAppViewClosedPayload): Promise { const { payload: { view: { viewId } = {} }, user: { _id: userId } = {}, diff --git a/apps/meteor/server/modules/core-apps/mention.module.ts b/apps/meteor/server/modules/core-apps/mention.module.ts index 8bd5bec4ce090..7d3785b4aaccd 100644 --- a/apps/meteor/server/modules/core-apps/mention.module.ts +++ b/apps/meteor/server/modules/core-apps/mention.module.ts @@ -1,6 +1,6 @@ import { api } from '@rocket.chat/core-services'; -import type { IUiKitCoreApp } from '@rocket.chat/core-services'; -import type { IMessage } from '@rocket.chat/core-typings'; +import type { IUiKitCoreApp, UiKitCoreAppBlockActionPayload } from '@rocket.chat/core-services'; +import type { IMessage, IUser } from '@rocket.chat/core-typings'; import { Subscriptions, Messages } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; @@ -24,13 +24,16 @@ const retrieveMentionsFromPayload = (stringifiedMentions: string): Exclude { + async blockAction(payload: UiKitCoreAppBlockActionPayload): Promise { const { actionId, payload: { value: stringifiedMentions, blockId: referenceMessageId }, } = payload; - const mentions = retrieveMentionsFromPayload(stringifiedMentions); + const user = payload.user!; + const room = payload.room!; + + const mentions = retrieveMentionsFromPayload(stringifiedMentions as string); const usernames = mentions.map(({ username }) => username); @@ -43,34 +46,34 @@ export class MentionModule implements IUiKitCoreApp { const joinedUsernames = `@${usernames.join(', @')}`; if (actionId === 'dismiss') { - void api.broadcast('notify.ephemeralMessage', payload.user._id, payload.room, { + void api.broadcast('notify.ephemeralMessage', user._id, room, { msg: i18n.t('You_mentioned___mentions__but_theyre_not_in_this_room', { mentions: joinedUsernames, - lng: payload.user.language, + lng: user.language, }), _id: payload.message, tmid: message.tmid, mentions, }); - return; + return undefined; } if (actionId === 'add-users') { - void addUsersToRoomMethod(payload.user._id, { rid: payload.room, users: usernames as string[] }, payload.user); - void api.broadcast('notify.ephemeralMessage', payload.user._id, payload.room, { + void addUsersToRoomMethod(user._id, { rid: room, users: usernames as string[] }, user); + void api.broadcast('notify.ephemeralMessage', user._id, room, { msg: i18n.t('You_mentioned___mentions__but_theyre_not_in_this_room', { mentions: joinedUsernames, - lng: payload.user.language, + lng: user.language, }), tmid: message.tmid, _id: payload.message, mentions, }); - return; + return undefined; } if (actionId === 'share-message') { - const sub = await Subscriptions.findOneByRoomIdAndUserId(payload.room, payload.user._id, { projection: { t: 1, rid: 1, name: 1 } }); + const sub = await Subscriptions.findOneByRoomIdAndUserId(room, user._id, { projection: { t: 1, rid: 1, name: 1 } }); // this should exist since the event is fired from withing the room (e.g the user sent a message) if (!sub) { throw new Error('Mention bot - Failed to retrieve room information'); @@ -83,7 +86,7 @@ export class MentionModule implements IUiKitCoreApp { const messageText = i18n.t('Youre_not_a_part_of__channel__and_I_mentioned_you_there', { channel: `#${sub.name}`, - lng: payload.user.language, + lng: user.language, }); const link = new URL(Meteor.absoluteUrl(roomPath)); @@ -97,18 +100,19 @@ export class MentionModule implements IUiKitCoreApp { text, separateResponse: true, // so that messages are sent to other DMs even if one or more fails }, - payload.user, + user as IUser & { username: string }, ); - void api.broadcast('notify.ephemeralMessage', payload.user._id, payload.room, { + void api.broadcast('notify.ephemeralMessage', user._id, room, { msg: i18n.t('You_mentioned___mentions__but_theyre_not_in_this_room_You_let_them_know_via_dm', { mentions: joinedUsernames, - lng: payload.user.language, + lng: user.language, }), tmid: message.tmid, _id: payload.message, mentions, }); + return undefined; } } } diff --git a/apps/meteor/server/modules/core-apps/nps.module.ts b/apps/meteor/server/modules/core-apps/nps.module.ts index 6e8965122df33..16e1763453f68 100644 --- a/apps/meteor/server/modules/core-apps/nps.module.ts +++ b/apps/meteor/server/modules/core-apps/nps.module.ts @@ -1,12 +1,13 @@ -import type { IUiKitCoreApp, UiKitCoreAppPayload } from '@rocket.chat/core-services'; +import type { IUiKitCoreApp, UiKitCoreAppBlockActionPayload, UiKitCoreAppViewSubmitPayload } from '@rocket.chat/core-services'; import { Banner, NPS } from '@rocket.chat/core-services'; +import type * as UiKit from '@rocket.chat/ui-kit'; import { createModal } from './nps/createModal'; export class Nps implements IUiKitCoreApp { appId = 'nps-core'; - async blockAction(payload: UiKitCoreAppPayload) { + async blockAction(payload: UiKitCoreAppBlockActionPayload): Promise { const { triggerId, actionId, @@ -32,7 +33,7 @@ export class Nps implements IUiKitCoreApp { }); } - async viewSubmit(payload: UiKitCoreAppPayload) { + async viewSubmit(payload: UiKitCoreAppViewSubmitPayload): Promise { if (!payload.payload?.view?.state || !payload.payload?.view?.id) { throw new Error('Invalid payload'); } @@ -65,7 +66,5 @@ export class Nps implements IUiKitCoreApp { } await Banner.dismiss(userId, bannerId); - - return true; } } diff --git a/apps/meteor/server/modules/core-apps/videoconf.module.ts b/apps/meteor/server/modules/core-apps/videoconf.module.ts index 694a0fac9b8e3..1f2765be0ce30 100644 --- a/apps/meteor/server/modules/core-apps/videoconf.module.ts +++ b/apps/meteor/server/modules/core-apps/videoconf.module.ts @@ -1,12 +1,13 @@ -import type { IUiKitCoreApp, UiKitCoreAppPayload } from '@rocket.chat/core-services'; +import type { IUiKitCoreApp, UiKitCoreAppBlockActionPayload } from '@rocket.chat/core-services'; import { VideoConf } from '@rocket.chat/core-services'; +import type * as UiKit from '@rocket.chat/ui-kit'; import { i18n } from '../../lib/i18n'; export class VideoConfModule implements IUiKitCoreApp { appId = 'videoconf-core'; - async blockAction(payload: UiKitCoreAppPayload) { + async blockAction(payload: UiKitCoreAppBlockActionPayload): Promise { const { triggerId, actionId, @@ -31,7 +32,6 @@ export class VideoConfModule implements IUiKitCoreApp { appId: this.appId, view: { appId: this.appId, - type: 'modal', id: `${callId}-info`, title: { type: 'plain_text', @@ -40,6 +40,8 @@ export class VideoConfModule implements IUiKitCoreApp { }, close: { type: 'button', + appId: this.appId, + blockId: callId, text: { type: 'plain_text', text: i18n.t('Close'), diff --git a/apps/meteor/server/services/uikit-core-app/service.ts b/apps/meteor/server/services/uikit-core-app/service.ts index a842a4854c6a3..7f07eb0a65fa6 100644 --- a/apps/meteor/server/services/uikit-core-app/service.ts +++ b/apps/meteor/server/services/uikit-core-app/service.ts @@ -1,5 +1,11 @@ import { ServiceClassInternal } from '@rocket.chat/core-services'; -import type { IUiKitCoreApp, IUiKitCoreAppService, UiKitCoreAppPayload } from '@rocket.chat/core-services'; +import type { + IUiKitCoreApp, + IUiKitCoreAppService, + UiKitCoreAppBlockActionPayload, + UiKitCoreAppViewClosedPayload, + UiKitCoreAppViewSubmitPayload, +} from '@rocket.chat/core-services'; const registeredApps = new Map(); @@ -24,29 +30,25 @@ export class UiKitCoreAppService extends ServiceClassInternal implements IUiKitC return registeredApps.has(appId); } - async blockAction(payload: UiKitCoreAppPayload) { + async blockAction(payload: UiKitCoreAppBlockActionPayload) { const { appId } = payload; const service = getAppModule(appId); - if (!service) { - return; - } + if (!service) return undefined; return service.blockAction?.(payload); } - async viewClosed(payload: UiKitCoreAppPayload) { + async viewClosed(payload: UiKitCoreAppViewClosedPayload) { const { appId } = payload; const service = getAppModule(appId); - if (!service) { - return; - } + if (!service) return undefined; return service.viewClosed?.(payload); } - async viewSubmit(payload: UiKitCoreAppPayload) { + async viewSubmit(payload: UiKitCoreAppViewSubmitPayload) { const { appId } = payload; const service = getAppModule(appId); diff --git a/apps/meteor/server/services/video-conference/service.ts b/apps/meteor/server/services/video-conference/service.ts index 1ea8c03f95c18..a5610b690f5de 100644 --- a/apps/meteor/server/services/video-conference/service.ts +++ b/apps/meteor/server/services/video-conference/service.ts @@ -172,7 +172,7 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf }); } - public async getInfo(callId: VideoConference['_id'], uid: IUser['_id'] | undefined): Promise { + public async getInfo(callId: VideoConference['_id'], uid: IUser['_id'] | undefined): Promise { const call = await VideoConferenceModel.findOneById(callId); if (!call) { throw new Error('invalid-call'); @@ -202,7 +202,7 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf }); if (blocks?.length) { - return blocks as UiKit.LayoutBlock[]; + return blocks as UiKit.ModalSurfaceLayout; } return [ diff --git a/packages/core-services/src/index.ts b/packages/core-services/src/index.ts index 817316a345b72..c0f2aeb517611 100644 --- a/packages/core-services/src/index.ts +++ b/packages/core-services/src/index.ts @@ -43,7 +43,13 @@ import type { IListRoomsFilter, } from './types/ITeamService'; import type { ITelemetryEvent, TelemetryMap, TelemetryEvents } from './types/ITelemetryEvent'; -import type { UiKitCoreAppPayload, IUiKitCoreApp, IUiKitCoreAppService } from './types/IUiKitCoreApp'; +import type { + UiKitCoreAppBlockActionPayload, + UiKitCoreAppViewClosedPayload, + UiKitCoreAppViewSubmitPayload, + IUiKitCoreApp, + IUiKitCoreAppService, +} from './types/IUiKitCoreApp'; import type { ISendFileLivechatMessageParams, ISendFileMessageParams, IUploadFileParams, IUploadService } from './types/IUploadService'; import type { IUserService } from './types/IUserService'; import type { IVideoConfService, VideoConferenceJoinOptions } from './types/IVideoConfService'; @@ -118,7 +124,9 @@ export { ITeamService, ITeamUpdateData, ITelemetryEvent, - UiKitCoreAppPayload, + UiKitCoreAppBlockActionPayload, + UiKitCoreAppViewClosedPayload, + UiKitCoreAppViewSubmitPayload, IUiKitCoreApp, IUiKitCoreAppService, IVideoConfService, diff --git a/packages/core-services/src/types/IUiKitCoreApp.ts b/packages/core-services/src/types/IUiKitCoreApp.ts index 5ba521b73642c..330fcbdff3e68 100644 --- a/packages/core-services/src/types/IUiKitCoreApp.ts +++ b/packages/core-services/src/types/IUiKitCoreApp.ts @@ -1,56 +1,61 @@ -import type { IUser } from '@rocket.chat/core-typings'; +import type { IMessage, IRoom, IUser } from '@rocket.chat/core-typings'; +import type * as UiKit from '@rocket.chat/ui-kit'; import type { IServiceClass } from './ServiceClass'; -// TODO: Fix this type to match `UiKit.UserInteraction` from `@rocket.chat/core-typings` -export type UiKitCoreAppPayload = { +export type UiKitCoreAppBlockActionPayload = Pick< + UiKit.ViewBlockActionUserInteraction | UiKit.MessageBlockActionUserInteraction, + 'type' | 'actionId' | 'triggerId' | 'container' | 'payload' +> & { appId: string; - type: 'blockAction' | 'viewClosed' | 'viewSubmit'; - actionId?: string; - triggerId?: string; - container?: { - id: string; - [key: string]: unknown; - }; - message?: unknown; + message: IMessage['_id'] | undefined; + user: IUser | undefined; + visitor: + | { + id: string; + username: string; + name?: string; + department?: string; + updatedAt?: Date; + token: string; + phone?: { phoneNumber: string }[] | null; + visitorEmails?: { address: string }[]; + livechatData?: Record; + status?: 'online' | 'away' | 'offline' | 'busy' | 'disabled'; + } + | undefined; + room: IRoom['_id'] | undefined; +}; + +export type UiKitCoreAppViewClosedPayload = Pick & { + appId: string; + user: IUser | undefined; payload: { - blockId?: string; - value?: unknown; - view?: { + view: UiKit.View & { viewId?: string; id?: string; - state?: { [blockId: string]: { [key: string]: unknown } }; - [key: string]: unknown; + state: { [blockId: string]: { [key: string]: unknown } }; }; - isCleared?: unknown; + isCleared?: boolean; }; - user?: IUser; - visitor?: { - id: string; - username: string; - name?: string; - department?: string; - updatedAt?: Date; - token: string; - phone?: { phoneNumber: string }[] | null; - visitorEmails?: { address: string }[]; - livechatData?: Record; - status?: 'online' | 'away' | 'offline' | 'busy' | 'disabled'; - }; - room?: unknown; +}; + +export type UiKitCoreAppViewSubmitPayload = Pick & { + appId: string; + user: IUser | undefined; }; export interface IUiKitCoreApp { appId: string; - blockAction?(payload: UiKitCoreAppPayload): Promise; - viewClosed?(payload: UiKitCoreAppPayload): Promise; - viewSubmit?(payload: UiKitCoreAppPayload): Promise; + blockAction?(payload: UiKitCoreAppBlockActionPayload): Promise; + viewClosed?(payload: UiKitCoreAppViewClosedPayload): Promise; + viewSubmit?(payload: UiKitCoreAppViewSubmitPayload): Promise; } export interface IUiKitCoreAppService extends IServiceClass { isRegistered(appId: string): Promise; - blockAction(payload: UiKitCoreAppPayload): Promise; - viewClosed(payload: UiKitCoreAppPayload): Promise; - viewSubmit(payload: UiKitCoreAppPayload): Promise; + blockAction(payload: UiKitCoreAppBlockActionPayload): Promise; + viewClosed(payload: UiKitCoreAppViewClosedPayload): Promise; + viewSubmit(payload: UiKitCoreAppViewSubmitPayload): Promise; } diff --git a/packages/core-services/src/types/IVideoConfService.ts b/packages/core-services/src/types/IVideoConfService.ts index 3c21db2f677b0..6d74413ccf211 100644 --- a/packages/core-services/src/types/IVideoConfService.ts +++ b/packages/core-services/src/types/IVideoConfService.ts @@ -21,7 +21,7 @@ export interface IVideoConfService { create(data: VideoConferenceCreateData, useAppUser?: boolean): Promise; start(caller: IUser['_id'], rid: string, options: { title?: string; allowRinging?: boolean }): Promise; join(uid: IUser['_id'] | undefined, callId: VideoConference['_id'], options: VideoConferenceJoinOptions): Promise; - getInfo(callId: VideoConference['_id'], uid: IUser['_id'] | undefined): Promise; + getInfo(callId: VideoConference['_id'], uid: IUser['_id'] | undefined): Promise; cancel(uid: IUser['_id'], callId: VideoConference['_id']): Promise; get(callId: VideoConference['_id']): Promise | null>; getUnfiltered(callId: VideoConference['_id']): Promise; diff --git a/packages/rest-typings/src/apps/index.ts b/packages/rest-typings/src/apps/index.ts index a012d251b9801..89d34deeb4bea 100644 --- a/packages/rest-typings/src/apps/index.ts +++ b/packages/rest-typings/src/apps/index.ts @@ -257,6 +257,6 @@ export type AppsEndpoints = { }; '/apps/ui.interaction/:id': { - POST: (params: UiKit.UserInteraction) => any; + POST: (params: UiKit.UserInteraction) => UiKit.ServerInteraction | Record; }; };