From 96051a1a24a95ca2b9d4b838ee2b500b68a310d7 Mon Sep 17 00:00:00 2001 From: Pierre Lehnen Date: Thu, 12 Feb 2026 18:33:47 -0300 Subject: [PATCH 01/51] feat: allow clients to accept calls before the session is established --- apps/meteor/app/api/server/index.ts | 1 + apps/meteor/app/api/server/v1/media-calls.ts | 99 +++++++++++++++++++ .../server/services/media-call/service.ts | 44 ++++++++- .../src/definition/IMediaCallServer.ts | 4 +- .../media-calls/src/definition/common.ts | 6 ++ .../src/internal/SignalProcessor.ts | 19 +++- .../internal/agents/CallSignalProcessor.ts | 38 +++++-- .../media-calls/src/server/MediaCallServer.ts | 15 +-- .../src/types/IMediaCallService.ts | 5 +- .../src/definition/call/IClientMediaCall.ts | 13 ++- .../src/definition/signals/client/answer.ts | 4 +- 11 files changed, 209 insertions(+), 39 deletions(-) create mode 100644 apps/meteor/app/api/server/v1/media-calls.ts diff --git a/apps/meteor/app/api/server/index.ts b/apps/meteor/app/api/server/index.ts index 59986d6e2da87..320ed4aea0deb 100644 --- a/apps/meteor/app/api/server/index.ts +++ b/apps/meteor/app/api/server/index.ts @@ -22,6 +22,7 @@ import './v1/integrations'; import './v1/invites'; import './v1/import'; import './v1/ldap'; +import './v1/media-calls'; import './v1/misc'; import './v1/permissions'; import './v1/presence'; diff --git a/apps/meteor/app/api/server/v1/media-calls.ts b/apps/meteor/app/api/server/v1/media-calls.ts new file mode 100644 index 0000000000000..9c3adb0cdf387 --- /dev/null +++ b/apps/meteor/app/api/server/v1/media-calls.ts @@ -0,0 +1,99 @@ +import { MediaCall } from '@rocket.chat/core-services'; +import type { IMediaCall } from '@rocket.chat/core-typings'; +import type { CallAnswer, CallFeature } from '@rocket.chat/media-signaling'; +import { callFeatureList, callAnswerList } from '@rocket.chat/media-signaling'; +import { + ajv, + validateNotFoundErrorResponse, + validateBadRequestErrorResponse, + validateUnauthorizedErrorResponse, + validateForbiddenErrorResponse, +} from '@rocket.chat/rest-typings'; +import type { JSONSchemaType } from 'ajv'; + +import type { ExtractRoutesFromAPI } from '../ApiClass'; +import { API } from '../api'; + +type MediaCallsAnswer = { + callId: string; + contractId: string; + + answer: CallAnswer; + + supportedFeatures?: CallFeature[]; +}; + +const MediaCallsAnswerSchema: JSONSchemaType = { + type: 'object', + properties: { + callId: { + type: 'string', + }, + contractId: { + type: 'string', + }, + answer: { + type: 'string', + enum: callAnswerList, + }, + supportedFeatures: { + type: 'array', + items: { + type: 'string', + enum: callFeatureList, + }, + nullable: true, + }, + }, + required: ['callId', 'contractId', 'answer'], + additionalProperties: false, +}; + +export const isMediaCallsAnswerProps = ajv.compile(MediaCallsAnswerSchema); + +const mediaCallsAnswerEndpoints = API.v1.post( + 'media-calls.answer', + { + response: { + 200: ajv.compile<{ + call: IMediaCall; + }>({ + additionalProperties: false, + type: 'object', + properties: { + call: { + type: 'object', + $ref: '#/components/schemas/IMediaCall', + description: 'The updated call information.', + nullable: true, + }, + success: { + type: 'boolean', + description: 'Indicates if the request was successful.', + }, + }, + required: ['call', 'success'], + }), + 400: validateBadRequestErrorResponse, + 401: validateUnauthorizedErrorResponse, + 403: validateForbiddenErrorResponse, + 404: validateNotFoundErrorResponse, + }, + body: isMediaCallsAnswerProps, + authRequired: true, + }, + async function action() { + const call = await MediaCall.answerCall(this.userId, this.bodyParams); + + return API.v1.success({ + call, + }); + }, +); + +type MediaCallsAnswerEndpoints = ExtractRoutesFromAPI; + +declare module '@rocket.chat/rest-typings' { + // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-empty-interface + interface Endpoints extends MediaCallsAnswerEndpoints {} +} diff --git a/apps/meteor/server/services/media-call/service.ts b/apps/meteor/server/services/media-call/service.ts index 6b1dd30b1e1e9..9edb93c5845f1 100644 --- a/apps/meteor/server/services/media-call/service.ts +++ b/apps/meteor/server/services/media-call/service.ts @@ -9,7 +9,8 @@ import type { } from '@rocket.chat/core-typings'; import { Logger } from '@rocket.chat/logger'; import { callServer, type IMediaCallServerSettings } from '@rocket.chat/media-calls'; -import { isClientMediaSignal, type ClientMediaSignal, type ServerMediaSignal } from '@rocket.chat/media-signaling'; +import type { ClientMediaSignal, ServerMediaSignal, ClientMediaSignalAnswer } from '@rocket.chat/media-signaling'; +import { isClientMediaSignal } from '@rocket.chat/media-signaling'; import type { InsertionModel } from '@rocket.chat/model-typings'; import { CallHistory, MediaCalls, Rooms, Users } from '@rocket.chat/models'; import { getHistoryMessagePayload } from '@rocket.chat/ui-voip/dist/ui-kit/getHistoryMessagePayload'; @@ -39,21 +40,56 @@ export class MediaCallService extends ServiceClassInternal implements IMediaCall this.configureMediaCallServer(); } + public async answerCall(uid: IUser['_id'], params: Omit): Promise { + const { callId } = params; + + const call = await MediaCalls.findOneById>(callId, { + projection: { callee: 1, acceptedAt: 1 }, + }); + if (!call || call.callee.type !== 'user' || call.callee.id !== uid) { + throw new Error('not-found'); + } + + const signal: ClientMediaSignalAnswer = { + type: 'answer', + ...params, + }; + + await callServer.receiveSignal(uid, signal, { throwIfSkipped: true }); + + const updatedCall = await MediaCalls.findOneById(callId); + if (!updatedCall) { + throw new Error('internal-error'); + } + + if (updatedCall.callee.contractId !== signal.contractId) { + if (updatedCall.callee.contractId) { + throw new Error('invalid-call-state'); + } + throw new Error('internal-error'); + } + + return updatedCall; + } + public async processSignal(uid: IUser['_id'], signal: ClientMediaSignal): Promise { try { - callServer.receiveSignal(uid, signal); + await callServer.receiveSignal(uid, signal); } catch (err) { logger.error({ msg: 'failed to process client signal', err, signal, uid }); } } public async processSerializedSignal(uid: IUser['_id'], signal: string): Promise { + let signalType: string | null = null; + try { const deserialized = await this.deserializeClientSignal(signal); + signalType = deserialized.type; - callServer.receiveSignal(uid, deserialized); + await callServer.receiveSignal(uid, deserialized); } catch (err) { - logger.error({ msg: 'failed to process client signal', err, uid }); + logger.error({ msg: 'failed to process client signal', err, uid, type: signalType }); } } diff --git a/ee/packages/media-calls/src/definition/IMediaCallServer.ts b/ee/packages/media-calls/src/definition/IMediaCallServer.ts index ba1994f6f2697..ed59484e0eaa4 100644 --- a/ee/packages/media-calls/src/definition/IMediaCallServer.ts +++ b/ee/packages/media-calls/src/definition/IMediaCallServer.ts @@ -2,7 +2,7 @@ import type { IUser } from '@rocket.chat/core-typings'; import type { Emitter } from '@rocket.chat/emitter'; import type { ClientMediaSignal, ClientMediaSignalBody, ServerMediaSignal } from '@rocket.chat/media-signaling'; -import type { InternalCallParams } from './common'; +import type { InternalCallParams, SignalProcessingOptions } from './common'; export type MediaCallServerEvents = { callUpdated: { callId: string; dtmf?: ClientMediaSignalBody<'dtmf'> }; @@ -41,7 +41,7 @@ export interface IMediaCallServer { updateCallHistory(params: { callId: string }): void; // functions that are run on events - receiveSignal(fromUid: IUser['_id'], signal: ClientMediaSignal): void; + receiveSignal(fromUid: IUser['_id'], signal: ClientMediaSignal, options?: SignalProcessingOptions): Promise; receiveCallUpdate(params: { callId: string; dtmf?: ClientMediaSignalBody<'dtmf'> }): void; // extra functions available to the service diff --git a/ee/packages/media-calls/src/definition/common.ts b/ee/packages/media-calls/src/definition/common.ts index cb0af26822ffa..46616a1a6914e 100644 --- a/ee/packages/media-calls/src/definition/common.ts +++ b/ee/packages/media-calls/src/definition/common.ts @@ -28,3 +28,9 @@ export class CallRejectedError extends Error { super(message || 'call-rejected'); } } + +export type SignalProcessingOptions = { + // Some signals can be safely skipped when they are not relevant to the current call state, but + // if the signal was received via REST, we shouldn't return success without processing anything, so we throw an error instead + throwIfSkipped?: boolean; +}; diff --git a/ee/packages/media-calls/src/internal/SignalProcessor.ts b/ee/packages/media-calls/src/internal/SignalProcessor.ts index 19a0e9f619330..1a6f7f3542ee8 100644 --- a/ee/packages/media-calls/src/internal/SignalProcessor.ts +++ b/ee/packages/media-calls/src/internal/SignalProcessor.ts @@ -10,7 +10,7 @@ import type { } from '@rocket.chat/media-signaling'; import { MediaCalls } from '@rocket.chat/models'; -import type { InternalCallParams } from '../definition/common'; +import type { InternalCallParams, SignalProcessingOptions } from '../definition/common'; import { logger } from '../logger'; import { mediaCallDirector } from '../server/CallDirector'; import { UserActorAgent } from './agents/UserActorAgent'; @@ -29,7 +29,7 @@ export class GlobalSignalProcessor { this.emitter = new Emitter(); } - public async processSignal(uid: IUser['_id'], signal: ClientMediaSignal): Promise { + public async processSignal(uid: IUser['_id'], signal: ClientMediaSignal, options: SignalProcessingOptions): Promise { switch (signal.type) { case 'register': return this.processRegisterSignal(uid, signal); @@ -38,7 +38,7 @@ export class GlobalSignalProcessor { } if ('callId' in signal) { - return this.processCallSignal(uid, signal); + return this.processCallSignal(uid, signal, options); } logger.error({ msg: 'Unrecognized media signal', signal: stripSensitiveDataFromSignal(signal) }); @@ -55,6 +55,7 @@ export class GlobalSignalProcessor { private async processCallSignal( uid: IUser['_id'], signal: Exclude, + { throwIfSkipped }: SignalProcessingOptions, ): Promise { try { const call = await MediaCalls.findOneById(signal.callId); @@ -90,6 +91,9 @@ export class GlobalSignalProcessor { // Ignore signals from different sessions if the actor is already signed if (!skipContractCheck && callActor.contractId && callActor.contractId !== signal.contractId) { + if (throwIfSkipped) { + throw new Error('invalid-contract'); + } return; } @@ -99,7 +103,14 @@ export class GlobalSignalProcessor { const { [role]: agent } = agents; if (!(agent instanceof UserActorAgent)) { - throw new Error('Actor agent is not prepared to process signals'); + logger.error({ + msg: 'Actor agent is not prepared to process signals', + method: 'processSignal', + signal: stripSensitiveDataFromSignal(signal), + isCaller, + isCallee, + }); + throw new Error('internal-error'); } await agent.processSignal(call, signal); diff --git a/ee/packages/media-calls/src/internal/agents/CallSignalProcessor.ts b/ee/packages/media-calls/src/internal/agents/CallSignalProcessor.ts index 57d40fbb9e713..61d46bccf815b 100644 --- a/ee/packages/media-calls/src/internal/agents/CallSignalProcessor.ts +++ b/ee/packages/media-calls/src/internal/agents/CallSignalProcessor.ts @@ -20,6 +20,7 @@ import type { import { MediaCallChannels, MediaCallNegotiations, MediaCalls } from '@rocket.chat/models'; import type { IMediaCallAgent } from '../../definition/IMediaCallAgent'; +import type { SignalProcessingOptions } from '../../definition/common'; import { logger } from '../../logger'; import { mediaCallDirector } from '../../server/CallDirector'; import { getMediaCallServer } from '../../server/injection'; @@ -58,6 +59,8 @@ export class UserActorSignalProcessor { public readonly ignored: boolean; + private throwIfSkipped: boolean; + constructor( protected readonly agent: IMediaCallAgent, protected readonly call: IMediaCall, @@ -67,6 +70,7 @@ export class UserActorSignalProcessor { this.signed = Boolean(actor.contractId && actor.contractId === channel.contractId); this.ignored = Boolean(actor.contractId && actor.contractId !== channel.contractId); + this.throwIfSkipped = false; } public async requestWebRTCOffer(params: { negotiationId: string }): Promise { @@ -80,7 +84,7 @@ export class UserActorSignalProcessor { }); } - public async processSignal(signal: ClientMediaSignal): Promise { + public async processSignal(signal: ClientMediaSignal, options: SignalProcessingOptions = {}): Promise { if (signal.type !== 'local-state') { logger.debug({ msg: 'UserActorSignalProcessor.processSignal', @@ -90,6 +94,8 @@ export class UserActorSignalProcessor { }); } + this.throwIfSkipped = options.throwIfSkipped || false; + // The code will only reach this point if one of the following conditions are true: // 1. the signal came from the exact user session where the caller initiated the call // 2. the signal came from the exact user session where the callee accepted the call @@ -290,13 +296,11 @@ export class UserActorSignalProcessor { } protected async clientHasRejected(): Promise { - if (!this.isCallPending()) { + if (!this.validatePendingCallee()) { return; } - if (this.role === 'callee') { - return mediaCallDirector.hangup(this.call, this.agent, 'rejected'); - } + return mediaCallDirector.hangup(this.call, this.agent, 'rejected'); } protected async clientIsUnavailable(): Promise { @@ -309,13 +313,11 @@ export class UserActorSignalProcessor { } protected async clientHasAccepted(supportedFeatures: CallFeature[]): Promise { - if (!this.isCallPending()) { + if (!this.validatePendingCallee()) { return; } - if (this.role === 'callee') { - await mediaCallDirector.acceptCall(this.call, this.agent, { calleeContractId: this.contractId, supportedFeatures }); - } + await mediaCallDirector.acceptCall(this.call, this.agent, { calleeContractId: this.contractId, supportedFeatures }); } protected async clientIsActive(): Promise { @@ -338,6 +340,24 @@ export class UserActorSignalProcessor { return ['active', 'hangup'].includes(this.call.state); } + protected validatePendingCallee(): boolean { + if (this.role !== 'callee') { + if (this.throwIfSkipped) { + throw new Error('invalid-call-role'); + } + return false; + } + + if (!this.isCallPending()) { + if (this.throwIfSkipped) { + throw new Error('invalid-call-state'); + } + return false; + } + + return true; + } + private async reviewLocalState(signal: ClientMediaSignalLocalState): Promise { if (!this.signed) { return; diff --git a/ee/packages/media-calls/src/server/MediaCallServer.ts b/ee/packages/media-calls/src/server/MediaCallServer.ts index e6dcc4dc90465..dc43786a939b4 100644 --- a/ee/packages/media-calls/src/server/MediaCallServer.ts +++ b/ee/packages/media-calls/src/server/MediaCallServer.ts @@ -1,13 +1,13 @@ import type { IUser } from '@rocket.chat/core-typings'; import { Emitter } from '@rocket.chat/emitter'; -import { isClientMediaSignal } from '@rocket.chat/media-signaling'; import type { CallRejectedReason, ClientMediaSignal, ClientMediaSignalBody, ServerMediaSignal } from '@rocket.chat/media-signaling'; import { mediaCallDirector } from './CallDirector'; import { getDefaultSettings } from './getDefaultSettings'; import { stripSensitiveDataFromSignal } from './stripSensitiveData'; import type { IMediaCallServer, IMediaCallServerSettings, MediaCallServerEvents } from '../definition/IMediaCallServer'; -import { CallRejectedError, type GetActorContactOptions, type InternalCallParams } from '../definition/common'; +import { CallRejectedError } from '../definition/common'; +import type { SignalProcessingOptions, GetActorContactOptions, InternalCallParams } from '../definition/common'; import { InternalCallProvider } from '../internal/InternalCallProvider'; import { GlobalSignalProcessor } from '../internal/SignalProcessor'; import { logger } from '../logger'; @@ -41,15 +41,8 @@ export class MediaCallServer implements IMediaCallServer { }); } - public receiveSignal(fromUid: IUser['_id'], signal: ClientMediaSignal): void { - if (!isClientMediaSignal(signal)) { - logger.error({ msg: 'The Media Signal Server received an invalid client signal object' }); - throw new Error('invalid-signal'); - } - - this.signalProcessor.processSignal(fromUid, signal).catch((err) => { - logger.error({ msg: 'Failed to process client signal', err, type: signal.type }); - }); + public async receiveSignal(fromUid: IUser['_id'], signal: ClientMediaSignal, options: SignalProcessingOptions = {}): Promise { + return this.signalProcessor.processSignal(fromUid, signal, options); } public sendSignal(toUid: IUser['_id'], signal: ServerMediaSignal): void { diff --git a/packages/core-services/src/types/IMediaCallService.ts b/packages/core-services/src/types/IMediaCallService.ts index a00e76a034d82..dcd7004937bf8 100644 --- a/packages/core-services/src/types/IMediaCallService.ts +++ b/packages/core-services/src/types/IMediaCallService.ts @@ -1,7 +1,8 @@ -import type { IUser } from '@rocket.chat/core-typings'; -import type { ClientMediaSignal } from '@rocket.chat/media-signaling'; +import type { IMediaCall, IUser } from '@rocket.chat/core-typings'; +import type { ClientMediaSignal, ClientMediaSignalAnswer } from '@rocket.chat/media-signaling'; export interface IMediaCallService { + answerCall(uid: IUser['_id'], params: Omit): Promise; processSignal(fromUid: IUser['_id'], signal: ClientMediaSignal): Promise; processSerializedSignal(fromUid: IUser['_id'], signal: string): Promise; hangupExpiredCalls(): Promise; diff --git a/packages/media-signaling/src/definition/call/IClientMediaCall.ts b/packages/media-signaling/src/definition/call/IClientMediaCall.ts index e96be078b6859..35985ec2adda1 100644 --- a/packages/media-signaling/src/definition/call/IClientMediaCall.ts +++ b/packages/media-signaling/src/definition/call/IClientMediaCall.ts @@ -50,11 +50,14 @@ export type CallHangupReason = | 'unknown' // One of the call's signed users reported they don't know this call | 'another-client'; // One of the call's users requested a hangup from a different client session than the one where the call is happening -export type CallAnswer = - | 'accept' // actor accepts the call - | 'reject' // actor rejects the call - | 'ack' // agent confirms the actor is reachable - | 'unavailable'; // agent reports the actor is unavailable +export const callAnswerList = [ + 'accept', // actor accepts the call + 'reject', // actor rejects the call + 'ack', // agent confirms the actor is reachable + 'unavailable', // agent reports the actor is unavailable +] as const; + +export type CallAnswer = (typeof callAnswerList)[number]; export type CallNotification = | 'accepted' // notify that the call has been accepted by both actors diff --git a/packages/media-signaling/src/definition/signals/client/answer.ts b/packages/media-signaling/src/definition/signals/client/answer.ts index 9b14771a1cda3..c48d7f90ada07 100644 --- a/packages/media-signaling/src/definition/signals/client/answer.ts +++ b/packages/media-signaling/src/definition/signals/client/answer.ts @@ -1,7 +1,7 @@ import type { JSONSchemaType } from 'ajv'; import type { CallAnswer, CallFeature } from '../../call'; -import { callFeatureList } from '../../call/IClientMediaCall'; +import { callAnswerList, callFeatureList } from '../../call/IClientMediaCall'; /** Client is saying that the user accepted or rejected a call, or simply reporting that the user can or can't be reached */ export type ClientMediaSignalAnswer = { @@ -33,7 +33,7 @@ export const clientMediaSignalAnswerSchema: JSONSchemaType Date: Mon, 16 Feb 2026 16:22:55 -0300 Subject: [PATCH 02/51] cleanup --- apps/meteor/app/api/server/v1/media-calls.ts | 1 - apps/meteor/server/services/media-call/service.ts | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/meteor/app/api/server/v1/media-calls.ts b/apps/meteor/app/api/server/v1/media-calls.ts index 9c3adb0cdf387..9d6e0bde77d84 100644 --- a/apps/meteor/app/api/server/v1/media-calls.ts +++ b/apps/meteor/app/api/server/v1/media-calls.ts @@ -65,7 +65,6 @@ const mediaCallsAnswerEndpoints = API.v1.post( type: 'object', $ref: '#/components/schemas/IMediaCall', description: 'The updated call information.', - nullable: true, }, success: { type: 'boolean', diff --git a/apps/meteor/server/services/media-call/service.ts b/apps/meteor/server/services/media-call/service.ts index 9edb93c5845f1..0f914ad4acc54 100644 --- a/apps/meteor/server/services/media-call/service.ts +++ b/apps/meteor/server/services/media-call/service.ts @@ -43,8 +43,8 @@ export class MediaCallService extends ServiceClassInternal implements IMediaCall public async answerCall(uid: IUser['_id'], params: Omit): Promise { const { callId } = params; - const call = await MediaCalls.findOneById>(callId, { - projection: { callee: 1, acceptedAt: 1 }, + const call = await MediaCalls.findOneById>(callId, { + projection: { callee: 1 }, }); if (!call || call.callee.type !== 'user' || call.callee.id !== uid) { throw new Error('not-found'); From 7f15e37c46621178443a2dd896df08cd68079660 Mon Sep 17 00:00:00 2001 From: Pierre Lehnen Date: Thu, 26 Feb 2026 13:20:59 -0300 Subject: [PATCH 03/51] use query to validate callee --- .../server/services/media-call/service.ts | 10 ++++++---- .../src/models/IMediaCallsModel.ts | 14 +++++++++++++- packages/models/src/models/MediaCalls.ts | 17 +++++++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/apps/meteor/server/services/media-call/service.ts b/apps/meteor/server/services/media-call/service.ts index 0f914ad4acc54..9ed8c6c2dd6d7 100644 --- a/apps/meteor/server/services/media-call/service.ts +++ b/apps/meteor/server/services/media-call/service.ts @@ -43,10 +43,12 @@ export class MediaCallService extends ServiceClassInternal implements IMediaCall public async answerCall(uid: IUser['_id'], params: Omit): Promise { const { callId } = params; - const call = await MediaCalls.findOneById>(callId, { - projection: { callee: 1 }, - }); - if (!call || call.callee.type !== 'user' || call.callee.id !== uid) { + const call = await MediaCalls.findOneByIdAndCallee>( + callId, + { type: 'user', id: uid }, + { projection: { _id: 1 } }, + ); + if (!call) { throw new Error('not-found'); } diff --git a/packages/model-typings/src/models/IMediaCallsModel.ts b/packages/model-typings/src/models/IMediaCallsModel.ts index a290fc73c3f33..2221a5335d226 100644 --- a/packages/model-typings/src/models/IMediaCallsModel.ts +++ b/packages/model-typings/src/models/IMediaCallsModel.ts @@ -1,9 +1,21 @@ -import type { IMediaCall, IUser, MediaCallActorType, MediaCallContact, MediaCallSignedContact } from '@rocket.chat/core-typings'; +import type { + IMediaCall, + IUser, + MediaCallActor, + MediaCallActorType, + MediaCallContact, + MediaCallSignedContact, +} from '@rocket.chat/core-typings'; import type { Document, FindCursor, FindOptions, UpdateResult } from 'mongodb'; import type { IBaseModel } from './IBaseModel'; export interface IMediaCallsModel extends IBaseModel { + findOneByIdAndCallee( + id: IMediaCall['_id'], + callee: MediaCallActor, + options?: FindOptions, + ): Promise; findOneByCallerRequestedId( id: Required['callerRequestedId'], caller: { type: MediaCallActorType; id: string }, diff --git a/packages/models/src/models/MediaCalls.ts b/packages/models/src/models/MediaCalls.ts index ab02a344fb91f..858ea9a9680ec 100644 --- a/packages/models/src/models/MediaCalls.ts +++ b/packages/models/src/models/MediaCalls.ts @@ -5,6 +5,7 @@ import type { MediaCallSignedContact, MediaCallContact, IUser, + MediaCallActor, } from '@rocket.chat/core-typings'; import type { IMediaCallsModel } from '@rocket.chat/model-typings'; import type { @@ -37,6 +38,22 @@ export class MediaCallsRaw extends BaseRaw implements IMediaCallsMod ]; } + public async findOneByIdAndCallee( + id: IMediaCall['_id'], + callee: MediaCallActor, + options?: FindOptions, + ): Promise { + return this.findOne( + { + '_id': id, + 'callee.type': callee.type, + 'callee.id': callee.id, + ...(callee.contractId && { 'callee.contractId': callee.contractId }), + }, + options, + ); + } + public async findOneByCallerRequestedId( id: Required['callerRequestedId'], caller: { type: MediaCallActorType; id: string }, From 57d51634cb512b6221678d30eb48d6cf49a4bf43 Mon Sep 17 00:00:00 2001 From: Pierre Lehnen Date: Thu, 26 Feb 2026 13:28:22 -0300 Subject: [PATCH 04/51] changeset --- .changeset/fair-lions-smell.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/fair-lions-smell.md diff --git a/.changeset/fair-lions-smell.md b/.changeset/fair-lions-smell.md new file mode 100644 index 0000000000000..403b673842ee0 --- /dev/null +++ b/.changeset/fair-lions-smell.md @@ -0,0 +1,10 @@ +--- +'@rocket.chat/media-calls': minor +'@rocket.chat/core-services': minor +'@rocket.chat/model-typings': minor +'@rocket.chat/models': minor +'@rocket.chat/meteor': minor +'@rocket.chat/media-signaling': minor +--- + +Adds a new REST endpoint to accept or reject media calls without an active media session From 6c3ae5d2d5e753bf5e8e39dd74e6cd8e08ab25f4 Mon Sep 17 00:00:00 2001 From: Pierre Lehnen Date: Mon, 16 Mar 2026 12:31:14 -0300 Subject: [PATCH 05/51] handle ack invalid state --- .../server/services/media-call/service.ts | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/meteor/server/services/media-call/service.ts b/apps/meteor/server/services/media-call/service.ts index 9ed8c6c2dd6d7..f048be327ce57 100644 --- a/apps/meteor/server/services/media-call/service.ts +++ b/apps/meteor/server/services/media-call/service.ts @@ -41,7 +41,7 @@ export class MediaCallService extends ServiceClassInternal implements IMediaCall } public async answerCall(uid: IUser['_id'], params: Omit): Promise { - const { callId } = params; + const { callId, answer } = params; const call = await MediaCalls.findOneByIdAndCallee>( callId, @@ -64,11 +64,22 @@ export class MediaCallService extends ServiceClassInternal implements IMediaCall throw new Error('internal-error'); } - if (updatedCall.callee.contractId !== signal.contractId) { - if (updatedCall.callee.contractId) { - throw new Error('invalid-call-state'); - } - throw new Error('internal-error'); + switch (answer) { + case 'ack': + if (updatedCall.acceptedAt || updatedCall.ended) { + throw new Error('invalid-call-state'); + } + break; + case 'unavailable': + break; + default: + if (updatedCall.callee.contractId !== signal.contractId) { + if (updatedCall.callee.contractId) { + throw new Error('invalid-call-state'); + } + throw new Error('internal-error'); + } + break; } return updatedCall; From bbd36e2037ff585a4dbd5d1fb95e9bc226199661 Mon Sep 17 00:00:00 2001 From: Pierre Lehnen Date: Mon, 16 Mar 2026 13:08:56 -0300 Subject: [PATCH 06/51] handle reject validations --- apps/meteor/server/services/media-call/service.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/meteor/server/services/media-call/service.ts b/apps/meteor/server/services/media-call/service.ts index f048be327ce57..3f91264cc17c3 100644 --- a/apps/meteor/server/services/media-call/service.ts +++ b/apps/meteor/server/services/media-call/service.ts @@ -70,9 +70,12 @@ export class MediaCallService extends ServiceClassInternal implements IMediaCall throw new Error('invalid-call-state'); } break; - case 'unavailable': + case 'reject': + if (!updatedCall.ended || updatedCall.endedBy?.id !== uid) { + throw new Error('invalid-call-state'); + } break; - default: + case 'accept': if (updatedCall.callee.contractId !== signal.contractId) { if (updatedCall.callee.contractId) { throw new Error('invalid-call-state'); From 9d42d281435fdcddd64bd4ddfd8ddc924419a140 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Fri, 27 Mar 2026 15:44:08 -0300 Subject: [PATCH 07/51] regression: populate permission to new federated-external role (#39854) --- .../server/functions/upsertPermissions.ts | 2 +- apps/meteor/server/startup/migrations/xrun.ts | 38 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/apps/meteor/app/authorization/server/functions/upsertPermissions.ts b/apps/meteor/app/authorization/server/functions/upsertPermissions.ts index 2b6d93f60d3cd..015f14189f46c 100644 --- a/apps/meteor/app/authorization/server/functions/upsertPermissions.ts +++ b/apps/meteor/app/authorization/server/functions/upsertPermissions.ts @@ -18,7 +18,7 @@ export const upsertPermissions = async (): Promise => { { name: 'leader', scope: 'Subscriptions', description: 'Leader' }, { name: 'owner', scope: 'Subscriptions', description: 'Owner' }, { name: 'user', scope: 'Users', description: '' }, - { name: 'federated-external', scope: 'Users', description: 'External Federated User' }, + { name: 'federated-external', scope: 'Users', description: '' }, { name: 'bot', scope: 'Users', description: '' }, { name: 'app', scope: 'Users', description: '' }, { name: 'guest', scope: 'Users', description: '' }, diff --git a/apps/meteor/server/startup/migrations/xrun.ts b/apps/meteor/server/startup/migrations/xrun.ts index 0344649f99935..8e552f034fa4a 100644 --- a/apps/meteor/server/startup/migrations/xrun.ts +++ b/apps/meteor/server/startup/migrations/xrun.ts @@ -1,4 +1,4 @@ -import { Settings } from '@rocket.chat/models'; +import { Permissions, Roles, Settings, Users } from '@rocket.chat/models'; import type { UpdateResult } from 'mongodb'; import { upsertPermissions } from '../../../app/authorization/server/functions/upsertPermissions'; @@ -55,10 +55,46 @@ const moveRetentionSetting = async () => { await Settings.updateMany({ _id: { $in: Array.from(maxAgeSettingMap.keys()) } }, { $set: { value: -1 } }); }; +async function setPermissionsToNewRole() { + const role = await Roles.findOneById('federated-external'); + + // if role was found it means it was already created with the permissions, so we can skip it + if (role) { + return; + } + + // if federation was used before the new role was created, we need to update their roles with the new role + await Users.updateMany({ federated: true }, { $addToSet: { roles: 'federated-external' } }); + + const rolePermissions = [ + 'create-c', + 'create-d', + 'create-p', + 'delete-own-message', + 'leave-c', + 'leave-p', + 'mention-all', + 'mention-here', + 'start-discussion', + 'start-discussion-other-user', + 'view-c-room', + 'view-d-room', + 'view-p-room', + 'preview-c-room', + 'view-outside-room', + 'mobile-upload-file', + 'access-federation', + ]; + + // since this is a one time query, no need to create a method in model class for it + await Permissions.updateMany({ _id: { $in: rolePermissions } }, { $addToSet: { roles: 'federated-external' } }); +} + export const performMigrationProcedure = async (): Promise => { await migrateDatabase(version === 'latest' ? version : parseInt(version), subcommands); // perform operations when the server is starting with a different version await onServerVersionChange(async () => { + await setPermissionsToNewRole(); await upsertPermissions(); await ensureCloudWorkspaceRegistered(); await moveRetentionSetting(); From f83159329d331140710a843f020b878cb6c3f4c8 Mon Sep 17 00:00:00 2001 From: Douglas Fabris Date: Fri, 27 Mar 2026 20:43:23 -0300 Subject: [PATCH 08/51] regression: Video recorder popup keep displaying while file is uploading (#39910) --- .../VideoMessageRecorder.tsx | 8 ++--- apps/meteor/tests/e2e/file-upload.spec.ts | 10 +++++++ .../e2e/page-objects/fragments/composer.ts | 30 +++++++++++++++++++ .../tests/e2e/page-objects/fragments/popup.ts | 15 ++++++++++ 4 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/popup.ts diff --git a/apps/meteor/client/views/composer/VideoMessageRecorder/VideoMessageRecorder.tsx b/apps/meteor/client/views/composer/VideoMessageRecorder/VideoMessageRecorder.tsx index 23e20f8f96935..5952c35da15e3 100644 --- a/apps/meteor/client/views/composer/VideoMessageRecorder/VideoMessageRecorder.tsx +++ b/apps/meteor/client/views/composer/VideoMessageRecorder/VideoMessageRecorder.tsx @@ -41,7 +41,7 @@ const VideoMessageRecorder = ({ rid, tmid, reference }: VideoMessageRecorderProp const videoRef = useRef(null); const dispatchToastMessage = useToastMessageDispatch(); - const [time, setTime] = useState(); + const [time, setTime] = useState('00:00'); const [recordingState, setRecordingState] = useState<'idle' | 'loading' | 'recording'>('idle'); const [recordingInterval, setRecordingInterval] = useState | null>(null); const isRecording = recordingState === 'recording'; @@ -85,10 +85,10 @@ const VideoMessageRecorder = ({ rid, tmid, reference }: VideoMessageRecorderProp const fileName = `${t('Video_record')}.${getVideoRecordingExtension()}`; const file = new File([blob], fileName, { type: VideoRecorder.getSupportedMimeTypes().split(';')[0] }); await chat?.flows.uploadFiles({ files: [file] }); - chat?.composer?.setRecordingVideo(false); }; VideoRecorder.stop(cb); + chat?.composer?.setRecordingVideo(false); setTime(undefined); stopVideoRecording(rid, tmid); }; @@ -114,12 +114,12 @@ const VideoMessageRecorder = ({ rid, tmid, reference }: VideoMessageRecorderProp return ( - + - - diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddMatrixUsers/useAddMatrixUsers.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddMatrixUsers/useAddMatrixUsers.tsx index 518470aed5d44..41b0f7b2e95ab 100644 --- a/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddMatrixUsers/useAddMatrixUsers.tsx +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddMatrixUsers/useAddMatrixUsers.tsx @@ -5,7 +5,7 @@ import { useMutation } from '@tanstack/react-query'; import AddMatrixUsersModal from './AddMatrixUsersModal'; export type useAddMatrixUsersProps = { - handleSave: (args_0: { users: string[] }) => Promise; + handleSave: (args_0: { users: string[]; unbanConfirmed?: boolean }) => Promise; users: string[]; }; diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx index 7c7151d056c5f..42a068bedfabc 100644 --- a/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx @@ -11,13 +11,14 @@ import { ContextualbarFooter, ContextualbarDialog, } from '@rocket.chat/ui-client'; -import { useToastMessageDispatch, useMethod, useRoomToolbox } from '@rocket.chat/ui-contexts'; +import { useToastMessageDispatch, useMethod, useSetModal, useEndpoint, useRoomToolbox } from '@rocket.chat/ui-contexts'; import { useId } from 'react'; import type { ReactElement } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { useAddMatrixUsers } from './AddMatrixUsers/useAddMatrixUsers'; +import BannedUsersUnbanModal from './BannedUsersUnbanModal'; import UserAutoCompleteMultiple from '../../../../../components/UserAutoCompleteMultiple'; import { useRoom } from '../../../contexts/RoomContext'; @@ -39,8 +40,11 @@ const AddUsers = ({ rid, onClickBack, reload }: AddUsersProps): ReactElement => const isFederationBlocked = room && !isRoomNativeFederated(room); const isFederated = roomIsFederated && !isFederationBlocked; + const setModal = useSetModal(); const { closeTab } = useRoomToolbox(); const saveAction = useMethod('addUsersToRoom'); + const getBannedUsers = useEndpoint('GET', '/v1/rooms.bannedUsers'); + const unbanUser = useEndpoint('POST', '/v1/rooms.unbanUser'); const { handleSubmit, @@ -49,13 +53,51 @@ const AddUsers = ({ rid, onClickBack, reload }: AddUsersProps): ReactElement => formState: { isDirty, isSubmitting, errors }, } = useForm({ defaultValues: { users: [] } }); - const handleSave = useEffectEvent(async ({ users }: { users: string[] }) => { + const handleSave = useEffectEvent(async ({ users, unbanConfirmed }: { users: string[]; unbanConfirmed?: boolean }) => { + if (unbanConfirmed) { + const { bannedUsers } = await getBannedUsers({ roomId: rid }); + const bannedSet = new Set(bannedUsers.map((u) => u.username)); + const usersToUnban = users.filter((username) => bannedSet.has(username)); + + if (usersToUnban.length) { + await Promise.all(usersToUnban.map((username) => unbanUser({ roomId: rid, username }))); + } + } + await saveAction({ rid, users }); + dispatchToastMessage({ type: 'success', message: t(roomIsFederated && !isFederationBlocked ? 'Users_invited' : 'Users_added') }); + onClickBack(); + reload(); + }); + + const handleSaveWithBannedCheck = useEffectEvent(async ({ users }: { users: string[] }) => { try { - await saveAction({ rid, users }); - dispatchToastMessage({ type: 'success', message: t(roomIsFederated && !isFederationBlocked ? 'Users_invited' : 'Users_added') }); - onClickBack(); - reload(); - } catch (error) { + await handleSave({ users }); + } catch (error: any) { + if (error.error === 'error-user-is-banned') { + const { bannedUsers } = await getBannedUsers({ roomId: rid }); + const bannedSet = new Set(bannedUsers.map((u) => u.username)); + const usersToUnban = users.filter((username) => bannedSet.has(username)); + + if (usersToUnban.length) { + setModal( + setModal(null)} + onConfirm={async () => { + await Promise.all(usersToUnban.map((username) => unbanUser({ roomId: rid, username }))); + await saveAction({ rid, users }); + setModal(null); + dispatchToastMessage({ + type: 'success', + message: t(roomIsFederated && !isFederationBlocked ? 'Users_invited' : 'Users_added'), + }); + onClickBack(); + reload(); + }} + />, + ); + return; + } + } dispatchToastMessage({ type: 'error', message: error as Error }); } }); @@ -114,7 +156,7 @@ const AddUsers = ({ rid, onClickBack, reload }: AddUsersProps): ReactElement => ) ) : ( - )} diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/BannedUsersUnbanModal.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/BannedUsersUnbanModal.tsx new file mode 100644 index 0000000000000..68fdeb32be762 --- /dev/null +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/BannedUsersUnbanModal.tsx @@ -0,0 +1,80 @@ +import { + Modal, + Box, + Button, + Label, + CheckBox, + ModalHeader, + ModalHeaderText, + ModalTitle, + ModalClose, + ModalContent, + ModalFooter, + ModalFooterAnnotation, + ModalFooterControllers, +} from '@rocket.chat/fuselage'; +import type { ReactElement } from 'react'; +import { useId, useState } from 'react'; +import { useTranslation } from 'react-i18next'; + +type BannedUsersUnbanModalProps = { + onClose: () => void; + onConfirm: () => Promise; +}; + +const BannedUsersUnbanModal = ({ onClose, onConfirm }: BannedUsersUnbanModalProps): ReactElement => { + const { t } = useTranslation(); + const checkboxId = useId(); + const [unbanConfirmed, setUnbanConfirmed] = useState(false); + const [error, setError] = useState(); + const [loading, setLoading] = useState(false); + + const handleConfirm = async () => { + setLoading(true); + setError(undefined); + try { + await onConfirm(); + } catch (err: any) { + setError(err?.message || t('Something_went_wrong')); + } finally { + setLoading(false); + } + }; + + return ( + + + + {t('User_is_banned')} + + + + + {t('User_is_banned_from_room_confirm_unban')} + {error && ( + + {error} + + )} + + + + + setUnbanConfirmed((prev) => !prev)} id={checkboxId} /> + + + + + + + + + + ); +}; + +export default BannedUsersUnbanModal; diff --git a/apps/meteor/tests/end-to-end/api/rooms.ts b/apps/meteor/tests/end-to-end/api/rooms.ts index fada0b0287546..96d9385569030 100644 --- a/apps/meteor/tests/end-to-end/api/rooms.ts +++ b/apps/meteor/tests/end-to-end/api/rooms.ts @@ -4382,8 +4382,49 @@ describe('[Rooms]', () => { }); describe('unban via re-invite', () => { - it('should unban the user when re-invited', () => { + it('should fail to invite a banned user', () => { return request + .post(api('channels.invite')) + .set(credentials) + .send({ + roomId: testChannel._id, + userId: bannableUser._id, + }) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('errorType', 'error-user-is-banned'); + }); + }); + + it('should list the banned user in rooms.bannedUsers', async () => { + const res = await request + .get(api('rooms.bannedUsers')) + .set(credentials) + .query({ + roomId: testChannel._id, + }) + .expect('Content-Type', 'application/json') + .expect(200); + + expect(res.body).to.have.property('success', true); + const usernames = res.body.bannedUsers.map((u: { username: string }) => u.username); + expect(usernames).to.include(bannableUser.username); + }); + + it('should unban the user and then re-invite successfully', async () => { + await request + .post(api('rooms.unbanUser')) + .set(credentials) + .send({ + roomId: testChannel._id, + username: bannableUser.username, + }) + .expect('Content-Type', 'application/json') + .expect(200); + + await request .post(api('channels.invite')) .set(credentials) .send({ diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 5a037daa7ec9e..c6bb52defeaa6 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -5917,6 +5917,9 @@ "Yes_archive_it": "Yes, archive it!", "Yes_ban_user": "Yes, ban user!", "Yes_unban_user": "Yes, unban user!", + "User_is_banned": "User is banned", + "Unban_and_add": "Unban and add", + "User_is_banned_from_room_confirm_unban": "This user is banned from this room. Do you want to unban and add them back?", "Yes_clear_all": "Yes, clear all!", "Yes_continue": "Yes, continue!", "Yes_deactivate_it": "Yes, deactivate it!", From 2b7ee36eb6a01eb7783ac633f6d9f07d19569c8e Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Mon, 30 Mar 2026 18:23:41 -0300 Subject: [PATCH 13/51] fix(federation): revoke invite when banning a user who has not yet accepted (#39839) Co-authored-by: Diego Sampaio --- apps/meteor/package.json | 2 +- apps/meteor/server/services/room/service.ts | 16 +++- docs/features/ban-user.md | 91 +++++++++++++++++++ ee/packages/federation-matrix/package.json | 2 +- .../federation-matrix/src/events/member.ts | 38 ++++++++ .../tests/end-to-end/room.spec.ts | 81 ++++++++--------- packages/core-services/package.json | 2 +- .../core-services/src/types/IRoomService.ts | 1 + yarn.lock | 16 ++-- 9 files changed, 195 insertions(+), 54 deletions(-) create mode 100644 docs/features/ban-user.md diff --git a/apps/meteor/package.json b/apps/meteor/package.json index 8517bc99f90af..347bad9981337 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -103,7 +103,7 @@ "@rocket.chat/emitter": "^0.32.0", "@rocket.chat/favicon": "workspace:^", "@rocket.chat/federation-matrix": "workspace:^", - "@rocket.chat/federation-sdk": "0.6.0", + "@rocket.chat/federation-sdk": "0.6.2", "@rocket.chat/fuselage": "^0.73.0", "@rocket.chat/fuselage-forms": "^1.0.0", "@rocket.chat/fuselage-hooks": "^0.40.0", diff --git a/apps/meteor/server/services/room/service.ts b/apps/meteor/server/services/room/service.ts index 5995c1b93f988..47d3dba8f49c9 100644 --- a/apps/meteor/server/services/room/service.ts +++ b/apps/meteor/server/services/room/service.ts @@ -22,7 +22,11 @@ import { performUserBan } from '../../../app/lib/server/functions/banUserFromRoo import { createRoom } from '../../../app/lib/server/functions/createRoom'; // TODO remove this import import { executeUnbanUserFromRoom } from '../../../app/lib/server/functions/executeUnbanUserFromRoom'; import { removeUserFromRoom, performUserRemoval } from '../../../app/lib/server/functions/removeUserFromRoom'; -import { notifyOnSubscriptionChangedById, notifyOnSubscriptionChangedByRoomIdAndUserId } from '../../../app/lib/server/lib/notifyListener'; +import { + notifyOnSubscriptionChanged, + notifyOnSubscriptionChangedById, + notifyOnSubscriptionChangedByRoomIdAndUserId, +} from '../../../app/lib/server/lib/notifyListener'; import { readThread } from '../../../app/threads/server/functions'; import { getDefaultSubscriptionPref } from '../../../app/utils/lib/getDefaultSubscriptionPref'; import { getValidRoomName } from '../../../app/utils/server/lib/getValidRoomName'; @@ -148,6 +152,16 @@ export class RoomService extends ServiceClassInternal implements IRoomService { return performAcceptRoomInvite(room, subscription, user); } + async revokeInvite(room: IRoom, user: IUser): Promise { + const subscription = await Subscriptions.findOneByRoomIdAndUserId(room._id, user._id); + if (subscription?.status !== 'INVITED') { + return; + } + + await Subscriptions.removeById(subscription._id); + void notifyOnSubscriptionChanged(subscription, 'removed'); + } + async getValidRoomName(displayName: string, roomId = '', options: { allowDuplicates?: boolean } = {}): Promise { return getValidRoomName(displayName, roomId, options); } diff --git a/docs/features/ban-user.md b/docs/features/ban-user.md new file mode 100644 index 0000000000000..10e5037b01f54 --- /dev/null +++ b/docs/features/ban-user.md @@ -0,0 +1,91 @@ +# Ban User + +## Overview + +Banning prevents a user from participating in a specific room. Unlike kicking (which deletes the subscription), banning **keeps the subscription record** with `status: 'BANNED'`, creating a persistent access barrier. + +## Ban Flow + +1. A user with `ban-user` permission (roles: `admin`, `owner`, `moderator`) triggers the ban via UI, API (`POST /v1/rooms.banUser`), or slash command (`/ban @username`). +2. **Validations** (`banUserFromRoomMethod` in `server/lib/banUserFromRoom.ts`): + - Checks `ban-user` permission scoped to the room. + - Checks if the room type allows the action (via `roomDirectives.allowMemberAction`). + - Checks if the banning user has access to the room. + - Checks if the target user exists and is in the room. + - Rejects ban if the target is already banned. + - Rejects ban if the target is the last owner. +3. **Execution** (`performUserBan` in `app/lib/server/functions/banUserFromRoom.ts`): + - Updates the subscription to `status: 'BANNED'` (does not delete the record). + - Removes the room from the user's `__rooms` array. + - Decrements the room's `usersCount`. + - Removes room-scoped roles (`moderator`, `owner`, `leader`) in channels and groups. + - If the room is a team's main room, removes the member from the team. + - Saves a `user-banned` system message. + - Notifies the client with a `removed` event on the subscription (so the client drops the stream). +4. **Callback** `afterBanFromRoom` fires (used by Matrix federation to propagate the ban). + +## Unban Flow + +1. Triggered via UI (contextual bar "Banned Users"), API (`POST /v1/rooms.unbanUser`), or slash command (`/unban @username`). +2. Finds the subscription via `findOneBannedSubscription`. +3. **Removes the subscription entirely** (`Subscriptions.removeById`) — does not restore it to active status. +4. Saves a `user-unbanned` system message. +5. **Callback** `afterUnbanFromRoom` fires (federation). + +**Important:** after unban the user **does not become a member** of the room again. The banned subscription is deleted. The user must be invited or join again. + +## Re-entry After Unban + +In `addUserToRoom`, if the user being added has a subscription with `status: 'BANNED'`: +- Removes the banned subscription. +- Saves a `user-unbanned` system message. +- Creates a new subscription normally. + +This means inviting/adding a banned user automatically unbans them. + +## Access Control + +The `canAccessRoom` validators check for bans in two public room scenarios: +- **Public rooms inside teams** — if banned, access is denied. +- **Regular public rooms** — if banned, access is denied. + +For private rooms, access is already controlled by the subscription (which is marked as `BANNED`). + +## UI + +- **Ban action:** appears in the user info panel (inside a room), gated by `ban-user` permission + `roomCanBan` + federation rules. +- **Banned users list:** "Banned Users" tab in the room toolbox (icon: `ban`, order: 13, requires `ban-user`), with virtualized scroll and infinite pagination via `GET /v1/rooms.bannedUsers`. +- **Unban action:** context menu on each item in the banned users list. +- **Confirmation:** both actions show a `GenericModal` with `danger` variant. + +## System Messages + +| Key | When | +|-----|------| +| `user-banned` | A user is banned from the room | +| `user-unbanned` | A user is unbanned (including via re-addition) | + +## REST Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| POST | `/v1/rooms.banUser` | Ban a user (accepts `userId` or `username` + `roomId`) | +| POST | `/v1/rooms.unbanUser` | Unban a user | +| GET | `/v1/rooms.bannedUsers` | List banned users (paginated) | + +## Key Files + +| Layer | File | +|-------|------| +| API routes | `app/api/server/v1/rooms.ts` | +| Validation & permissions | `server/lib/banUserFromRoom.ts` | +| Core ban logic | `app/lib/server/functions/banUserFromRoom.ts` | +| Core unban logic | `app/lib/server/functions/executeUnbanUserFromRoom.ts` | +| Slash commands | `app/slashcommands-ban/server/ban.ts`, `unban.ts` | +| Client ban hook | `client/views/room/hooks/useBanUser.tsx` | +| Client unban hook | `client/views/room/hooks/useUnbanUser.tsx` | +| Ban action (user info) | `client/views/room/hooks/useUserInfoActions/actions/useBanUserAction.tsx` | +| Banned users UI | `client/views/room/contextualBar/BannedUsers/` | +| Subscription types | `packages/core-typings/src/ISubscription.ts` | +| REST typings | `packages/rest-typings/src/v1/rooms.ts` | +| Model typings | `packages/model-typings/src/models/ISubscriptionsModel.ts` | diff --git a/ee/packages/federation-matrix/package.json b/ee/packages/federation-matrix/package.json index 0f687cfa842fc..43dae56e3ca77 100644 --- a/ee/packages/federation-matrix/package.json +++ b/ee/packages/federation-matrix/package.json @@ -22,7 +22,7 @@ "@rocket.chat/core-services": "workspace:^", "@rocket.chat/core-typings": "workspace:^", "@rocket.chat/emitter": "^0.32.0", - "@rocket.chat/federation-sdk": "0.6.0", + "@rocket.chat/federation-sdk": "0.6.2", "@rocket.chat/http-router": "workspace:^", "@rocket.chat/license": "workspace:^", "@rocket.chat/models": "workspace:^", diff --git a/ee/packages/federation-matrix/src/events/member.ts b/ee/packages/federation-matrix/src/events/member.ts index 00ed97bc6b5ed..ce834f7bf5df9 100644 --- a/ee/packages/federation-matrix/src/events/member.ts +++ b/ee/packages/federation-matrix/src/events/member.ts @@ -395,6 +395,36 @@ async function handleBan({ await Room.performUserBan(room, bannedUser, senderUser); } +async function handleMembershipRejected({ + event, + reason, +}: HomeserverEventSignatures['homeserver.matrix.membership.rejected']): Promise { + const room = await Rooms.findOne({ 'federation.mrid': event.room_id }); + if (!room) { + logger.debug({ msg: 'No local room found for rejected membership event', roomId: event.room_id, reason }); + return; + } + + const serverName = federationSDK.getConfig('serverName'); + const [username] = getUsernameServername(event.state_key, serverName); + + const user = await Users.findOneByUsername(username); + if (!user) { + logger.debug({ msg: 'User not found for rejected membership event', userId: event.state_key, reason }); + return; + } + + await Room.revokeInvite(room, user); + + logger.info({ + msg: 'Revoked invite due to rejected membership event', + userId: user._id, + roomId: room._id, + membership: event.content.membership, + reason, + }); +} + export function member() { federationSDK.eventEmitterService.on('homeserver.matrix.membership', async ({ event }) => { try { @@ -422,4 +452,12 @@ export function member() { logger.error({ msg: 'Failed to process Matrix membership event', err }); } }); + + federationSDK.eventEmitterService.on('homeserver.matrix.membership.rejected', async (payload) => { + try { + await handleMembershipRejected(payload); + } catch (err) { + logger.error({ msg: 'Failed to process rejected membership event', err }); + } + }); } diff --git a/ee/packages/federation-matrix/tests/end-to-end/room.spec.ts b/ee/packages/federation-matrix/tests/end-to-end/room.spec.ts index 760c74435da83..8dfc338560c57 100644 --- a/ee/packages/federation-matrix/tests/end-to-end/room.spec.ts +++ b/ee/packages/federation-matrix/tests/end-to-end/room.spec.ts @@ -95,7 +95,7 @@ import { SynapseClient } from '../helper/synapse-client'; await deleteUser(createdUser, {}, rc1AdminRequestConfig); }); - it('It should create a federated room when federated members are added', async () => { + it('should create a federated room when federated members are added', async () => { const response = await createRoom({ type: 'd', username: federationConfig.hs1.adminMatrixUserId, @@ -112,7 +112,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(roomInfo.room).toHaveProperty('federated', true); }); - it('It should create a non-federated room when only local members are added', async () => { + it('should create a non-federated room when only local members are added', async () => { const response = await createRoom({ type: 'd', username: federationConfig.rc1.additionalUser1.username, @@ -132,7 +132,7 @@ import { SynapseClient } from '../helper/synapse-client'; describe('Create a room on RC as private, explicitly not federated, with federated users in creation modal', () => { describe('Add 1 federated user in the creation modal', () => { - it('It should not allow the creation of the room', async () => { + it('should not allow the creation of the room', async () => { const channelName = `non-federated-channel-single-fed-${Date.now()}`; // RC view: Attempt to create a non-federated private room with 1 federated user @@ -154,7 +154,7 @@ import { SynapseClient } from '../helper/synapse-client'; }); describe('Add 2 federated users in the creation modal', () => { - it('It should not allow the creation of the room', async () => { + it('should not allow the creation of the room', async () => { const channelName = `non-federated-channel-multi-fed-${Date.now()}`; // RC view: Attempt to create a non-federated private room with 2 federated users @@ -176,7 +176,7 @@ import { SynapseClient } from '../helper/synapse-client'; }); describe('Add 1 federated user and 1 local user in the creation modal', () => { - it('It should not allow the creation of the room', async () => { + it('should not allow the creation of the room', async () => { const channelName = `non-federated-channel-mixed-${Date.now()}`; // RC view: Attempt to create a non-federated private room with 1 federated user and 1 local user @@ -226,7 +226,7 @@ import { SynapseClient } from '../helper/synapse-client'; // No cleanup needed - rooms are left for debugging purposes describe('Go to the members list and try to add a federated user', () => { - it('It should not allow and show an error message', async () => { + it('should not allow and show an error message', async () => { // RC view: Attempt to add a federated user to the non-federated room const response = await addUserToRoom({ usernames: [federationConfig.hs1.adminMatrixUserId], @@ -258,7 +258,7 @@ import { SynapseClient } from '../helper/synapse-client'; }); describe('Go to the composer and use the /invite slash command to add a federated user', () => { - it('It should not allow and show an error message', async () => { + it('should not allow and show an error message', async () => { // Set up DDP listener to catch ephemeral messages const ddpListener = createDDPListener(federationConfig.rc1.url, rc1AdminRequestConfig); @@ -347,7 +347,7 @@ import { SynapseClient } from '../helper/synapse-client'; // expect(acceptedRoomId, 'Expected to have joined the room, but joinedRoomId is different from acceptedRoomId').to.equal(joinedRoomId); }, 10000); - it('It should show the room on the remote Element or RC', async () => { + it('should show the room on the remote Element or RC', async () => { // RC view: Check in RC const roomInfo = await getRoomInfo(federatedChannel._id, rc1AdminRequestConfig); expect(roomInfo.room).toHaveProperty('_id', federatedChannel._id); @@ -358,7 +358,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(elementRoom).toHaveProperty('name', channelName); }); - it('It should show the new user in the members list', async () => { + it('should show the new user in the members list', async () => { // RC view: Check in RC that the federated user is in the members list const rc1AdminUserInRC = await findRoomMember( federatedChannel._id, @@ -388,7 +388,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(hs1AdminUserInSynapse).not.toBeNull(); }); - it('It should show the system message that the user was invited', async () => { + it('should show the system message that the user was invited', async () => { // RC view: Check in RC. We don't check in Synapse because this is not part of the protocol // Get the room history to find the system message const historyResponse = await getGroupHistory(federatedChannel._id, rc1AdminRequestConfig); @@ -447,7 +447,7 @@ import { SynapseClient } from '../helper/synapse-client'; // expect(acceptedRoomId, 'Expected to have joined the room, but joinedRoomId is different from acceptedRoomId').to.equal(joinedRoomId); }, 15000); - it('It should show the room on all the involved remote Element or RC', async () => { + it('should show the room on all the involved remote Element or RC', async () => { // RC view: Check in RC const roomInfo = await getRoomInfo(federatedChannel._id, rc1AdminRequestConfig); expect(roomInfo.room).toHaveProperty('_id', federatedChannel._id); @@ -462,7 +462,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(elementRoom2).toHaveProperty('name', channelName); }); - it('It should show the new users in the members list of all RCs involved', async () => { + it('should show the new users in the members list of all RCs involved', async () => { // RC view: Check in RC that both federated users are in the members list const rc1AdminUserInRC = await findRoomMember(federatedChannel._id, federationConfig.rc1.adminUser, {}, rc1AdminRequestConfig); const hs1AdminUserInRC = await findRoomMember( @@ -505,7 +505,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(hs1User1InSynapseUser1).not.toBeNull(); }); - it('It should show the system messages that the users were invited', async () => { + it('should show the system messages that the users were invited', async () => { // RC view: Check in RC. We don't check in Synapse because this is not part of the protocol // Get the room history to find the system messages const historyResponse = await getGroupHistory(federatedChannel._id, rc1AdminRequestConfig); @@ -530,7 +530,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(hs1User1InviteMessage?.u?.username).toBe(federationConfig.rc1.adminUser); }); - it('It should show the system messages that the users joined when they accept the invites', async () => { + it('should show the system messages that the users joined when they accept the invites', async () => { // RC view: Check in RC. We don't check in Synapse because this is not part of the protocol // Get the room history to find the system messages const historyResponse = await getGroupHistory(federatedChannel._id, rc1AdminRequestConfig); @@ -596,7 +596,7 @@ import { SynapseClient } from '../helper/synapse-client'; await acceptRoomInvite(federatedChannel._id, rc1User1RequestConfig); }, 15000); - it('It should show the room on the remote Element or RC and local for the second user', async () => { + it('should show the room on the remote Element or RC and local for the second user', async () => { // RC view: Check in RC (admin view) const roomInfo = await getRoomInfo(federatedChannel._id, rc1AdminRequestConfig); expect(roomInfo.room).toHaveProperty('_id', federatedChannel._id); @@ -613,7 +613,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(room.getMyMembership()).toBe('join'); }); - it('It should show the 2 new users in the members list', async () => { + it('should show the 2 new users in the members list', async () => { // RC view: Check in RC (admin view) that both users are in the members list const rc1AdminUserInRC = await findRoomMember(federatedChannel._id, federationConfig.rc1.adminUser, {}, rc1AdminRequestConfig); const rc1User1InRC = await findRoomMember( @@ -675,7 +675,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(hs1AdminUserInSynapse).not.toBeNull(); }); - it('It should show the 2 system messages that the users were invited', async () => { + it('should show the 2 system messages that the users were invited', async () => { // RC view: Check in RC (admin view) for system messages about both users being invited const historyResponse = await getGroupHistory(federatedChannel._id, rc1AdminRequestConfig); expect(Array.isArray(historyResponse.messages)).toBe(true); @@ -859,7 +859,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(acceptedRoomId).not.toBe(''); }, 15000); - it('It should show the room on the remote Element or RC', async () => { + it('should show the room on the remote Element or RC', async () => { // RC view: Check in RC const roomInfo = await getRoomInfo(federatedChannel._id, rc1AdminRequestConfig); expect(roomInfo.room).toHaveProperty('_id', federatedChannel._id); @@ -870,7 +870,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(elementRoom).toHaveProperty('name', channelName); }); - it('It should show the new user in the members list', async () => { + it('should show the new user in the members list', async () => { // RC view: Check in RC that both users are in the members list const rc1AdminUserInRC = await findRoomMember( federatedChannel._id, @@ -900,7 +900,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(hs1AdminUserInSynapse).not.toBeNull(); }); - it('It should show the system message that the user joined', async () => { + it('should show the system message that the user joined', async () => { // RC view: Check in RC // Get the room history to find the system messages const historyResponse = await getGroupHistory(federatedChannel._id, rc1AdminRequestConfig); @@ -965,7 +965,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(acceptedRoomId2).not.toBe(''); }, 15000); - it('It should show the room on all the involved remote Element or RC', async () => { + it('should show the room on all the involved remote Element or RC', async () => { // RC view: Check in RC const roomInfo = await getRoomInfo(federatedChannel._id, rc1AdminRequestConfig); expect(roomInfo.room).toHaveProperty('_id', federatedChannel._id); @@ -980,7 +980,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(elementRoom2).toHaveProperty('name', channelName); }); - it('It should show the new users in the members list of all RCs involved', async () => { + it('should show the new users in the members list of all RCs involved', async () => { // RC view: Check in RC that all users are in the members list const rc1AdminUserInRC = await findRoomMember(federatedChannel._id, federationConfig.rc1.adminUser, {}, rc1AdminRequestConfig); const hs1AdminUserInRC = await findRoomMember( @@ -1027,7 +1027,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(hs1User1InSynapseUser1).not.toBeNull(); }); - it('It should show the system messages that the users joined', async () => { + it('should show the system messages that the users joined', async () => { // RC view: Check in RC // Get the room history to find the system messages const historyResponse = await getGroupHistory(federatedChannel._id, rc1AdminRequestConfig); @@ -1101,7 +1101,7 @@ import { SynapseClient } from '../helper/synapse-client'; await acceptRoomInvite(federatedChannel._id, rc1User1RequestConfig); }, 15000); - it('It should show the room on the remote Element or RC and local for the second user', async () => { + it('should show the room on the remote Element or RC and local for the second user', async () => { // RC view: Check in RC (admin view) const roomInfo = await getRoomInfo(federatedChannel._id, rc1AdminRequestConfig); expect(roomInfo.room).toHaveProperty('_id', federatedChannel._id); @@ -1118,7 +1118,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(room.getMyMembership()).toBe('join'); }); - it('It should show the 2 new users in the members list', async () => { + it('should show the 2 new users in the members list', async () => { // RC view: Check in RC (admin view) that all users are in the members list const rc1AdminUserInRC = await findRoomMember(federatedChannel._id, federationConfig.rc1.adminUser, {}, rc1AdminRequestConfig); const rc1User1InRC = await findRoomMember( @@ -1180,7 +1180,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(hs1AdminUserInSynapse).not.toBeNull(); }); - it('It should show the 2 system messages that the user joined', async () => { + it('should show the 2 system messages that the user joined', async () => { // RC view: Check in RC (admin view) for system messages about both users joining const historyResponse = await getGroupHistory(federatedChannel._id, rc1AdminRequestConfig); expect(Array.isArray(historyResponse.messages)).toBe(true); @@ -1270,7 +1270,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(acceptedRoomId).not.toBe(''); }, 15000); - it('It should show the room on the remote Element or RC', async () => { + it('should show the room on the remote Element or RC', async () => { // RC view: Check in RC const roomInfo = await getRoomInfo(federatedChannel._id, rc1AdminRequestConfig); expect(roomInfo.room).toHaveProperty('_id', federatedChannel._id); @@ -1281,7 +1281,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(elementRoom).toHaveProperty('name', channelName); }); - it('It should show the new user in the members list', async () => { + it('should show the new user in the members list', async () => { // RC view: Check in RC that both users are in the members list const rc1AdminUserInRC = await findRoomMember( federatedChannel._id, @@ -1311,7 +1311,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(hs1AdminUserInSynapse).not.toBeNull(); }); - it('It should show the system message that the user joined', async () => { + it('should show the system message that the user joined', async () => { // RC view: Check in RC // Get the room history to find the system messages const historyResponse = await getGroupHistory(federatedChannel._id, rc1AdminRequestConfig); @@ -1376,7 +1376,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(acceptedRoomId2).not.toBe(''); }, 15000); - it('It should show the room on all the involved remote Element or RC', async () => { + it('should show the room on all the involved remote Element or RC', async () => { // RC view: Check in RC const roomInfo = await getRoomInfo(federatedChannel._id, rc1AdminRequestConfig); expect(roomInfo.room).toHaveProperty('_id', federatedChannel._id); @@ -1391,7 +1391,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(elementRoom2).toHaveProperty('name', channelName); }); - it('It should show the new users in the members list of all RCs involved', async () => { + it('should show the new users in the members list of all RCs involved', async () => { // RC view: Check in RC that all users are in the members list const rc1AdminUserInRC = await findRoomMember(federatedChannel._id, federationConfig.rc1.adminUser, {}, rc1AdminRequestConfig); const hs1AdminUserInRC = await findRoomMember( @@ -1438,7 +1438,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(hs1User1InSynapseUser1).not.toBeNull(); }); - it('It should show the system messages that the user joined on all RCs involved', async () => { + it('should show the system messages that the user joined on all RCs involved', async () => { // RC view: Check in RC // Get the room history to find the system messages const historyResponse = await getGroupHistory(federatedChannel._id, rc1AdminRequestConfig); @@ -1511,7 +1511,7 @@ import { SynapseClient } from '../helper/synapse-client'; await acceptRoomInvite(federatedChannel._id, rc1User1RequestConfig); }, 15000); - it('It should show the room on the remote Element or RC and local for the second user', async () => { + it('should show the room on the remote Element or RC and local for the second user', async () => { // RC view: Check in RC (admin view) const roomInfo = await getRoomInfo(federatedChannel._id, rc1AdminRequestConfig); expect(roomInfo.room).toHaveProperty('_id', federatedChannel._id); @@ -1528,7 +1528,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(room.getMyMembership()).toBe('join'); }); - it('It should show the 2 new users in the members list', async () => { + it('should show the 2 new users in the members list', async () => { // RC view: Check in RC (admin view) that all users are in the members list const rc1AdminUserInRC = await findRoomMember(federatedChannel._id, federationConfig.rc1.adminUser, {}, rc1AdminRequestConfig); const rc1User1InRC = await findRoomMember( @@ -1590,7 +1590,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(hs1AdminUserInSynapse).not.toBeNull(); }); - it('It should show the 2 system messages that the user joined', async () => { + it('should show the 2 system messages that the user joined', async () => { // RC view: Check in RC (admin view) for system messages about both users joining const historyResponse = await getGroupHistory(federatedChannel._id, rc1AdminRequestConfig); expect(Array.isArray(historyResponse.messages)).toBe(true); @@ -1661,7 +1661,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(federatedChannel).toHaveProperty('federated', true); }, 10000); - it('It should not allow admin to accept invitation on behalf of another user', async () => { + it('should not allow admin to accept invitation on behalf of another user', async () => { // RC view: Admin tries to accept rc1User1's invitation const response = await acceptRoomInvite(federatedChannel._id, rc1AdminRequestConfig); expect(response.success).toBe(false); @@ -1670,7 +1670,7 @@ import { SynapseClient } from '../helper/synapse-client'; ); }); - it('It should not allow admin to reject invitation on behalf of another user', async () => { + it('should not allow admin to reject invitation on behalf of another user', async () => { // RC view: Admin tries to reject rc1User1's invitation const response = await rejectRoomInvite(federatedChannel._id, rc1AdminRequestConfig); expect(response.success).toBe(false); @@ -1711,7 +1711,7 @@ import { SynapseClient } from '../helper/synapse-client'; }, 15000); describe('It should reflect all the members and messagens on the rocket.chat side', () => { - it('It should show all the three users in the members list', async () => { + it('should show all the three users in the members list', async () => { await retry( 'Getting room members until all are present', async () => { @@ -1796,10 +1796,7 @@ import { SynapseClient } from '../helper/synapse-client'; expect(acceptResponse.success).toBe(false); }); - it('should allow RC user to reject the revoked invitation and remove the subscription', async () => { - const rejectResponse = await rejectRoomInvite(rid, rc1AdminRequestConfig); - expect(rejectResponse.success).toBe(true); - + it('should not have the subscription on the RC side after revoked invitation', async () => { const subscriptions = await getSubscriptions(rc1AdminRequestConfig); const invitedSub = subscriptions.update.find((sub) => sub.fname?.includes(channelName)); expect(invitedSub).toBeFalsy(); diff --git a/packages/core-services/package.json b/packages/core-services/package.json index a6b61c77af530..9d4646bc660dc 100644 --- a/packages/core-services/package.json +++ b/packages/core-services/package.json @@ -18,7 +18,7 @@ }, "dependencies": { "@rocket.chat/core-typings": "workspace:^", - "@rocket.chat/federation-sdk": "0.6.0", + "@rocket.chat/federation-sdk": "0.6.2", "@rocket.chat/http-router": "workspace:^", "@rocket.chat/icons": "~0.47.0", "@rocket.chat/media-signaling": "workspace:^", diff --git a/packages/core-services/src/types/IRoomService.ts b/packages/core-services/src/types/IRoomService.ts index 617a60974aada..57c15e101a4c6 100644 --- a/packages/core-services/src/types/IRoomService.ts +++ b/packages/core-services/src/types/IRoomService.ts @@ -40,6 +40,7 @@ export interface IRoomService { performUserBan(room: IRoom, user: IUser, byUser: IUser): Promise; performUserUnban(room: IRoom, user: IUser, byUser: IUser): Promise; performAcceptRoomInvite(room: IRoom, subscription: ISubscription, user: IUser): Promise; + revokeInvite(room: IRoom, user: IUser): Promise; removeUserFromRoom( roomId: string, user: IUser, diff --git a/yarn.lock b/yarn.lock index 0aa5f7003aa3d..63aa64a700fe6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9140,7 +9140,7 @@ __metadata: dependencies: "@rocket.chat/apps-engine": "workspace:^" "@rocket.chat/core-typings": "workspace:^" - "@rocket.chat/federation-sdk": "npm:0.6.0" + "@rocket.chat/federation-sdk": "npm:0.6.2" "@rocket.chat/http-router": "workspace:^" "@rocket.chat/icons": "npm:~0.47.0" "@rocket.chat/jest-presets": "workspace:~" @@ -9350,7 +9350,7 @@ __metadata: "@rocket.chat/core-typings": "workspace:^" "@rocket.chat/ddp-client": "workspace:^" "@rocket.chat/emitter": "npm:^0.32.0" - "@rocket.chat/federation-sdk": "npm:0.6.0" + "@rocket.chat/federation-sdk": "npm:0.6.2" "@rocket.chat/http-router": "workspace:^" "@rocket.chat/license": "workspace:^" "@rocket.chat/models": "workspace:^" @@ -9379,9 +9379,9 @@ __metadata: languageName: unknown linkType: soft -"@rocket.chat/federation-sdk@npm:0.6.0": - version: 0.6.0 - resolution: "@rocket.chat/federation-sdk@npm:0.6.0" +"@rocket.chat/federation-sdk@npm:0.6.2": + version: 0.6.2 + resolution: "@rocket.chat/federation-sdk@npm:0.6.2" dependencies: "@datastructures-js/priority-queue": "npm:^6.3.5" "@noble/ed25519": "npm:^3.0.0" @@ -9394,7 +9394,7 @@ __metadata: zod: "npm:~4.3.6" peerDependencies: typescript: ~5.9.2 - checksum: 10/704e01164679b9945907b499e48923e20ab699212dd0f282080f805a95d616d2a4e4c6bb85c9473284c56d18ccdff05af599c75ddbba388d51b5f8a69751974d + checksum: 10/dd21576de694e4f18dcde46d3357f5ca3b817e3f9f20d2b66b526a35c716faee870f7a72356c86c1b59c27beddd53225725e126c460cd5f52eaba964bb807bdf languageName: node linkType: hard @@ -10001,7 +10001,7 @@ __metadata: "@rocket.chat/emitter": "npm:^0.32.0" "@rocket.chat/favicon": "workspace:^" "@rocket.chat/federation-matrix": "workspace:^" - "@rocket.chat/federation-sdk": "npm:0.6.0" + "@rocket.chat/federation-sdk": "npm:0.6.2" "@rocket.chat/fuselage": "npm:^0.73.0" "@rocket.chat/fuselage-forms": "npm:^1.0.0" "@rocket.chat/fuselage-hooks": "npm:^0.40.0" @@ -11366,7 +11366,7 @@ __metadata: peerDependencies: "@rocket.chat/layout": "*" "@rocket.chat/tools": 0.2.5-rc.0 - "@rocket.chat/ui-contexts": 29.0.0-rc.1 + "@rocket.chat/ui-contexts": 29.0.0-rc.2 "@tanstack/react-query": "*" react: "*" react-hook-form: "*" From dd52a22b9e4869f409fb461da02bca699446b513 Mon Sep 17 00:00:00 2001 From: rocketchat-github-ci Date: Mon, 30 Mar 2026 22:27:23 +0000 Subject: [PATCH 14/51] Release 8.3.0-rc.3 [no ci] --- .changeset/bump-patch-1774909627968.md | 5 +++ .changeset/pre.json | 1 + apps/meteor/CHANGELOG.md | 41 +++++++++++++++++++ apps/meteor/app/utils/rocketchat.info | 2 +- apps/meteor/ee/server/services/CHANGELOG.md | 14 +++++++ apps/meteor/ee/server/services/package.json | 2 +- apps/meteor/package.json | 2 +- apps/uikit-playground/CHANGELOG.md | 12 ++++++ apps/uikit-playground/package.json | 2 +- ee/apps/account-service/CHANGELOG.md | 14 +++++++ ee/apps/account-service/package.json | 2 +- ee/apps/authorization-service/CHANGELOG.md | 15 +++++++ ee/apps/authorization-service/package.json | 2 +- ee/apps/ddp-streamer/CHANGELOG.md | 15 +++++++ ee/apps/ddp-streamer/package.json | 2 +- ee/apps/omnichannel-transcript/CHANGELOG.md | 15 +++++++ ee/apps/omnichannel-transcript/package.json | 2 +- ee/apps/presence-service/CHANGELOG.md | 14 +++++++ ee/apps/presence-service/package.json | 2 +- ee/apps/queue-worker/CHANGELOG.md | 14 +++++++ ee/apps/queue-worker/package.json | 2 +- ee/packages/abac/CHANGELOG.md | 11 +++++ ee/packages/abac/package.json | 2 +- ee/packages/federation-matrix/CHANGELOG.md | 15 +++++++ ee/packages/federation-matrix/package.json | 2 +- ee/packages/license/CHANGELOG.md | 9 ++++ ee/packages/license/package.json | 2 +- ee/packages/media-calls/CHANGELOG.md | 10 +++++ ee/packages/media-calls/package.json | 2 +- ee/packages/network-broker/CHANGELOG.md | 9 ++++ ee/packages/network-broker/package.json | 2 +- ee/packages/omni-core-ee/CHANGELOG.md | 11 +++++ ee/packages/omni-core-ee/package.json | 2 +- ee/packages/omnichannel-services/CHANGELOG.md | 15 +++++++ ee/packages/omnichannel-services/package.json | 2 +- ee/packages/pdf-worker/CHANGELOG.md | 9 ++++ ee/packages/pdf-worker/package.json | 2 +- ee/packages/presence/CHANGELOG.md | 11 +++++ ee/packages/presence/package.json | 2 +- package.json | 2 +- packages/api-client/CHANGELOG.md | 10 +++++ packages/api-client/package.json | 2 +- packages/apps/CHANGELOG.md | 10 +++++ packages/apps/package.json | 2 +- packages/core-services/CHANGELOG.md | 12 ++++++ packages/core-services/package.json | 2 +- packages/core-typings/CHANGELOG.md | 2 + packages/core-typings/package.json | 2 +- packages/cron/CHANGELOG.md | 10 +++++ packages/cron/package.json | 2 +- packages/ddp-client/CHANGELOG.md | 11 +++++ packages/ddp-client/package.json | 2 +- packages/fuselage-ui-kit/CHANGELOG.md | 13 ++++++ packages/fuselage-ui-kit/package.json | 2 +- packages/gazzodown/CHANGELOG.md | 11 +++++ packages/gazzodown/package.json | 2 +- packages/http-router/CHANGELOG.md | 10 +++++ packages/http-router/package.json | 2 +- packages/instance-status/CHANGELOG.md | 9 ++++ packages/instance-status/package.json | 2 +- packages/livechat/CHANGELOG.md | 9 ++++ packages/livechat/package.json | 2 +- packages/mock-providers/CHANGELOG.md | 9 ++++ packages/mock-providers/package.json | 2 +- packages/model-typings/CHANGELOG.md | 9 ++++ packages/model-typings/package.json | 2 +- packages/models/CHANGELOG.md | 10 +++++ packages/models/package.json | 2 +- packages/omni-core/CHANGELOG.md | 9 ++++ packages/omni-core/package.json | 2 +- packages/rest-typings/CHANGELOG.md | 9 ++++ packages/rest-typings/package.json | 2 +- packages/server-fetch/CHANGELOG.md | 9 ++++ packages/server-fetch/package.json | 2 +- packages/ui-avatar/CHANGELOG.md | 9 ++++ packages/ui-avatar/package.json | 2 +- packages/ui-client/CHANGELOG.md | 10 +++++ packages/ui-client/package.json | 2 +- packages/ui-contexts/CHANGELOG.md | 11 +++++ packages/ui-contexts/package.json | 2 +- packages/ui-video-conf/CHANGELOG.md | 10 +++++ packages/ui-video-conf/package.json | 2 +- packages/ui-voip/CHANGELOG.md | 12 ++++++ packages/ui-voip/package.json | 2 +- packages/web-ui-registration/CHANGELOG.md | 9 ++++ packages/web-ui-registration/package.json | 4 +- 86 files changed, 527 insertions(+), 44 deletions(-) create mode 100644 .changeset/bump-patch-1774909627968.md diff --git a/.changeset/bump-patch-1774909627968.md b/.changeset/bump-patch-1774909627968.md new file mode 100644 index 0000000000000..e1eaa7980afb1 --- /dev/null +++ b/.changeset/bump-patch-1774909627968.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Bump @rocket.chat/meteor version. diff --git a/.changeset/pre.json b/.changeset/pre.json index 9ac619a97d49f..987bedbf85fe5 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -82,6 +82,7 @@ "bright-dots-march", "bump-patch-1774533301673", "bump-patch-1774666021169", + "bump-patch-1774909627968", "clean-ears-fly", "eight-colts-kiss", "five-chicken-invite", diff --git a/apps/meteor/CHANGELOG.md b/apps/meteor/CHANGELOG.md index 4d511c6d6c7c7..48471a32bbb9c 100644 --- a/apps/meteor/CHANGELOG.md +++ b/apps/meteor/CHANGELOG.md @@ -1,5 +1,46 @@ # @rocket.chat/meteor +## 8.3.0-rc.3 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 + - @rocket.chat/abac@0.1.6-rc.3 + - @rocket.chat/federation-matrix@0.1.0-rc.3 + - @rocket.chat/license@1.1.13-rc.3 + - @rocket.chat/media-calls@0.3.0-rc.3 + - @rocket.chat/omnichannel-services@0.3.50-rc.3 + - @rocket.chat/pdf-worker@0.3.32-rc.3 + - @rocket.chat/presence@0.2.53-rc.3 + - @rocket.chat/api-client@0.2.53-rc.3 + - @rocket.chat/apps@0.6.6-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/cron@0.1.53-rc.3 + - @rocket.chat/fuselage-ui-kit@29.0.0-rc.3 + - @rocket.chat/gazzodown@29.0.0-rc.3 + - @rocket.chat/http-router@7.9.20-rc.3 + - @rocket.chat/message-types@0.1.1-rc.0 + - @rocket.chat/model-typings@2.1.2-rc.3 + - @rocket.chat/ui-avatar@25.0.0-rc.3 + - @rocket.chat/ui-client@29.0.0-rc.3 + - @rocket.chat/ui-contexts@29.0.0-rc.3 + - @rocket.chat/ui-voip@19.0.0-rc.3 + - @rocket.chat/web-ui-registration@29.0.0-rc.3 + - @rocket.chat/models@2.1.2-rc.3 + - @rocket.chat/server-cloud-communication@0.0.3-rc.0 + - @rocket.chat/network-broker@0.2.32-rc.3 + - @rocket.chat/omni-core-ee@0.0.18-rc.3 + - @rocket.chat/ui-video-conf@29.0.0-rc.3 + - @rocket.chat/instance-status@0.1.53-rc.3 + - @rocket.chat/omni-core@0.0.18-rc.3 + - @rocket.chat/server-fetch@0.1.2-rc.3 +
+ ## 8.3.0-rc.2 ### Patch Changes diff --git a/apps/meteor/app/utils/rocketchat.info b/apps/meteor/app/utils/rocketchat.info index e90509e8cef8e..3166b21bd6ea1 100644 --- a/apps/meteor/app/utils/rocketchat.info +++ b/apps/meteor/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "8.3.0-rc.2" + "version": "8.3.0-rc.3" } diff --git a/apps/meteor/ee/server/services/CHANGELOG.md b/apps/meteor/ee/server/services/CHANGELOG.md index b82c559153a2d..9943153c5d126 100644 --- a/apps/meteor/ee/server/services/CHANGELOG.md +++ b/apps/meteor/ee/server/services/CHANGELOG.md @@ -1,5 +1,19 @@ # rocketchat-services +## 2.0.44-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/model-typings@2.1.2-rc.3 + - @rocket.chat/models@2.1.2-rc.3 + - @rocket.chat/network-broker@0.2.32-rc.3 +
+ ## 2.0.44-rc.2 ### Patch Changes diff --git a/apps/meteor/ee/server/services/package.json b/apps/meteor/ee/server/services/package.json index 890c7ba4d03bf..9110263979d9d 100644 --- a/apps/meteor/ee/server/services/package.json +++ b/apps/meteor/ee/server/services/package.json @@ -1,7 +1,7 @@ { "name": "rocketchat-services", "private": true, - "version": "2.0.44-rc.2", + "version": "2.0.44-rc.3", "description": "Rocket.Chat Authorization service", "main": "index.js", "scripts": { diff --git a/apps/meteor/package.json b/apps/meteor/package.json index 347bad9981337..7ccc0456809b1 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/meteor", - "version": "8.3.0-rc.2", + "version": "8.3.0-rc.3", "private": true, "description": "The Ultimate Open Source WebChat Platform", "keywords": [ diff --git a/apps/uikit-playground/CHANGELOG.md b/apps/uikit-playground/CHANGELOG.md index 7b82510eebc75..f6c917045db24 100644 --- a/apps/uikit-playground/CHANGELOG.md +++ b/apps/uikit-playground/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/uikit-playground +## 0.7.9-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/fuselage-ui-kit@29.0.0-rc.3 + - @rocket.chat/ui-avatar@25.0.0-rc.3 + - @rocket.chat/ui-contexts@29.0.0-rc.3 +
+ ## 0.7.9-rc.2 ### Patch Changes diff --git a/apps/uikit-playground/package.json b/apps/uikit-playground/package.json index 536de44f63813..e3f3f704e7f3d 100644 --- a/apps/uikit-playground/package.json +++ b/apps/uikit-playground/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/uikit-playground", - "version": "0.7.9-rc.2", + "version": "0.7.9-rc.3", "private": true, "type": "module", "scripts": { diff --git a/ee/apps/account-service/CHANGELOG.md b/ee/apps/account-service/CHANGELOG.md index 15a9f282c6e7b..e193ac332f677 100644 --- a/ee/apps/account-service/CHANGELOG.md +++ b/ee/apps/account-service/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/account-service +## 0.4.53-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/model-typings@2.1.2-rc.3 + - @rocket.chat/models@2.1.2-rc.3 + - @rocket.chat/network-broker@0.2.32-rc.3 +
+ ## 0.4.53-rc.2 ### Patch Changes diff --git a/ee/apps/account-service/package.json b/ee/apps/account-service/package.json index dbe978eee022b..bd9e46301d942 100644 --- a/ee/apps/account-service/package.json +++ b/ee/apps/account-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/account-service", - "version": "0.4.53-rc.2", + "version": "0.4.53-rc.3", "private": true, "description": "Rocket.Chat Account service", "keywords": [ diff --git a/ee/apps/authorization-service/CHANGELOG.md b/ee/apps/authorization-service/CHANGELOG.md index d3d2451214c4f..6a07a0dc42454 100644 --- a/ee/apps/authorization-service/CHANGELOG.md +++ b/ee/apps/authorization-service/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/authorization-service +## 0.5.6-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 + - @rocket.chat/abac@0.1.6-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/model-typings@2.1.2-rc.3 + - @rocket.chat/models@2.1.2-rc.3 + - @rocket.chat/network-broker@0.2.32-rc.3 +
+ ## 0.5.6-rc.2 ### Patch Changes diff --git a/ee/apps/authorization-service/package.json b/ee/apps/authorization-service/package.json index 35d6740c1fdbd..1b4dedc4297d5 100644 --- a/ee/apps/authorization-service/package.json +++ b/ee/apps/authorization-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/authorization-service", - "version": "0.5.6-rc.2", + "version": "0.5.6-rc.3", "private": true, "description": "Rocket.Chat Authorization service", "keywords": [ diff --git a/ee/apps/ddp-streamer/CHANGELOG.md b/ee/apps/ddp-streamer/CHANGELOG.md index d3e6975468c5e..61528633d4116 100644 --- a/ee/apps/ddp-streamer/CHANGELOG.md +++ b/ee/apps/ddp-streamer/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/ddp-streamer +## 0.3.53-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/model-typings@2.1.2-rc.3 + - @rocket.chat/models@2.1.2-rc.3 + - @rocket.chat/network-broker@0.2.32-rc.3 + - @rocket.chat/instance-status@0.1.53-rc.3 +
+ ## 0.3.53-rc.2 ### Patch Changes diff --git a/ee/apps/ddp-streamer/package.json b/ee/apps/ddp-streamer/package.json index a473780233578..a991ff7f39e8f 100644 --- a/ee/apps/ddp-streamer/package.json +++ b/ee/apps/ddp-streamer/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ddp-streamer", - "version": "0.3.53-rc.2", + "version": "0.3.53-rc.3", "private": true, "description": "Rocket.Chat DDP-Streamer service", "keywords": [ diff --git a/ee/apps/omnichannel-transcript/CHANGELOG.md b/ee/apps/omnichannel-transcript/CHANGELOG.md index 8528f83ec0527..ddc1dcaf5a3f6 100644 --- a/ee/apps/omnichannel-transcript/CHANGELOG.md +++ b/ee/apps/omnichannel-transcript/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/omnichannel-transcript +## 0.4.53-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/omnichannel-services@0.3.50-rc.3 + - @rocket.chat/pdf-worker@0.3.32-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/model-typings@2.1.2-rc.3 + - @rocket.chat/models@2.1.2-rc.3 + - @rocket.chat/network-broker@0.2.32-rc.3 +
+ ## 0.4.53-rc.2 ### Patch Changes diff --git a/ee/apps/omnichannel-transcript/package.json b/ee/apps/omnichannel-transcript/package.json index 3429181295c24..8ff47a9151c3d 100644 --- a/ee/apps/omnichannel-transcript/package.json +++ b/ee/apps/omnichannel-transcript/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omnichannel-transcript", - "version": "0.4.53-rc.2", + "version": "0.4.53-rc.3", "private": true, "description": "Rocket.Chat service", "keywords": [ diff --git a/ee/apps/presence-service/CHANGELOG.md b/ee/apps/presence-service/CHANGELOG.md index b514f8b18fbef..9496dd14f3409 100644 --- a/ee/apps/presence-service/CHANGELOG.md +++ b/ee/apps/presence-service/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/presence-service +## 0.4.53-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/presence@0.2.53-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/model-typings@2.1.2-rc.3 + - @rocket.chat/models@2.1.2-rc.3 + - @rocket.chat/network-broker@0.2.32-rc.3 +
+ ## 0.4.53-rc.2 ### Patch Changes diff --git a/ee/apps/presence-service/package.json b/ee/apps/presence-service/package.json index e3938110259c2..b8280f75ade61 100644 --- a/ee/apps/presence-service/package.json +++ b/ee/apps/presence-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/presence-service", - "version": "0.4.53-rc.2", + "version": "0.4.53-rc.3", "private": true, "description": "Rocket.Chat Presence service", "keywords": [ diff --git a/ee/apps/queue-worker/CHANGELOG.md b/ee/apps/queue-worker/CHANGELOG.md index 6766408d64075..cf6a6479c5f32 100644 --- a/ee/apps/queue-worker/CHANGELOG.md +++ b/ee/apps/queue-worker/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/queue-worker +## 0.4.53-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/omnichannel-services@0.3.50-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/model-typings@2.1.2-rc.3 + - @rocket.chat/models@2.1.2-rc.3 + - @rocket.chat/network-broker@0.2.32-rc.3 +
+ ## 0.4.53-rc.2 ### Patch Changes diff --git a/ee/apps/queue-worker/package.json b/ee/apps/queue-worker/package.json index 64f00b9c4a24a..9716802b899c3 100644 --- a/ee/apps/queue-worker/package.json +++ b/ee/apps/queue-worker/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/queue-worker", - "version": "0.4.53-rc.2", + "version": "0.4.53-rc.3", "private": true, "description": "Rocket.Chat service", "keywords": [ diff --git a/ee/packages/abac/CHANGELOG.md b/ee/packages/abac/CHANGELOG.md index 3badd98098c6e..6facaa5c5da2f 100644 --- a/ee/packages/abac/CHANGELOG.md +++ b/ee/packages/abac/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/abac +## 0.1.6-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/models@2.1.2-rc.3 +
+ ## 0.1.6-rc.2 ### Patch Changes diff --git a/ee/packages/abac/package.json b/ee/packages/abac/package.json index 876c35b82ef9f..7ed19487b9ed8 100644 --- a/ee/packages/abac/package.json +++ b/ee/packages/abac/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/abac", - "version": "0.1.6-rc.2", + "version": "0.1.6-rc.3", "private": true, "description": "Rocket.Chat - Attribute Based Access Control (ABAC) support utilities", "main": "./dist/index.js", diff --git a/ee/packages/federation-matrix/CHANGELOG.md b/ee/packages/federation-matrix/CHANGELOG.md index c7fb7dddefc83..2a0634b4c8e0f 100644 --- a/ee/packages/federation-matrix/CHANGELOG.md +++ b/ee/packages/federation-matrix/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/federation-matrix +## 0.1.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 + - @rocket.chat/license@1.1.13-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/http-router@7.9.20-rc.3 + - @rocket.chat/models@2.1.2-rc.3 + - @rocket.chat/network-broker@0.2.32-rc.3 +
+ ## 0.1.0-rc.2 ### Patch Changes diff --git a/ee/packages/federation-matrix/package.json b/ee/packages/federation-matrix/package.json index 43dae56e3ca77..ab9ac1a8d8c7d 100644 --- a/ee/packages/federation-matrix/package.json +++ b/ee/packages/federation-matrix/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/federation-matrix", - "version": "0.1.0-rc.2", + "version": "0.1.0-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/license/CHANGELOG.md b/ee/packages/license/CHANGELOG.md index 52f4b8c1c07b8..b4e6380772688 100644 --- a/ee/packages/license/CHANGELOG.md +++ b/ee/packages/license/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/license +## 1.1.13-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 +
+ ## 1.1.13-rc.2 ### Patch Changes diff --git a/ee/packages/license/package.json b/ee/packages/license/package.json index 25ec0a3f06d2b..a0417dfebcccf 100644 --- a/ee/packages/license/package.json +++ b/ee/packages/license/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/license", - "version": "1.1.13-rc.2", + "version": "1.1.13-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/media-calls/CHANGELOG.md b/ee/packages/media-calls/CHANGELOG.md index b4cd7d3b64823..4020a1dc53450 100644 --- a/ee/packages/media-calls/CHANGELOG.md +++ b/ee/packages/media-calls/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/media-calls +## 0.3.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/models@2.1.2-rc.3 +
+ ## 0.3.0-rc.2 ### Patch Changes diff --git a/ee/packages/media-calls/package.json b/ee/packages/media-calls/package.json index 5cabc6c857a3c..e96559cb3e254 100644 --- a/ee/packages/media-calls/package.json +++ b/ee/packages/media-calls/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/media-calls", - "version": "0.3.0-rc.2", + "version": "0.3.0-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/network-broker/CHANGELOG.md b/ee/packages/network-broker/CHANGELOG.md index f7cf4d34d1d6a..5670d9c18fe89 100644 --- a/ee/packages/network-broker/CHANGELOG.md +++ b/ee/packages/network-broker/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/network-broker +## 0.2.32-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-services@0.13.2-rc.3 +
+ ## 0.2.32-rc.2 ### Patch Changes diff --git a/ee/packages/network-broker/package.json b/ee/packages/network-broker/package.json index 456ce217d4f20..b57e53f0656d0 100644 --- a/ee/packages/network-broker/package.json +++ b/ee/packages/network-broker/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/network-broker", - "version": "0.2.32-rc.2", + "version": "0.2.32-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/omni-core-ee/CHANGELOG.md b/ee/packages/omni-core-ee/CHANGELOG.md index 7c8580d61b6bf..9abdaffcdf5ae 100644 --- a/ee/packages/omni-core-ee/CHANGELOG.md +++ b/ee/packages/omni-core-ee/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/omni-core-ee +## 0.0.18-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/models@2.1.2-rc.3 + - @rocket.chat/omni-core@0.0.18-rc.3 +
+ ## 0.0.18-rc.2 ### Patch Changes diff --git a/ee/packages/omni-core-ee/package.json b/ee/packages/omni-core-ee/package.json index 54894d2942a0c..746bf6f6b8646 100644 --- a/ee/packages/omni-core-ee/package.json +++ b/ee/packages/omni-core-ee/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omni-core-ee", - "version": "0.0.18-rc.2", + "version": "0.0.18-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/omnichannel-services/CHANGELOG.md b/ee/packages/omnichannel-services/CHANGELOG.md index 7dd67baa4a9ac..5596dc1f25929 100644 --- a/ee/packages/omnichannel-services/CHANGELOG.md +++ b/ee/packages/omnichannel-services/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/omnichannel-services +## 0.3.50-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 + - @rocket.chat/pdf-worker@0.3.32-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/message-types@0.1.1-rc.0 + - @rocket.chat/model-typings@2.1.2-rc.3 + - @rocket.chat/models@2.1.2-rc.3 +
+ ## 0.3.50-rc.2 ### Patch Changes diff --git a/ee/packages/omnichannel-services/package.json b/ee/packages/omnichannel-services/package.json index c935bddd422c7..c29e912d52de1 100644 --- a/ee/packages/omnichannel-services/package.json +++ b/ee/packages/omnichannel-services/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omnichannel-services", - "version": "0.3.50-rc.2", + "version": "0.3.50-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/pdf-worker/CHANGELOG.md b/ee/packages/pdf-worker/CHANGELOG.md index 11ffaeb45755f..e6a9e79aa773e 100644 --- a/ee/packages/pdf-worker/CHANGELOG.md +++ b/ee/packages/pdf-worker/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/pdf-worker +## 0.3.32-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 +
+ ## 0.3.32-rc.2 ### Patch Changes diff --git a/ee/packages/pdf-worker/package.json b/ee/packages/pdf-worker/package.json index c67cea1269398..417f00a575d5e 100644 --- a/ee/packages/pdf-worker/package.json +++ b/ee/packages/pdf-worker/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/pdf-worker", - "version": "0.3.32-rc.2", + "version": "0.3.32-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/presence/CHANGELOG.md b/ee/packages/presence/CHANGELOG.md index b3116634a4ec8..0d2d700637cea 100644 --- a/ee/packages/presence/CHANGELOG.md +++ b/ee/packages/presence/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/presence +## 0.2.53-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/core-services@0.13.2-rc.3 + - @rocket.chat/models@2.1.2-rc.3 +
+ ## 0.2.53-rc.2 ### Patch Changes diff --git a/ee/packages/presence/package.json b/ee/packages/presence/package.json index dcc985d553e06..847fe5b941131 100644 --- a/ee/packages/presence/package.json +++ b/ee/packages/presence/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/presence", - "version": "0.2.53-rc.2", + "version": "0.2.53-rc.3", "private": true, "main": "./dist/Presence.js", "typings": "./dist/Presence.d.ts", diff --git a/package.json b/package.json index 72f5e2ef32676..001decfe1b384 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rocket.chat", - "version": "8.3.0-rc.2", + "version": "8.3.0-rc.3", "private": true, "description": "Rocket.Chat Monorepo", "homepage": "https://github.com/RocketChat/Rocket.Chat#readme", diff --git a/packages/api-client/CHANGELOG.md b/packages/api-client/CHANGELOG.md index 553c83a25f4d4..6e0faef679dcc 100644 --- a/packages/api-client/CHANGELOG.md +++ b/packages/api-client/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/api-client +## 0.2.53-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 +
+ ## 0.2.53-rc.2 ### Patch Changes diff --git a/packages/api-client/package.json b/packages/api-client/package.json index aec05ae5f9a1f..b17c5eedf0bff 100644 --- a/packages/api-client/package.json +++ b/packages/api-client/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/api-client", - "version": "0.2.53-rc.2", + "version": "0.2.53-rc.3", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/apps/CHANGELOG.md b/packages/apps/CHANGELOG.md index 7f8d8789d5a64..a46dda1bf8d2b 100644 --- a/packages/apps/CHANGELOG.md +++ b/packages/apps/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/apps +## 0.6.6-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/model-typings@2.1.2-rc.3 +
+ ## 0.6.6-rc.2 ### Patch Changes diff --git a/packages/apps/package.json b/packages/apps/package.json index 6abe510ee509e..86460b8bb9ea9 100644 --- a/packages/apps/package.json +++ b/packages/apps/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/apps", - "version": "0.6.6-rc.2", + "version": "0.6.6-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/core-services/CHANGELOG.md b/packages/core-services/CHANGELOG.md index 93175bd93aa98..3285ff9f0ed6b 100644 --- a/packages/core-services/CHANGELOG.md +++ b/packages/core-services/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/core-services +## 0.13.2-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 + - @rocket.chat/http-router@7.9.20-rc.3 + - @rocket.chat/models@2.1.2-rc.3 +
+ ## 0.13.2-rc.2 ### Patch Changes diff --git a/packages/core-services/package.json b/packages/core-services/package.json index 9d4646bc660dc..94457ae56c103 100644 --- a/packages/core-services/package.json +++ b/packages/core-services/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/core-services", - "version": "0.13.2-rc.2", + "version": "0.13.2-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/core-typings/CHANGELOG.md b/packages/core-typings/CHANGELOG.md index 36087a0d96ab4..c2ce9b5669d63 100644 --- a/packages/core-typings/CHANGELOG.md +++ b/packages/core-typings/CHANGELOG.md @@ -1,5 +1,7 @@ # @rocket.chat/core-typings +## 8.3.0-rc.3 + ## 8.3.0-rc.2 ## 8.3.0-rc.1 diff --git a/packages/core-typings/package.json b/packages/core-typings/package.json index 85e4944309d4e..cf8a635c1dc51 100644 --- a/packages/core-typings/package.json +++ b/packages/core-typings/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package", "name": "@rocket.chat/core-typings", - "version": "8.3.0-rc.2", + "version": "8.3.0-rc.3", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/cron/CHANGELOG.md b/packages/cron/CHANGELOG.md index 67b7cbecf131c..e6246f7e1a126 100644 --- a/packages/cron/CHANGELOG.md +++ b/packages/cron/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/cron +## 0.1.53-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/models@2.1.2-rc.3 +
+ ## 0.1.53-rc.2 ### Patch Changes diff --git a/packages/cron/package.json b/packages/cron/package.json index a8a040469bfe5..48ee223d89352 100644 --- a/packages/cron/package.json +++ b/packages/cron/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/cron", - "version": "0.1.53-rc.2", + "version": "0.1.53-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ddp-client/CHANGELOG.md b/packages/ddp-client/CHANGELOG.md index 2f25384257b6b..a8a31284e1898 100644 --- a/packages/ddp-client/CHANGELOG.md +++ b/packages/ddp-client/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/ddp-client +## 1.0.6-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 + - @rocket.chat/api-client@0.2.53-rc.3 +
+ ## 1.0.6-rc.2 ### Patch Changes diff --git a/packages/ddp-client/package.json b/packages/ddp-client/package.json index e3f26d827b13a..faf89f5376d69 100644 --- a/packages/ddp-client/package.json +++ b/packages/ddp-client/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ddp-client", - "version": "1.0.6-rc.2", + "version": "1.0.6-rc.3", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/fuselage-ui-kit/CHANGELOG.md b/packages/fuselage-ui-kit/CHANGELOG.md index b89317f5c415f..81790f32d0164 100644 --- a/packages/fuselage-ui-kit/CHANGELOG.md +++ b/packages/fuselage-ui-kit/CHANGELOG.md @@ -1,5 +1,18 @@ # Change Log +## 29.0.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/gazzodown@29.0.0-rc.3 + - @rocket.chat/ui-avatar@25.0.0-rc.3 + - @rocket.chat/ui-contexts@29.0.0-rc.3 + - @rocket.chat/ui-video-conf@29.0.0-rc.3 +
+ ## 29.0.0-rc.2 ### Patch Changes diff --git a/packages/fuselage-ui-kit/package.json b/packages/fuselage-ui-kit/package.json index 651d5165a409f..230cba7358f5f 100644 --- a/packages/fuselage-ui-kit/package.json +++ b/packages/fuselage-ui-kit/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/fuselage-ui-kit", - "version": "29.0.0-rc.2", + "version": "29.0.0-rc.3", "private": true, "description": "UiKit elements for Rocket.Chat Apps built under Fuselage design system", "homepage": "https://rocketchat.github.io/Rocket.Chat.Fuselage/", diff --git a/packages/gazzodown/CHANGELOG.md b/packages/gazzodown/CHANGELOG.md index 2455cc926c051..abb2b1b8395ea 100644 --- a/packages/gazzodown/CHANGELOG.md +++ b/packages/gazzodown/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/gazzodown +## 29.0.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/ui-client@29.0.0-rc.3 + - @rocket.chat/ui-contexts@29.0.0-rc.3 +
+ ## 29.0.0-rc.2 ### Patch Changes diff --git a/packages/gazzodown/package.json b/packages/gazzodown/package.json index 40230b211e91e..499d84e1eae0a 100644 --- a/packages/gazzodown/package.json +++ b/packages/gazzodown/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/gazzodown", - "version": "29.0.0-rc.2", + "version": "29.0.0-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/http-router/CHANGELOG.md b/packages/http-router/CHANGELOG.md index 1756de93b0c96..1877af3f68c6e 100644 --- a/packages/http-router/CHANGELOG.md +++ b/packages/http-router/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/http-router +## 7.9.20-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 +
+ ## 7.9.20-rc.2 ### Patch Changes diff --git a/packages/http-router/package.json b/packages/http-router/package.json index 3bae1bd9b9c5b..d54edfc428733 100644 --- a/packages/http-router/package.json +++ b/packages/http-router/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/http-router", - "version": "7.9.20-rc.2", + "version": "7.9.20-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/instance-status/CHANGELOG.md b/packages/instance-status/CHANGELOG.md index 4142efd61e528..4e6e653c86055 100644 --- a/packages/instance-status/CHANGELOG.md +++ b/packages/instance-status/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/instance-status +## 0.1.53-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/models@2.1.2-rc.3 +
+ ## 0.1.53-rc.2 ### Patch Changes diff --git a/packages/instance-status/package.json b/packages/instance-status/package.json index eecaca5eec6f1..29cdad407662a 100644 --- a/packages/instance-status/package.json +++ b/packages/instance-status/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/instance-status", - "version": "0.1.53-rc.2", + "version": "0.1.53-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/livechat/CHANGELOG.md b/packages/livechat/CHANGELOG.md index e801d1df8a9a5..5a278ccf4472a 100644 --- a/packages/livechat/CHANGELOG.md +++ b/packages/livechat/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/livechat Change Log +## 2.1.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/gazzodown@29.0.0-rc.3 +
+ ## 2.1.0-rc.2 ### Patch Changes diff --git a/packages/livechat/package.json b/packages/livechat/package.json index f7784bf04a5b0..0ee2d0bda5d22 100644 --- a/packages/livechat/package.json +++ b/packages/livechat/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/livechat", - "version": "2.1.0-rc.2", + "version": "2.1.0-rc.3", "homepage": "https://rocket.chat", "repository": { "type": "git", diff --git a/packages/mock-providers/CHANGELOG.md b/packages/mock-providers/CHANGELOG.md index 64aa73dbef963..653320bc62be5 100644 --- a/packages/mock-providers/CHANGELOG.md +++ b/packages/mock-providers/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/mock-providers +## 0.4.13-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/ui-contexts@29.0.0-rc.3 +
+ ## 0.4.13-rc.2 ### Patch Changes diff --git a/packages/mock-providers/package.json b/packages/mock-providers/package.json index bc06ec8ef95c4..0a60b8f2c146d 100644 --- a/packages/mock-providers/package.json +++ b/packages/mock-providers/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/mock-providers", - "version": "0.4.13-rc.2", + "version": "0.4.13-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/model-typings/CHANGELOG.md b/packages/model-typings/CHANGELOG.md index fa2cd1ee4e6dc..ba91bc66b8594 100644 --- a/packages/model-typings/CHANGELOG.md +++ b/packages/model-typings/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/model-typings +## 2.1.2-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 +
+ ## 2.1.2-rc.2 ### Patch Changes diff --git a/packages/model-typings/package.json b/packages/model-typings/package.json index 85d6287783c42..c8434fdf33d9c 100644 --- a/packages/model-typings/package.json +++ b/packages/model-typings/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/model-typings", - "version": "2.1.2-rc.2", + "version": "2.1.2-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/models/CHANGELOG.md b/packages/models/CHANGELOG.md index 6cd79f8ac0ab8..15c35fe23b4d6 100644 --- a/packages/models/CHANGELOG.md +++ b/packages/models/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/models +## 2.1.2-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/rest-typings@8.3.0-rc.3 + - @rocket.chat/model-typings@2.1.2-rc.3 +
+ ## 2.1.2-rc.2 ### Patch Changes diff --git a/packages/models/package.json b/packages/models/package.json index 2fa0a3748944d..ee5a124c8059b 100644 --- a/packages/models/package.json +++ b/packages/models/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/models", - "version": "2.1.2-rc.2", + "version": "2.1.2-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/omni-core/CHANGELOG.md b/packages/omni-core/CHANGELOG.md index d5e935fc3b7d0..b88a164fad208 100644 --- a/packages/omni-core/CHANGELOG.md +++ b/packages/omni-core/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/omni-core +## 0.0.18-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/models@2.1.2-rc.3 +
+ ## 0.0.18-rc.2 ### Patch Changes diff --git a/packages/omni-core/package.json b/packages/omni-core/package.json index 6a7c7a2393aed..8f34e2660acab 100644 --- a/packages/omni-core/package.json +++ b/packages/omni-core/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omni-core", - "version": "0.0.18-rc.2", + "version": "0.0.18-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/rest-typings/CHANGELOG.md b/packages/rest-typings/CHANGELOG.md index 874dc3236cc8b..b1d2cc4ce1576 100644 --- a/packages/rest-typings/CHANGELOG.md +++ b/packages/rest-typings/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/rest-typings +## 8.3.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 +
+ ## 8.3.0-rc.2 ### Patch Changes diff --git a/packages/rest-typings/package.json b/packages/rest-typings/package.json index ebfd985b8541a..7ec50c06128cb 100644 --- a/packages/rest-typings/package.json +++ b/packages/rest-typings/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/rest-typings", - "version": "8.3.0-rc.2", + "version": "8.3.0-rc.3", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/server-fetch/CHANGELOG.md b/packages/server-fetch/CHANGELOG.md index c65e41b1ab355..8e820b1cdf2a7 100644 --- a/packages/server-fetch/CHANGELOG.md +++ b/packages/server-fetch/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/server-fetch +## 0.1.2-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/models@2.1.2-rc.3 +
+ ## 0.1.2-rc.2 ### Patch Changes diff --git a/packages/server-fetch/package.json b/packages/server-fetch/package.json index c940b928c9948..5b80fb81c98a8 100644 --- a/packages/server-fetch/package.json +++ b/packages/server-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/server-fetch", - "version": "0.1.2-rc.2", + "version": "0.1.2-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-avatar/CHANGELOG.md b/packages/ui-avatar/CHANGELOG.md index aa4e994a1daf1..7ced66625026e 100644 --- a/packages/ui-avatar/CHANGELOG.md +++ b/packages/ui-avatar/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/ui-avatar +## 25.0.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/ui-contexts@29.0.0-rc.3 +
+ ## 25.0.0-rc.2 ### Patch Changes diff --git a/packages/ui-avatar/package.json b/packages/ui-avatar/package.json index 3997e6052ca46..8f38c52502a9a 100644 --- a/packages/ui-avatar/package.json +++ b/packages/ui-avatar/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-avatar", - "version": "25.0.0-rc.2", + "version": "25.0.0-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-client/CHANGELOG.md b/packages/ui-client/CHANGELOG.md index 293f2b78b55df..3d9b1b2a36e5a 100644 --- a/packages/ui-client/CHANGELOG.md +++ b/packages/ui-client/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/ui-client +## 29.0.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/ui-avatar@25.0.0-rc.3 + - @rocket.chat/ui-contexts@29.0.0-rc.3 +
+ ## 29.0.0-rc.2 ### Patch Changes diff --git a/packages/ui-client/package.json b/packages/ui-client/package.json index af496e75b2abe..ce1d190db49c5 100644 --- a/packages/ui-client/package.json +++ b/packages/ui-client/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-client", - "version": "29.0.0-rc.2", + "version": "29.0.0-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-contexts/CHANGELOG.md b/packages/ui-contexts/CHANGELOG.md index e25b193b95eb0..81e5495d5a196 100644 --- a/packages/ui-contexts/CHANGELOG.md +++ b/packages/ui-contexts/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/ui-contexts +## 29.0.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.3 + - @rocket.chat/rest-typings@8.3.0-rc.3 + - @rocket.chat/ddp-client@1.0.6-rc.3 +
+ ## 29.0.0-rc.2 ### Patch Changes diff --git a/packages/ui-contexts/package.json b/packages/ui-contexts/package.json index d924dd5aa867e..b55db1ae48dd4 100644 --- a/packages/ui-contexts/package.json +++ b/packages/ui-contexts/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-contexts", - "version": "29.0.0-rc.2", + "version": "29.0.0-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-video-conf/CHANGELOG.md b/packages/ui-video-conf/CHANGELOG.md index d46999e1cb176..9068eaf43ce65 100644 --- a/packages/ui-video-conf/CHANGELOG.md +++ b/packages/ui-video-conf/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/ui-video-conf +## 29.0.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/ui-avatar@25.0.0-rc.3 + - @rocket.chat/ui-contexts@29.0.0-rc.3 +
+ ## 29.0.0-rc.2 ### Patch Changes diff --git a/packages/ui-video-conf/package.json b/packages/ui-video-conf/package.json index a697d8d5f3016..be24b453c529b 100644 --- a/packages/ui-video-conf/package.json +++ b/packages/ui-video-conf/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-video-conf", - "version": "29.0.0-rc.2", + "version": "29.0.0-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-voip/CHANGELOG.md b/packages/ui-voip/CHANGELOG.md index 55e99617241f2..cec1e2ad60fc2 100644 --- a/packages/ui-voip/CHANGELOG.md +++ b/packages/ui-voip/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/ui-voip +## 19.0.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/fuselage-ui-kit@29.0.0-rc.3 + - @rocket.chat/ui-avatar@25.0.0-rc.3 + - @rocket.chat/ui-client@29.0.0-rc.3 + - @rocket.chat/ui-contexts@29.0.0-rc.3 +
+ ## 19.0.0-rc.2 ### Patch Changes diff --git a/packages/ui-voip/package.json b/packages/ui-voip/package.json index bd2e8370399e1..f274e0781026a 100644 --- a/packages/ui-voip/package.json +++ b/packages/ui-voip/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-voip", - "version": "19.0.0-rc.2", + "version": "19.0.0-rc.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/web-ui-registration/CHANGELOG.md b/packages/web-ui-registration/CHANGELOG.md index 3b072e6b8f9cb..d106812d6e8eb 100644 --- a/packages/web-ui-registration/CHANGELOG.md +++ b/packages/web-ui-registration/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/web-ui-registration +## 29.0.0-rc.3 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/ui-contexts@29.0.0-rc.3 +
+ ## 29.0.0-rc.2 ### Patch Changes diff --git a/packages/web-ui-registration/package.json b/packages/web-ui-registration/package.json index dd8b312ed19f8..395ce757fe0a7 100644 --- a/packages/web-ui-registration/package.json +++ b/packages/web-ui-registration/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/web-ui-registration", - "version": "29.0.0-rc.2", + "version": "29.0.0-rc.3", "private": true, "homepage": "https://rocket.chat", "main": "./dist/index.js", @@ -60,7 +60,7 @@ "peerDependencies": { "@rocket.chat/layout": "*", "@rocket.chat/tools": "0.2.5-rc.0", - "@rocket.chat/ui-contexts": "29.0.0-rc.2", + "@rocket.chat/ui-contexts": "29.0.0-rc.3", "@tanstack/react-query": "*", "react": "*", "react-hook-form": "*", From 4bce5954437d6dd9c25bd5910f3aea3b13b61e83 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 31 Mar 2026 16:15:56 -0300 Subject: [PATCH 15/51] test(federation): add tests for re-inviting RC users after leaving or being kicked (#39990) --- apps/meteor/package.json | 2 +- .../docker-compose/hs1/homeserver.yaml | 5 + ee/packages/federation-matrix/package.json | 2 +- .../tests/end-to-end/room.spec.ts | 140 ++++++++++++++++++ packages/core-services/package.json | 2 +- yarn.lock | 16 +- 6 files changed, 156 insertions(+), 11 deletions(-) diff --git a/apps/meteor/package.json b/apps/meteor/package.json index 7ccc0456809b1..f5bf7e07efd52 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -103,7 +103,7 @@ "@rocket.chat/emitter": "^0.32.0", "@rocket.chat/favicon": "workspace:^", "@rocket.chat/federation-matrix": "workspace:^", - "@rocket.chat/federation-sdk": "0.6.2", + "@rocket.chat/federation-sdk": "0.6.3", "@rocket.chat/fuselage": "^0.73.0", "@rocket.chat/fuselage-forms": "^1.0.0", "@rocket.chat/fuselage-hooks": "^0.40.0", diff --git a/ee/packages/federation-matrix/docker-compose/hs1/homeserver.yaml b/ee/packages/federation-matrix/docker-compose/hs1/homeserver.yaml index decb4ee98cd65..6db872a0559bf 100644 --- a/ee/packages/federation-matrix/docker-compose/hs1/homeserver.yaml +++ b/ee/packages/federation-matrix/docker-compose/hs1/homeserver.yaml @@ -72,6 +72,11 @@ rc_registration_token_validity: per_second: 10000 burst_count: 10000 +# Room creation +rc_room_creation: + per_second: 10000 + burst_count: 10000 + # Login (IP, account, and failed-attempt buckets) rc_login: address: diff --git a/ee/packages/federation-matrix/package.json b/ee/packages/federation-matrix/package.json index ab9ac1a8d8c7d..b2cef8f916234 100644 --- a/ee/packages/federation-matrix/package.json +++ b/ee/packages/federation-matrix/package.json @@ -22,7 +22,7 @@ "@rocket.chat/core-services": "workspace:^", "@rocket.chat/core-typings": "workspace:^", "@rocket.chat/emitter": "^0.32.0", - "@rocket.chat/federation-sdk": "0.6.2", + "@rocket.chat/federation-sdk": "0.6.3", "@rocket.chat/http-router": "workspace:^", "@rocket.chat/license": "workspace:^", "@rocket.chat/models": "workspace:^", diff --git a/ee/packages/federation-matrix/tests/end-to-end/room.spec.ts b/ee/packages/federation-matrix/tests/end-to-end/room.spec.ts index 8dfc338560c57..347f7bd4b8ebe 100644 --- a/ee/packages/federation-matrix/tests/end-to-end/room.spec.ts +++ b/ee/packages/federation-matrix/tests/end-to-end/room.spec.ts @@ -1809,6 +1809,146 @@ import { SynapseClient } from '../helper/synapse-client'; }); }); + describe('Re-inviting a RC user from Synapse after leaving or being kicked', () => { + describe('Kick a RC user from Synapse, send a message, then re-invite the same user', () => { + let matrixRoomId: string; + let channelName: string; + + beforeAll(async () => { + channelName = `federated-channel-reinvite-kicked-${Date.now()}`; + + // Step 1: Create a room on Synapse + matrixRoomId = await hs1AdminApp.createRoom(channelName); + + // Step 2: Invite RC user from Synapse + await hs1AdminApp.matrixClient.invite(matrixRoomId, federationConfig.rc1.adminMatrixUserId); + + // Step 3: RC user accepts the invite + const subscriptions = await getSubscriptions(rc1AdminRequestConfig); + const pendingInvitation = subscriptions.update.find( + (subscription) => subscription.status === 'INVITED' && subscription.fname?.includes(channelName), + ); + expect(pendingInvitation).not.toBeUndefined(); + + const rid = pendingInvitation!.rid!; + await acceptRoomInvite(rid, rc1AdminRequestConfig); + + // Wait for join to propagate to Synapse + await retry( + 'waiting for RC user join to propagate to Synapse', + async () => { + const member = await hs1AdminApp.findRoomMember(channelName, federationConfig.rc1.adminMatrixUserId); + expect(member?.membership).toBe('join'); + }, + { delayMs: 500 }, + ); + + // Step 4: Kick RC user from Synapse + await hs1AdminApp.matrixClient.kick(matrixRoomId, federationConfig.rc1.adminMatrixUserId, 'Kicked for re-invite test'); + + // Wait for kick to propagate to Synapse + await retry( + 'waiting for RC user kick to propagate to Synapse', + async () => { + const member = await hs1AdminApp.findRoomMember(channelName, federationConfig.rc1.adminMatrixUserId); + expect(member?.membership).toBe('leave'); + }, + { delayMs: 500 }, + ); + + // Step 5: Send a message from Synapse (while RC user is kicked) + await hs1AdminApp.matrixClient.sendTextMessage(matrixRoomId, 'Message sent after kicking RC user'); + }, 30000); + + it('should allow re-inviting the same RC user after being kicked', async () => { + // Step 6: Re-invite the same RC user from Synapse + await hs1AdminApp.matrixClient.invite(matrixRoomId, federationConfig.rc1.adminMatrixUserId); + + // Step 7: Validate the invite was created successfully on the RC side + const subscriptions = await getSubscriptions(rc1AdminRequestConfig); + const pendingInvitation = subscriptions.update.find( + (subscription) => subscription.status === 'INVITED' && subscription.fname?.includes(channelName), + ); + + expect(pendingInvitation).not.toBeUndefined(); + expect(pendingInvitation).toHaveProperty('rid'); + expect(pendingInvitation).toHaveProperty('fname'); + expect(pendingInvitation!.fname).toContain(channelName); + }); + }); + + describe('RC user leaves the room, Synapse sends a message, then re-invites the same user', () => { + let matrixRoomId: string; + let channelName: string; + + beforeAll(async () => { + channelName = `federated-channel-reinvite-left-${Date.now()}`; + + // Step 1: Create a room on Synapse + matrixRoomId = await hs1AdminApp.createRoom(channelName); + + // Step 2: Invite RC user from Synapse + await hs1AdminApp.matrixClient.invite(matrixRoomId, federationConfig.rc1.adminMatrixUserId); + + // Step 3: RC user accepts the invite + const subscriptions = await getSubscriptions(rc1AdminRequestConfig); + const pendingInvitation = subscriptions.update.find( + (subscription) => subscription.status === 'INVITED' && subscription.fname?.includes(channelName), + ); + expect(pendingInvitation).not.toBeUndefined(); + + const rid = pendingInvitation!.rid!; + await acceptRoomInvite(rid, rc1AdminRequestConfig); + + // Wait for join to propagate to Synapse + await retry( + 'waiting for RC user join to propagate to Synapse', + async () => { + const member = await hs1AdminApp.findRoomMember(channelName, federationConfig.rc1.adminMatrixUserId); + expect(member?.membership).toBe('join'); + }, + { delayMs: 500 }, + ); + + // Step 4: RC user leaves the room + await rc1AdminRequestConfig.request + .post(api('rooms.leave')) + .set(rc1AdminRequestConfig.credentials) + .send({ roomId: rid }) + .expect(200); + + // Wait for leave to propagate to Synapse + await retry( + 'waiting for RC user leave to propagate to Synapse', + async () => { + const member = await hs1AdminApp.findRoomMember(channelName, federationConfig.rc1.adminMatrixUserId); + expect(member?.membership).toBe('leave'); + }, + { delayMs: 500 }, + ); + + // Step 5: Send a message from Synapse (while RC user has left) + await hs1AdminApp.matrixClient.sendTextMessage(matrixRoomId, 'Message sent after RC user left'); + }, 30000); + + it('should allow re-inviting the same RC user after they left', async () => { + // Step 6: Re-invite the same RC user from Synapse + await hs1AdminApp.matrixClient.invite(matrixRoomId, federationConfig.rc1.adminMatrixUserId); + + // Step 7: Validate the invite was created successfully on the RC side + const subscriptions = await getSubscriptions(rc1AdminRequestConfig); + const pendingInvitation = subscriptions.update.find( + (subscription) => subscription.status === 'INVITED' && subscription.fname?.includes(channelName), + ); + + expect(pendingInvitation).not.toBeUndefined(); + expect(pendingInvitation).toHaveProperty('rid'); + expect(pendingInvitation).toHaveProperty('fname'); + expect(pendingInvitation!.fname).toContain(channelName); + }); + }); + }); + describe.skip('Synchronizing user names across federated servers', () => { const ts = Date.now(); diff --git a/packages/core-services/package.json b/packages/core-services/package.json index 94457ae56c103..97aca0f9ad1a5 100644 --- a/packages/core-services/package.json +++ b/packages/core-services/package.json @@ -18,7 +18,7 @@ }, "dependencies": { "@rocket.chat/core-typings": "workspace:^", - "@rocket.chat/federation-sdk": "0.6.2", + "@rocket.chat/federation-sdk": "0.6.3", "@rocket.chat/http-router": "workspace:^", "@rocket.chat/icons": "~0.47.0", "@rocket.chat/media-signaling": "workspace:^", diff --git a/yarn.lock b/yarn.lock index 63aa64a700fe6..f24e6b61ad2ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9140,7 +9140,7 @@ __metadata: dependencies: "@rocket.chat/apps-engine": "workspace:^" "@rocket.chat/core-typings": "workspace:^" - "@rocket.chat/federation-sdk": "npm:0.6.2" + "@rocket.chat/federation-sdk": "npm:0.6.3" "@rocket.chat/http-router": "workspace:^" "@rocket.chat/icons": "npm:~0.47.0" "@rocket.chat/jest-presets": "workspace:~" @@ -9350,7 +9350,7 @@ __metadata: "@rocket.chat/core-typings": "workspace:^" "@rocket.chat/ddp-client": "workspace:^" "@rocket.chat/emitter": "npm:^0.32.0" - "@rocket.chat/federation-sdk": "npm:0.6.2" + "@rocket.chat/federation-sdk": "npm:0.6.3" "@rocket.chat/http-router": "workspace:^" "@rocket.chat/license": "workspace:^" "@rocket.chat/models": "workspace:^" @@ -9379,9 +9379,9 @@ __metadata: languageName: unknown linkType: soft -"@rocket.chat/federation-sdk@npm:0.6.2": - version: 0.6.2 - resolution: "@rocket.chat/federation-sdk@npm:0.6.2" +"@rocket.chat/federation-sdk@npm:0.6.3": + version: 0.6.3 + resolution: "@rocket.chat/federation-sdk@npm:0.6.3" dependencies: "@datastructures-js/priority-queue": "npm:^6.3.5" "@noble/ed25519": "npm:^3.0.0" @@ -9394,7 +9394,7 @@ __metadata: zod: "npm:~4.3.6" peerDependencies: typescript: ~5.9.2 - checksum: 10/dd21576de694e4f18dcde46d3357f5ca3b817e3f9f20d2b66b526a35c716faee870f7a72356c86c1b59c27beddd53225725e126c460cd5f52eaba964bb807bdf + checksum: 10/71c8667f3d63e0b4ef0d82ee2b7c7c707494c286cfadf0c6be7e0feed7abc8817b0dfd44bb249861f8411c7747fdcfcde996a1c63d9c2396bba19d7ecb5689ac languageName: node linkType: hard @@ -10001,7 +10001,7 @@ __metadata: "@rocket.chat/emitter": "npm:^0.32.0" "@rocket.chat/favicon": "workspace:^" "@rocket.chat/federation-matrix": "workspace:^" - "@rocket.chat/federation-sdk": "npm:0.6.2" + "@rocket.chat/federation-sdk": "npm:0.6.3" "@rocket.chat/fuselage": "npm:^0.73.0" "@rocket.chat/fuselage-forms": "npm:^1.0.0" "@rocket.chat/fuselage-hooks": "npm:^0.40.0" @@ -11366,7 +11366,7 @@ __metadata: peerDependencies: "@rocket.chat/layout": "*" "@rocket.chat/tools": 0.2.5-rc.0 - "@rocket.chat/ui-contexts": 29.0.0-rc.2 + "@rocket.chat/ui-contexts": 29.0.0-rc.3 "@tanstack/react-query": "*" react: "*" react-hook-form: "*" From 413d925507d7f94e357d0f8e674822b9889c9154 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Thu, 2 Apr 2026 06:52:09 -0600 Subject: [PATCH 16/51] regression: Omnichannel `inquiries.take` endpoint returning `[error]` instead of `error` for max chats limit (#40031) --- apps/meteor/app/livechat/server/lib/takeInquiry.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/meteor/app/livechat/server/lib/takeInquiry.ts b/apps/meteor/app/livechat/server/lib/takeInquiry.ts index 1c7541b276f72..3bea195ceaca2 100644 --- a/apps/meteor/app/livechat/server/lib/takeInquiry.ts +++ b/apps/meteor/app/livechat/server/lib/takeInquiry.ts @@ -55,9 +55,5 @@ export const takeInquiry = async ( username: user.username, }; - try { - await RoutingManager.takeInquiry(inquiry, agent, options ?? {}, room); - } catch (e: any) { - throw new Meteor.Error(e.message); - } + await RoutingManager.takeInquiry(inquiry, agent, options ?? {}, room); }; From 7de4d069fd13d4afb295bb80eb501007e3c0e114 Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Thu, 2 Apr 2026 16:57:04 -0300 Subject: [PATCH 17/51] regression: Sending thread message scrolls main channel to bottom (#40034) --- .../room/body/hooks/useHasNewMessages.ts | 4 + .../e2e/messaging-scroll-to-bottom.spec.ts | 121 ++++++++++++++++++ .../page-objects/fragments/home-content.ts | 15 +++ 3 files changed, 140 insertions(+) create mode 100644 apps/meteor/tests/e2e/messaging-scroll-to-bottom.spec.ts diff --git a/apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts b/apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts index 9080264a65f36..cbdc00ce0ea1e 100644 --- a/apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts +++ b/apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts @@ -71,6 +71,10 @@ export const useHasNewMessages = ( clientCallbacks.add( 'afterSaveMessage', (msg: IMessage) => { + if (msg.tmid) { + return; + } + if (msg.u._id === uid) { sendToBottom(); setHasNewMessages(false); diff --git a/apps/meteor/tests/e2e/messaging-scroll-to-bottom.spec.ts b/apps/meteor/tests/e2e/messaging-scroll-to-bottom.spec.ts new file mode 100644 index 0000000000000..57b426ba200b0 --- /dev/null +++ b/apps/meteor/tests/e2e/messaging-scroll-to-bottom.spec.ts @@ -0,0 +1,121 @@ +import { faker } from '@faker-js/faker'; +import type { Locator } from 'playwright-core'; + +import { Users } from './fixtures/userStates'; +import { HomeChannel } from './page-objects'; +import { deleteChannel } from './utils'; +import type { BaseTest } from './utils/test'; +import { expect, test } from './utils/test'; + +test.use({ storageState: Users.admin.state }); +test.describe.serial('Messaging scroll to bottom', () => { + let targetChannel: { name: string; _id: string }; + let poHomeChannel: HomeChannel; + let mainMessage: { _id: string }; + + const fillMessages = async (api: BaseTest['api']) => { + const firstResponse = await api.post('/chat.postMessage', { + roomId: targetChannel._id, + text: faker.lorem.paragraphs(6), + }); + + const { message: firstMessage } = await firstResponse.json(); + mainMessage = firstMessage; + + await Promise.all( + Array.from({ length: 4 }).map(() => + api.post('/chat.postMessage', { + roomId: targetChannel._id, + text: faker.lorem.paragraphs(6), + }), + ), + ); + + await Promise.all( + Array.from({ length: 5 }).map(() => + api.post('/chat.postMessage', { + roomId: targetChannel._id, + text: faker.lorem.paragraphs(6), + tmid: firstMessage._id, + }), + ), + ); + }; + + const scrollToTop = async (scroller: Locator) => { + await scroller.evaluate((el) => { + el.scrollTop = 0; + }); + await expect(scroller).toHaveJSProperty('scrollTop', 0); + }; + + const expectScrolledToBottom = async (scroller: Locator) => { + await expect.poll(() => scroller.evaluate((el) => Math.abs(el.scrollTop - (el.scrollHeight - el.clientHeight)) < 2)).toBe(true); + }; + + test.beforeAll(async ({ api }) => { + await api + .post('/channels.create', { name: faker.string.uuid() }) + .then((res) => res.json()) + .then((data) => { + targetChannel = data.channel; + }); + + await fillMessages(api); + }); + + test.beforeEach(async ({ page }) => { + poHomeChannel = new HomeChannel(page); + await page.goto(`/channel/${targetChannel._id}/thread/${mainMessage._id}`); + await poHomeChannel.content.waitForChannel(); + await poHomeChannel.content.waitForThread(); + }); + + test.afterAll(async ({ api }) => { + await deleteChannel(api, targetChannel.name); + }); + + test('should scroll the main message list to bottom when sending a message in the main channel', async ({ page }) => { + await page.setViewportSize({ width: 1023, height: 700 }); + + await scrollToTop(poHomeChannel.content.mainMessageListScroller); + + await poHomeChannel.content.sendMessage('main channel message'); + + await expectScrolledToBottom(poHomeChannel.content.mainMessageListScroller); + }); + + test('should scroll the thread message list to bottom when sending a message in the thread', async ({ page }) => { + await page.setViewportSize({ width: 1023, height: 700 }); + + await scrollToTop(poHomeChannel.content.threadMessageListScroller); + + await poHomeChannel.content.sendMessageInThread('new thread reply'); + + await expectScrolledToBottom(poHomeChannel.content.threadMessageListScroller); + }); + + test('should not scroll the main channel message list when sending a message in the thread', async ({ page }) => { + await page.setViewportSize({ width: 1023, height: 700 }); + + await scrollToTop(poHomeChannel.content.mainMessageListScroller); + await scrollToTop(poHomeChannel.content.threadMessageListScroller); + + await poHomeChannel.content.sendMessageInThread('another thread reply'); + + await expectScrolledToBottom(poHomeChannel.content.threadMessageListScroller); + await expect(poHomeChannel.content.mainMessageListScroller).toHaveJSProperty('scrollTop', 0); + }); + + test('should not scroll the thread message list when sending a message in the main channel', async ({ page }) => { + await page.setViewportSize({ width: 1023, height: 700 }); + + await scrollToTop(poHomeChannel.content.mainMessageListScroller); + await scrollToTop(poHomeChannel.content.threadMessageListScroller); + + await poHomeChannel.content.sendMessage('another main channel message'); + + await expectScrolledToBottom(poHomeChannel.content.mainMessageListScroller); + await expect(poHomeChannel.content.threadMessageListScroller).toHaveJSProperty('scrollTop', 0); + }); +}); diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts index d05b356dd5b0e..a9e4c0e18b65c 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts @@ -54,6 +54,14 @@ export class HomeContent { return this.mainMessageList.locator('[role="listitem"][aria-roledescription="message"]'); } + get mainMessageListScroller(): Locator { + return this.page.locator('[data-overlayscrollbars-viewport]', { has: this.mainMessageList }); + } + + get threadMessageListScroller(): Locator { + return this.page.locator('[data-overlayscrollbars-viewport]', { has: this.threadMessageList }); + } + get systemMessageListItems(): Locator { return this.mainMessageList.locator('[role="listitem"][aria-roledescription="system message"]'); } @@ -548,6 +556,13 @@ export class HomeContent { await expect(messageList).not.toHaveAttribute('aria-busy', 'true'); } + async waitForThread(): Promise { + const messageList = this.page.getByRole('list', { name: 'Thread message list', exact: true }); + await messageList.waitFor(); + + await expect(messageList).not.toHaveAttribute('aria-busy', 'true'); + } + async openReplyInThread(): Promise { await this.lastUserMessage.hover(); await this.lastUserMessage.getByRole('button', { name: 'Reply in thread' }).waitFor(); From fcf9bd49a2d73c44032adf6a964b391ae5a2ba46 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 2 Apr 2026 17:13:18 -0300 Subject: [PATCH 18/51] regression: enable REST type coercion back (#40035) --- .../tests/end-to-end/api/livechat/06-integrations.ts | 4 ++-- .../tests/end-to-end/api/livechat/12-priorites.ts | 11 +++++++++++ apps/meteor/tests/end-to-end/api/subscriptions.ts | 2 +- packages/rest-typings/src/v1/Ajv.ts | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/meteor/tests/end-to-end/api/livechat/06-integrations.ts b/apps/meteor/tests/end-to-end/api/livechat/06-integrations.ts index a036eb23046cc..0ccc395322c75 100644 --- a/apps/meteor/tests/end-to-end/api/livechat/06-integrations.ts +++ b/apps/meteor/tests/end-to-end/api/livechat/06-integrations.ts @@ -282,8 +282,8 @@ describe('LIVECHAT - Integrations', () => { LivechatWebhookUrl: 8000, }) .expect('Content-Type', 'application/json') - .expect(400); - expect(response.body).to.have.property('success', false); + .expect(200); + expect(response.body).to.have.property('success', true); }); it('should fail if a wrong setting is provided', async () => { const response = await request diff --git a/apps/meteor/tests/end-to-end/api/livechat/12-priorites.ts b/apps/meteor/tests/end-to-end/api/livechat/12-priorites.ts index 1d0c42394ad6d..7d5a57da0f4af 100644 --- a/apps/meteor/tests/end-to-end/api/livechat/12-priorites.ts +++ b/apps/meteor/tests/end-to-end/api/livechat/12-priorites.ts @@ -568,6 +568,17 @@ import { generateRandomSLAData } from '../../../e2e/utils/omnichannel/sla'; expect(response.body).to.have.property('error'); expect(response.body?.error).to.contain('invalid-params'); }); + it('should not fail to edit a priority with a PUT if using a boolean as name (it becomes a string)', async () => { + const response = await request + .put(api(`livechat/priorities/${priority._id}`)) + .set(credentials) + .send({ + name: false, + }) + .expect('Content-Type', 'application/json') + .expect(200); + expect(response.body).to.have.property('success', true); + }); it('should fail to update a non-existing priority', async () => { const response = await request .put(api('livechat/priorities/123')) diff --git a/apps/meteor/tests/end-to-end/api/subscriptions.ts b/apps/meteor/tests/end-to-end/api/subscriptions.ts index 76f6c86645da5..7379e59606aab 100644 --- a/apps/meteor/tests/end-to-end/api/subscriptions.ts +++ b/apps/meteor/tests/end-to-end/api/subscriptions.ts @@ -277,7 +277,7 @@ describe('[Subscriptions]', () => { .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); - expect(res.body).to.have.property('errorType', 'invalid-params'); + expect(res.body).to.have.property('error', 'error-invalid-subscription'); }) .end(done); }); diff --git a/packages/rest-typings/src/v1/Ajv.ts b/packages/rest-typings/src/v1/Ajv.ts index 4691f936fcbc2..db410b91baa5f 100644 --- a/packages/rest-typings/src/v1/Ajv.ts +++ b/packages/rest-typings/src/v1/Ajv.ts @@ -2,7 +2,7 @@ import Ajv from 'ajv'; import addFormats from 'ajv-formats'; const ajv = new Ajv({ - coerceTypes: false, + coerceTypes: true, allowUnionTypes: true, code: { source: true }, discriminator: true, From 89e46931816441f3b6ee6af721027946e0a5631f Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Thu, 2 Apr 2026 20:30:19 -0300 Subject: [PATCH 19/51] regression: Allow ban actions for non-federated rooms as well (#39987) Co-authored-by: Diego Sampaio --- .changeset/thick-nails-exist.md | 4 ++-- apps/meteor/app/api/server/v1/rooms.ts | 4 ++-- .../hooks/roomActions/useBannedUsersRoomAction.ts | 14 ++++---------- .../actions/useBanUserAction.tsx | 11 +++-------- apps/meteor/server/lib/unbanUserFromRoom.ts | 6 ++++-- 5 files changed, 15 insertions(+), 24 deletions(-) diff --git a/.changeset/thick-nails-exist.md b/.changeset/thick-nails-exist.md index 9150fe12335e3..985c251a2044e 100644 --- a/.changeset/thick-nails-exist.md +++ b/.changeset/thick-nails-exist.md @@ -1,5 +1,5 @@ --- -"@rocket.chat/meteor": patch +'@rocket.chat/meteor': minor --- -Adds support for ban management in federated rooms, enabling authorized users to ban and unban members via UI and slash commands. +Adds support for ban management in rooms, enabling authorized users to ban and unban members via UI and slash commands. diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index bb4278bbb70fb..ae02a578ab05c 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -34,6 +34,7 @@ import { eraseRoom } from '../../../../server/lib/eraseRoom'; import { findUsersOfRoomOrderedByRole } from '../../../../server/lib/findUsersOfRoomOrderedByRole'; import { openRoom } from '../../../../server/lib/openRoom'; import type { RoomRoles } from '../../../../server/lib/roles/getRoomRoles'; +import { unbanUserFromRoom } from '../../../../server/lib/unbanUserFromRoom'; import { hideRoomMethod } from '../../../../server/methods/hideRoom'; import { muteUserInRoom } from '../../../../server/methods/muteUserInRoom'; import { toggleFavoriteMethod } from '../../../../server/methods/toggleFavorite'; @@ -45,7 +46,6 @@ import { saveRoomSettings } from '../../../channel-settings/server/methods/saveR import { createDiscussion } from '../../../discussion/server/methods/createDiscussion'; import { FileUpload } from '../../../file-upload/server'; import { sendFileMessage } from '../../../file-upload/server/methods/sendFileMessage'; -import { executeUnbanUserFromRoom } from '../../../lib/server/functions/executeUnbanUserFromRoom'; import { syncRolePrioritiesForRoomIfRequired } from '../../../lib/server/functions/syncRolePrioritiesForRoomIfRequired'; import { executeArchiveRoom } from '../../../lib/server/methods/archiveRoom'; import { cleanRoomHistoryMethod } from '../../../lib/server/methods/cleanRoomHistory'; @@ -1333,7 +1333,7 @@ export const roomEndpoints = API.v1 return API.v1.failure('Invalid user'); } - await executeUnbanUserFromRoom(this.bodyParams.roomId, user, this.user); + await unbanUserFromRoom(this.userId, { rid: this.bodyParams.roomId, username: user.username }); return API.v1.success(); }, diff --git a/apps/meteor/client/hooks/roomActions/useBannedUsersRoomAction.ts b/apps/meteor/client/hooks/roomActions/useBannedUsersRoomAction.ts index d158489a9d4ff..e4bbbd9a371f3 100644 --- a/apps/meteor/client/hooks/roomActions/useBannedUsersRoomAction.ts +++ b/apps/meteor/client/hooks/roomActions/useBannedUsersRoomAction.ts @@ -1,24 +1,18 @@ -import { isRoomNativeFederated } from '@rocket.chat/core-typings'; import type { RoomToolboxActionConfig } from '@rocket.chat/ui-contexts'; -import { usePermission, useUser } from '@rocket.chat/ui-contexts'; +import { usePermission } from '@rocket.chat/ui-contexts'; import { lazy, useMemo } from 'react'; -import * as Federation from '../../lib/federation/Federation'; -import { useRoom, useRoomSubscription } from '../../views/room/contexts/RoomContext'; +import { useRoom } from '../../views/room/contexts/RoomContext'; const BannedUsers = lazy(() => import('../../views/room/contextualBar/BannedUsers')); export const useBannedUsersRoomAction = () => { const room = useRoom(); - const user = useUser(); - const subscription = useRoomSubscription(); const hasPermissionToBan = usePermission('ban-user', room._id); - const federationCanBan = isRoomNativeFederated(room) && Federation.isEditableByTheUser(user || undefined, room, subscription); - return useMemo((): RoomToolboxActionConfig | undefined => { - if (!hasPermissionToBan || !federationCanBan) { + if (!hasPermissionToBan) { return undefined; } @@ -31,5 +25,5 @@ export const useBannedUsersRoomAction = () => { order: 13, type: 'moderation', }; - }, [federationCanBan, hasPermissionToBan]); + }, [hasPermissionToBan]); }; diff --git a/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useBanUserAction.tsx b/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useBanUserAction.tsx index 43dfac319a3a5..8bc56c262b73e 100644 --- a/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useBanUserAction.tsx +++ b/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useBanUserAction.tsx @@ -1,10 +1,8 @@ import type { IRoom, IUser } from '@rocket.chat/core-typings'; -import { isRoomNativeFederated } from '@rocket.chat/core-typings'; -import { usePermission, useUser, useUserRoom, useUserSubscription } from '@rocket.chat/ui-contexts'; +import { usePermission, useUserRoom, useUserSubscription } from '@rocket.chat/ui-contexts'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import * as Federation from '../../../../../lib/federation/Federation'; import { getRoomDirectives } from '../../../lib/getRoomDirectives'; import { useBanUser } from '../../useBanUser'; import type { UserInfoAction } from '../useUserInfoActions'; @@ -12,7 +10,6 @@ import type { UserInfoAction } from '../useUserInfoActions'; export const useBanUserAction = (user: Pick, roomId: IRoom['_id']): UserInfoAction | undefined => { const { t } = useTranslation(); - const currentUser = useUser(); const room = useUserRoom(roomId); const subscription = useUserSubscription(roomId); @@ -27,14 +24,12 @@ export const useBanUserAction = (user: Pick, roomId: const { _id: uid, username } = user; const hasPermissionToBan = usePermission('ban-user', roomId); - const federationCanBan = isRoomNativeFederated(room) && Federation.isEditableByTheUser(currentUser || undefined, room, subscription); - const { roomCanBan } = getRoomDirectives({ room, showingUserId: uid, userSubscription: subscription }); const handleBan = useBanUser({ roomId }); return useMemo(() => { - if (!hasPermissionToBan || !federationCanBan || !roomCanBan) { + if (!hasPermissionToBan || !roomCanBan) { return undefined; } @@ -45,5 +40,5 @@ export const useBanUserAction = (user: Pick, roomId: type: 'moderation' as const, variant: 'danger' as const, }; - }, [handleBan, roomCanBan, federationCanBan, hasPermissionToBan, t, username]); + }, [handleBan, roomCanBan, hasPermissionToBan, t, username]); }; diff --git a/apps/meteor/server/lib/unbanUserFromRoom.ts b/apps/meteor/server/lib/unbanUserFromRoom.ts index 488a90239cb3b..65916b399a1aa 100644 --- a/apps/meteor/server/lib/unbanUserFromRoom.ts +++ b/apps/meteor/server/lib/unbanUserFromRoom.ts @@ -1,8 +1,10 @@ import { Rooms, Users } from '@rocket.chat/models'; +import { roomCoordinator } from './rooms/roomCoordinator'; import { canAccessRoomAsync } from '../../app/authorization/server'; import { hasPermissionAsync } from '../../app/authorization/server/functions/hasPermission'; import { executeUnbanUserFromRoom } from '../../app/lib/server/functions/executeUnbanUserFromRoom'; +import { RoomMemberActions } from '../../definition/IRoomTypeConfig'; export const unbanUserFromRoom = async (fromId: string, data: { rid: string; username: string }): Promise => { if (!(await hasPermissionAsync(fromId, 'ban-user', data.rid))) { @@ -10,8 +12,8 @@ export const unbanUserFromRoom = async (fromId: string, data: { rid: string; use } const room = await Rooms.findOneById(data.rid); - if (!room) { - throw new Error('Invalid room'); + if (!room || !(await roomCoordinator.getRoomDirectives(room.t).allowMemberAction(room, RoomMemberActions.BAN, fromId))) { + throw new Error('Not allowed'); } const fromUser = await Users.findOneById(fromId); From aad2007c07fc7afd79641e2ee4bdf05925cf75f7 Mon Sep 17 00:00:00 2001 From: rocketchat-github-ci Date: Thu, 2 Apr 2026 23:47:18 +0000 Subject: [PATCH 20/51] Release 8.3.0-rc.4 [no ci] --- .changeset/bump-patch-1775173623076.md | 5 +++ .changeset/pre.json | 1 + apps/meteor/CHANGELOG.md | 41 +++++++++++++++++++ apps/meteor/app/utils/rocketchat.info | 2 +- apps/meteor/ee/server/services/CHANGELOG.md | 14 +++++++ apps/meteor/ee/server/services/package.json | 2 +- apps/meteor/package.json | 2 +- apps/uikit-playground/CHANGELOG.md | 12 ++++++ apps/uikit-playground/package.json | 2 +- ee/apps/account-service/CHANGELOG.md | 14 +++++++ ee/apps/account-service/package.json | 2 +- ee/apps/authorization-service/CHANGELOG.md | 15 +++++++ ee/apps/authorization-service/package.json | 2 +- ee/apps/ddp-streamer/CHANGELOG.md | 15 +++++++ ee/apps/ddp-streamer/package.json | 2 +- ee/apps/omnichannel-transcript/CHANGELOG.md | 15 +++++++ ee/apps/omnichannel-transcript/package.json | 2 +- ee/apps/presence-service/CHANGELOG.md | 14 +++++++ ee/apps/presence-service/package.json | 2 +- ee/apps/queue-worker/CHANGELOG.md | 14 +++++++ ee/apps/queue-worker/package.json | 2 +- ee/packages/abac/CHANGELOG.md | 11 +++++ ee/packages/abac/package.json | 2 +- ee/packages/federation-matrix/CHANGELOG.md | 15 +++++++ ee/packages/federation-matrix/package.json | 2 +- ee/packages/license/CHANGELOG.md | 9 ++++ ee/packages/license/package.json | 2 +- ee/packages/media-calls/CHANGELOG.md | 10 +++++ ee/packages/media-calls/package.json | 2 +- ee/packages/network-broker/CHANGELOG.md | 9 ++++ ee/packages/network-broker/package.json | 2 +- ee/packages/omni-core-ee/CHANGELOG.md | 11 +++++ ee/packages/omni-core-ee/package.json | 2 +- ee/packages/omnichannel-services/CHANGELOG.md | 15 +++++++ ee/packages/omnichannel-services/package.json | 2 +- ee/packages/pdf-worker/CHANGELOG.md | 9 ++++ ee/packages/pdf-worker/package.json | 2 +- ee/packages/presence/CHANGELOG.md | 11 +++++ ee/packages/presence/package.json | 2 +- package.json | 2 +- packages/api-client/CHANGELOG.md | 10 +++++ packages/api-client/package.json | 2 +- packages/apps/CHANGELOG.md | 10 +++++ packages/apps/package.json | 2 +- packages/core-services/CHANGELOG.md | 12 ++++++ packages/core-services/package.json | 2 +- packages/core-typings/CHANGELOG.md | 2 + packages/core-typings/package.json | 2 +- packages/cron/CHANGELOG.md | 10 +++++ packages/cron/package.json | 2 +- packages/ddp-client/CHANGELOG.md | 11 +++++ packages/ddp-client/package.json | 2 +- packages/fuselage-ui-kit/CHANGELOG.md | 13 ++++++ packages/fuselage-ui-kit/package.json | 2 +- packages/gazzodown/CHANGELOG.md | 11 +++++ packages/gazzodown/package.json | 2 +- packages/http-router/CHANGELOG.md | 10 +++++ packages/http-router/package.json | 2 +- packages/instance-status/CHANGELOG.md | 9 ++++ packages/instance-status/package.json | 2 +- packages/livechat/CHANGELOG.md | 9 ++++ packages/livechat/package.json | 2 +- packages/mock-providers/CHANGELOG.md | 9 ++++ packages/mock-providers/package.json | 2 +- packages/model-typings/CHANGELOG.md | 9 ++++ packages/model-typings/package.json | 2 +- packages/models/CHANGELOG.md | 10 +++++ packages/models/package.json | 2 +- packages/omni-core/CHANGELOG.md | 9 ++++ packages/omni-core/package.json | 2 +- packages/rest-typings/CHANGELOG.md | 9 ++++ packages/rest-typings/package.json | 2 +- packages/server-fetch/CHANGELOG.md | 9 ++++ packages/server-fetch/package.json | 2 +- packages/ui-avatar/CHANGELOG.md | 9 ++++ packages/ui-avatar/package.json | 2 +- packages/ui-client/CHANGELOG.md | 10 +++++ packages/ui-client/package.json | 2 +- packages/ui-contexts/CHANGELOG.md | 11 +++++ packages/ui-contexts/package.json | 2 +- packages/ui-video-conf/CHANGELOG.md | 10 +++++ packages/ui-video-conf/package.json | 2 +- packages/ui-voip/CHANGELOG.md | 12 ++++++ packages/ui-voip/package.json | 2 +- packages/web-ui-registration/CHANGELOG.md | 9 ++++ packages/web-ui-registration/package.json | 4 +- 86 files changed, 527 insertions(+), 44 deletions(-) create mode 100644 .changeset/bump-patch-1775173623076.md diff --git a/.changeset/bump-patch-1775173623076.md b/.changeset/bump-patch-1775173623076.md new file mode 100644 index 0000000000000..e1eaa7980afb1 --- /dev/null +++ b/.changeset/bump-patch-1775173623076.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Bump @rocket.chat/meteor version. diff --git a/.changeset/pre.json b/.changeset/pre.json index 987bedbf85fe5..0da5f495d163a 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -83,6 +83,7 @@ "bump-patch-1774533301673", "bump-patch-1774666021169", "bump-patch-1774909627968", + "bump-patch-1775173623076", "clean-ears-fly", "eight-colts-kiss", "five-chicken-invite", diff --git a/apps/meteor/CHANGELOG.md b/apps/meteor/CHANGELOG.md index 48471a32bbb9c..ef99b7db28c6f 100644 --- a/apps/meteor/CHANGELOG.md +++ b/apps/meteor/CHANGELOG.md @@ -1,5 +1,46 @@ # @rocket.chat/meteor +## 8.3.0-rc.4 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 + - @rocket.chat/abac@0.1.6-rc.4 + - @rocket.chat/federation-matrix@0.1.0-rc.4 + - @rocket.chat/license@1.1.13-rc.4 + - @rocket.chat/media-calls@0.3.0-rc.4 + - @rocket.chat/omnichannel-services@0.3.50-rc.4 + - @rocket.chat/pdf-worker@0.3.32-rc.4 + - @rocket.chat/presence@0.2.53-rc.4 + - @rocket.chat/api-client@0.2.53-rc.4 + - @rocket.chat/apps@0.6.6-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/cron@0.1.53-rc.4 + - @rocket.chat/fuselage-ui-kit@29.0.0-rc.4 + - @rocket.chat/gazzodown@29.0.0-rc.4 + - @rocket.chat/http-router@7.9.20-rc.4 + - @rocket.chat/message-types@0.1.1-rc.0 + - @rocket.chat/model-typings@2.1.2-rc.4 + - @rocket.chat/ui-avatar@25.0.0-rc.4 + - @rocket.chat/ui-client@29.0.0-rc.4 + - @rocket.chat/ui-contexts@29.0.0-rc.4 + - @rocket.chat/ui-voip@19.0.0-rc.4 + - @rocket.chat/web-ui-registration@29.0.0-rc.4 + - @rocket.chat/models@2.1.2-rc.4 + - @rocket.chat/server-cloud-communication@0.0.3-rc.0 + - @rocket.chat/network-broker@0.2.32-rc.4 + - @rocket.chat/omni-core-ee@0.0.18-rc.4 + - @rocket.chat/ui-video-conf@29.0.0-rc.4 + - @rocket.chat/instance-status@0.1.53-rc.4 + - @rocket.chat/omni-core@0.0.18-rc.4 + - @rocket.chat/server-fetch@0.1.2-rc.4 +
+ ## 8.3.0-rc.3 ### Patch Changes diff --git a/apps/meteor/app/utils/rocketchat.info b/apps/meteor/app/utils/rocketchat.info index 3166b21bd6ea1..547de34360c67 100644 --- a/apps/meteor/app/utils/rocketchat.info +++ b/apps/meteor/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "8.3.0-rc.3" + "version": "8.3.0-rc.4" } diff --git a/apps/meteor/ee/server/services/CHANGELOG.md b/apps/meteor/ee/server/services/CHANGELOG.md index 9943153c5d126..3432573049d4e 100644 --- a/apps/meteor/ee/server/services/CHANGELOG.md +++ b/apps/meteor/ee/server/services/CHANGELOG.md @@ -1,5 +1,19 @@ # rocketchat-services +## 2.0.44-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/model-typings@2.1.2-rc.4 + - @rocket.chat/models@2.1.2-rc.4 + - @rocket.chat/network-broker@0.2.32-rc.4 +
+ ## 2.0.44-rc.3 ### Patch Changes diff --git a/apps/meteor/ee/server/services/package.json b/apps/meteor/ee/server/services/package.json index 9110263979d9d..2357f6a80aa70 100644 --- a/apps/meteor/ee/server/services/package.json +++ b/apps/meteor/ee/server/services/package.json @@ -1,7 +1,7 @@ { "name": "rocketchat-services", "private": true, - "version": "2.0.44-rc.3", + "version": "2.0.44-rc.4", "description": "Rocket.Chat Authorization service", "main": "index.js", "scripts": { diff --git a/apps/meteor/package.json b/apps/meteor/package.json index f5bf7e07efd52..1ca6d29a563c7 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/meteor", - "version": "8.3.0-rc.3", + "version": "8.3.0-rc.4", "private": true, "description": "The Ultimate Open Source WebChat Platform", "keywords": [ diff --git a/apps/uikit-playground/CHANGELOG.md b/apps/uikit-playground/CHANGELOG.md index f6c917045db24..7fa2672121492 100644 --- a/apps/uikit-playground/CHANGELOG.md +++ b/apps/uikit-playground/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/uikit-playground +## 0.7.9-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/fuselage-ui-kit@29.0.0-rc.4 + - @rocket.chat/ui-avatar@25.0.0-rc.4 + - @rocket.chat/ui-contexts@29.0.0-rc.4 +
+ ## 0.7.9-rc.3 ### Patch Changes diff --git a/apps/uikit-playground/package.json b/apps/uikit-playground/package.json index e3f3f704e7f3d..47c9b73b9b2ac 100644 --- a/apps/uikit-playground/package.json +++ b/apps/uikit-playground/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/uikit-playground", - "version": "0.7.9-rc.3", + "version": "0.7.9-rc.4", "private": true, "type": "module", "scripts": { diff --git a/ee/apps/account-service/CHANGELOG.md b/ee/apps/account-service/CHANGELOG.md index e193ac332f677..e8990a99a1de3 100644 --- a/ee/apps/account-service/CHANGELOG.md +++ b/ee/apps/account-service/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/account-service +## 0.4.53-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/model-typings@2.1.2-rc.4 + - @rocket.chat/models@2.1.2-rc.4 + - @rocket.chat/network-broker@0.2.32-rc.4 +
+ ## 0.4.53-rc.3 ### Patch Changes diff --git a/ee/apps/account-service/package.json b/ee/apps/account-service/package.json index bd9e46301d942..15a4f1fe22fbe 100644 --- a/ee/apps/account-service/package.json +++ b/ee/apps/account-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/account-service", - "version": "0.4.53-rc.3", + "version": "0.4.53-rc.4", "private": true, "description": "Rocket.Chat Account service", "keywords": [ diff --git a/ee/apps/authorization-service/CHANGELOG.md b/ee/apps/authorization-service/CHANGELOG.md index 6a07a0dc42454..5095bdf0bbca5 100644 --- a/ee/apps/authorization-service/CHANGELOG.md +++ b/ee/apps/authorization-service/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/authorization-service +## 0.5.6-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 + - @rocket.chat/abac@0.1.6-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/model-typings@2.1.2-rc.4 + - @rocket.chat/models@2.1.2-rc.4 + - @rocket.chat/network-broker@0.2.32-rc.4 +
+ ## 0.5.6-rc.3 ### Patch Changes diff --git a/ee/apps/authorization-service/package.json b/ee/apps/authorization-service/package.json index 1b4dedc4297d5..451421a2d7dc6 100644 --- a/ee/apps/authorization-service/package.json +++ b/ee/apps/authorization-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/authorization-service", - "version": "0.5.6-rc.3", + "version": "0.5.6-rc.4", "private": true, "description": "Rocket.Chat Authorization service", "keywords": [ diff --git a/ee/apps/ddp-streamer/CHANGELOG.md b/ee/apps/ddp-streamer/CHANGELOG.md index 61528633d4116..dd94fc18b8c0a 100644 --- a/ee/apps/ddp-streamer/CHANGELOG.md +++ b/ee/apps/ddp-streamer/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/ddp-streamer +## 0.3.53-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/model-typings@2.1.2-rc.4 + - @rocket.chat/models@2.1.2-rc.4 + - @rocket.chat/network-broker@0.2.32-rc.4 + - @rocket.chat/instance-status@0.1.53-rc.4 +
+ ## 0.3.53-rc.3 ### Patch Changes diff --git a/ee/apps/ddp-streamer/package.json b/ee/apps/ddp-streamer/package.json index a991ff7f39e8f..d1b34a6bd6b26 100644 --- a/ee/apps/ddp-streamer/package.json +++ b/ee/apps/ddp-streamer/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ddp-streamer", - "version": "0.3.53-rc.3", + "version": "0.3.53-rc.4", "private": true, "description": "Rocket.Chat DDP-Streamer service", "keywords": [ diff --git a/ee/apps/omnichannel-transcript/CHANGELOG.md b/ee/apps/omnichannel-transcript/CHANGELOG.md index ddc1dcaf5a3f6..0048a1b35ef0a 100644 --- a/ee/apps/omnichannel-transcript/CHANGELOG.md +++ b/ee/apps/omnichannel-transcript/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/omnichannel-transcript +## 0.4.53-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/omnichannel-services@0.3.50-rc.4 + - @rocket.chat/pdf-worker@0.3.32-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/model-typings@2.1.2-rc.4 + - @rocket.chat/models@2.1.2-rc.4 + - @rocket.chat/network-broker@0.2.32-rc.4 +
+ ## 0.4.53-rc.3 ### Patch Changes diff --git a/ee/apps/omnichannel-transcript/package.json b/ee/apps/omnichannel-transcript/package.json index 8ff47a9151c3d..9a76feb464c81 100644 --- a/ee/apps/omnichannel-transcript/package.json +++ b/ee/apps/omnichannel-transcript/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omnichannel-transcript", - "version": "0.4.53-rc.3", + "version": "0.4.53-rc.4", "private": true, "description": "Rocket.Chat service", "keywords": [ diff --git a/ee/apps/presence-service/CHANGELOG.md b/ee/apps/presence-service/CHANGELOG.md index 9496dd14f3409..b023bf136efb6 100644 --- a/ee/apps/presence-service/CHANGELOG.md +++ b/ee/apps/presence-service/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/presence-service +## 0.4.53-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/presence@0.2.53-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/model-typings@2.1.2-rc.4 + - @rocket.chat/models@2.1.2-rc.4 + - @rocket.chat/network-broker@0.2.32-rc.4 +
+ ## 0.4.53-rc.3 ### Patch Changes diff --git a/ee/apps/presence-service/package.json b/ee/apps/presence-service/package.json index b8280f75ade61..857925e9bf807 100644 --- a/ee/apps/presence-service/package.json +++ b/ee/apps/presence-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/presence-service", - "version": "0.4.53-rc.3", + "version": "0.4.53-rc.4", "private": true, "description": "Rocket.Chat Presence service", "keywords": [ diff --git a/ee/apps/queue-worker/CHANGELOG.md b/ee/apps/queue-worker/CHANGELOG.md index cf6a6479c5f32..072e95aff25f3 100644 --- a/ee/apps/queue-worker/CHANGELOG.md +++ b/ee/apps/queue-worker/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/queue-worker +## 0.4.53-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/omnichannel-services@0.3.50-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/model-typings@2.1.2-rc.4 + - @rocket.chat/models@2.1.2-rc.4 + - @rocket.chat/network-broker@0.2.32-rc.4 +
+ ## 0.4.53-rc.3 ### Patch Changes diff --git a/ee/apps/queue-worker/package.json b/ee/apps/queue-worker/package.json index 9716802b899c3..ece00ab46372a 100644 --- a/ee/apps/queue-worker/package.json +++ b/ee/apps/queue-worker/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/queue-worker", - "version": "0.4.53-rc.3", + "version": "0.4.53-rc.4", "private": true, "description": "Rocket.Chat service", "keywords": [ diff --git a/ee/packages/abac/CHANGELOG.md b/ee/packages/abac/CHANGELOG.md index 6facaa5c5da2f..8e3a63ff8ed5f 100644 --- a/ee/packages/abac/CHANGELOG.md +++ b/ee/packages/abac/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/abac +## 0.1.6-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/models@2.1.2-rc.4 +
+ ## 0.1.6-rc.3 ### Patch Changes diff --git a/ee/packages/abac/package.json b/ee/packages/abac/package.json index 7ed19487b9ed8..af34f15869b08 100644 --- a/ee/packages/abac/package.json +++ b/ee/packages/abac/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/abac", - "version": "0.1.6-rc.3", + "version": "0.1.6-rc.4", "private": true, "description": "Rocket.Chat - Attribute Based Access Control (ABAC) support utilities", "main": "./dist/index.js", diff --git a/ee/packages/federation-matrix/CHANGELOG.md b/ee/packages/federation-matrix/CHANGELOG.md index 2a0634b4c8e0f..d928159ca1c2a 100644 --- a/ee/packages/federation-matrix/CHANGELOG.md +++ b/ee/packages/federation-matrix/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/federation-matrix +## 0.1.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 + - @rocket.chat/license@1.1.13-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/http-router@7.9.20-rc.4 + - @rocket.chat/models@2.1.2-rc.4 + - @rocket.chat/network-broker@0.2.32-rc.4 +
+ ## 0.1.0-rc.3 ### Patch Changes diff --git a/ee/packages/federation-matrix/package.json b/ee/packages/federation-matrix/package.json index b2cef8f916234..90a319b9ec5ea 100644 --- a/ee/packages/federation-matrix/package.json +++ b/ee/packages/federation-matrix/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/federation-matrix", - "version": "0.1.0-rc.3", + "version": "0.1.0-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/license/CHANGELOG.md b/ee/packages/license/CHANGELOG.md index b4e6380772688..4c3b65cd3a2ce 100644 --- a/ee/packages/license/CHANGELOG.md +++ b/ee/packages/license/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/license +## 1.1.13-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 +
+ ## 1.1.13-rc.3 ### Patch Changes diff --git a/ee/packages/license/package.json b/ee/packages/license/package.json index a0417dfebcccf..e8dfbd3952004 100644 --- a/ee/packages/license/package.json +++ b/ee/packages/license/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/license", - "version": "1.1.13-rc.3", + "version": "1.1.13-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/media-calls/CHANGELOG.md b/ee/packages/media-calls/CHANGELOG.md index 4020a1dc53450..872f8abe541c6 100644 --- a/ee/packages/media-calls/CHANGELOG.md +++ b/ee/packages/media-calls/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/media-calls +## 0.3.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/models@2.1.2-rc.4 +
+ ## 0.3.0-rc.3 ### Patch Changes diff --git a/ee/packages/media-calls/package.json b/ee/packages/media-calls/package.json index e96559cb3e254..9e91e31e3036c 100644 --- a/ee/packages/media-calls/package.json +++ b/ee/packages/media-calls/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/media-calls", - "version": "0.3.0-rc.3", + "version": "0.3.0-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/network-broker/CHANGELOG.md b/ee/packages/network-broker/CHANGELOG.md index 5670d9c18fe89..7e9b2e3827fbb 100644 --- a/ee/packages/network-broker/CHANGELOG.md +++ b/ee/packages/network-broker/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/network-broker +## 0.2.32-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-services@0.13.2-rc.4 +
+ ## 0.2.32-rc.3 ### Patch Changes diff --git a/ee/packages/network-broker/package.json b/ee/packages/network-broker/package.json index b57e53f0656d0..ea58ec1ca06ad 100644 --- a/ee/packages/network-broker/package.json +++ b/ee/packages/network-broker/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/network-broker", - "version": "0.2.32-rc.3", + "version": "0.2.32-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/omni-core-ee/CHANGELOG.md b/ee/packages/omni-core-ee/CHANGELOG.md index 9abdaffcdf5ae..eaf672d9f41be 100644 --- a/ee/packages/omni-core-ee/CHANGELOG.md +++ b/ee/packages/omni-core-ee/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/omni-core-ee +## 0.0.18-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/models@2.1.2-rc.4 + - @rocket.chat/omni-core@0.0.18-rc.4 +
+ ## 0.0.18-rc.3 ### Patch Changes diff --git a/ee/packages/omni-core-ee/package.json b/ee/packages/omni-core-ee/package.json index 746bf6f6b8646..4289c77fe3d1c 100644 --- a/ee/packages/omni-core-ee/package.json +++ b/ee/packages/omni-core-ee/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omni-core-ee", - "version": "0.0.18-rc.3", + "version": "0.0.18-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/omnichannel-services/CHANGELOG.md b/ee/packages/omnichannel-services/CHANGELOG.md index 5596dc1f25929..288d91d179469 100644 --- a/ee/packages/omnichannel-services/CHANGELOG.md +++ b/ee/packages/omnichannel-services/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/omnichannel-services +## 0.3.50-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 + - @rocket.chat/pdf-worker@0.3.32-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/message-types@0.1.1-rc.0 + - @rocket.chat/model-typings@2.1.2-rc.4 + - @rocket.chat/models@2.1.2-rc.4 +
+ ## 0.3.50-rc.3 ### Patch Changes diff --git a/ee/packages/omnichannel-services/package.json b/ee/packages/omnichannel-services/package.json index c29e912d52de1..94987195643b7 100644 --- a/ee/packages/omnichannel-services/package.json +++ b/ee/packages/omnichannel-services/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omnichannel-services", - "version": "0.3.50-rc.3", + "version": "0.3.50-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/pdf-worker/CHANGELOG.md b/ee/packages/pdf-worker/CHANGELOG.md index e6a9e79aa773e..0d16dd87bbba3 100644 --- a/ee/packages/pdf-worker/CHANGELOG.md +++ b/ee/packages/pdf-worker/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/pdf-worker +## 0.3.32-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 +
+ ## 0.3.32-rc.3 ### Patch Changes diff --git a/ee/packages/pdf-worker/package.json b/ee/packages/pdf-worker/package.json index 417f00a575d5e..0f084d20a6270 100644 --- a/ee/packages/pdf-worker/package.json +++ b/ee/packages/pdf-worker/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/pdf-worker", - "version": "0.3.32-rc.3", + "version": "0.3.32-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/presence/CHANGELOG.md b/ee/packages/presence/CHANGELOG.md index 0d2d700637cea..13a0e26dc5ec7 100644 --- a/ee/packages/presence/CHANGELOG.md +++ b/ee/packages/presence/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/presence +## 0.2.53-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/core-services@0.13.2-rc.4 + - @rocket.chat/models@2.1.2-rc.4 +
+ ## 0.2.53-rc.3 ### Patch Changes diff --git a/ee/packages/presence/package.json b/ee/packages/presence/package.json index 847fe5b941131..86934bb75bda5 100644 --- a/ee/packages/presence/package.json +++ b/ee/packages/presence/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/presence", - "version": "0.2.53-rc.3", + "version": "0.2.53-rc.4", "private": true, "main": "./dist/Presence.js", "typings": "./dist/Presence.d.ts", diff --git a/package.json b/package.json index 001decfe1b384..0554ce138a6a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rocket.chat", - "version": "8.3.0-rc.3", + "version": "8.3.0-rc.4", "private": true, "description": "Rocket.Chat Monorepo", "homepage": "https://github.com/RocketChat/Rocket.Chat#readme", diff --git a/packages/api-client/CHANGELOG.md b/packages/api-client/CHANGELOG.md index 6e0faef679dcc..0717fc0c9cdac 100644 --- a/packages/api-client/CHANGELOG.md +++ b/packages/api-client/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/api-client +## 0.2.53-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 +
+ ## 0.2.53-rc.3 ### Patch Changes diff --git a/packages/api-client/package.json b/packages/api-client/package.json index b17c5eedf0bff..99c32dd305bb0 100644 --- a/packages/api-client/package.json +++ b/packages/api-client/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/api-client", - "version": "0.2.53-rc.3", + "version": "0.2.53-rc.4", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/apps/CHANGELOG.md b/packages/apps/CHANGELOG.md index a46dda1bf8d2b..689e49eb0f245 100644 --- a/packages/apps/CHANGELOG.md +++ b/packages/apps/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/apps +## 0.6.6-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/model-typings@2.1.2-rc.4 +
+ ## 0.6.6-rc.3 ### Patch Changes diff --git a/packages/apps/package.json b/packages/apps/package.json index 86460b8bb9ea9..87dfdb9161882 100644 --- a/packages/apps/package.json +++ b/packages/apps/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/apps", - "version": "0.6.6-rc.3", + "version": "0.6.6-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/core-services/CHANGELOG.md b/packages/core-services/CHANGELOG.md index 3285ff9f0ed6b..34e24af61a53c 100644 --- a/packages/core-services/CHANGELOG.md +++ b/packages/core-services/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/core-services +## 0.13.2-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 + - @rocket.chat/http-router@7.9.20-rc.4 + - @rocket.chat/models@2.1.2-rc.4 +
+ ## 0.13.2-rc.3 ### Patch Changes diff --git a/packages/core-services/package.json b/packages/core-services/package.json index 97aca0f9ad1a5..b26479c469c96 100644 --- a/packages/core-services/package.json +++ b/packages/core-services/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/core-services", - "version": "0.13.2-rc.3", + "version": "0.13.2-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/core-typings/CHANGELOG.md b/packages/core-typings/CHANGELOG.md index c2ce9b5669d63..30482e5955265 100644 --- a/packages/core-typings/CHANGELOG.md +++ b/packages/core-typings/CHANGELOG.md @@ -1,5 +1,7 @@ # @rocket.chat/core-typings +## 8.3.0-rc.4 + ## 8.3.0-rc.3 ## 8.3.0-rc.2 diff --git a/packages/core-typings/package.json b/packages/core-typings/package.json index cf8a635c1dc51..7909d35db1058 100644 --- a/packages/core-typings/package.json +++ b/packages/core-typings/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package", "name": "@rocket.chat/core-typings", - "version": "8.3.0-rc.3", + "version": "8.3.0-rc.4", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/cron/CHANGELOG.md b/packages/cron/CHANGELOG.md index e6246f7e1a126..82a24f3330f43 100644 --- a/packages/cron/CHANGELOG.md +++ b/packages/cron/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/cron +## 0.1.53-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/models@2.1.2-rc.4 +
+ ## 0.1.53-rc.3 ### Patch Changes diff --git a/packages/cron/package.json b/packages/cron/package.json index 48ee223d89352..881b191d6d3bf 100644 --- a/packages/cron/package.json +++ b/packages/cron/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/cron", - "version": "0.1.53-rc.3", + "version": "0.1.53-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ddp-client/CHANGELOG.md b/packages/ddp-client/CHANGELOG.md index a8a31284e1898..da99070fa01f6 100644 --- a/packages/ddp-client/CHANGELOG.md +++ b/packages/ddp-client/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/ddp-client +## 1.0.6-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 + - @rocket.chat/api-client@0.2.53-rc.4 +
+ ## 1.0.6-rc.3 ### Patch Changes diff --git a/packages/ddp-client/package.json b/packages/ddp-client/package.json index faf89f5376d69..0b7fbcd114037 100644 --- a/packages/ddp-client/package.json +++ b/packages/ddp-client/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ddp-client", - "version": "1.0.6-rc.3", + "version": "1.0.6-rc.4", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/fuselage-ui-kit/CHANGELOG.md b/packages/fuselage-ui-kit/CHANGELOG.md index 81790f32d0164..2147228ae123e 100644 --- a/packages/fuselage-ui-kit/CHANGELOG.md +++ b/packages/fuselage-ui-kit/CHANGELOG.md @@ -1,5 +1,18 @@ # Change Log +## 29.0.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/gazzodown@29.0.0-rc.4 + - @rocket.chat/ui-avatar@25.0.0-rc.4 + - @rocket.chat/ui-contexts@29.0.0-rc.4 + - @rocket.chat/ui-video-conf@29.0.0-rc.4 +
+ ## 29.0.0-rc.3 ### Patch Changes diff --git a/packages/fuselage-ui-kit/package.json b/packages/fuselage-ui-kit/package.json index 230cba7358f5f..736c46265f046 100644 --- a/packages/fuselage-ui-kit/package.json +++ b/packages/fuselage-ui-kit/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/fuselage-ui-kit", - "version": "29.0.0-rc.3", + "version": "29.0.0-rc.4", "private": true, "description": "UiKit elements for Rocket.Chat Apps built under Fuselage design system", "homepage": "https://rocketchat.github.io/Rocket.Chat.Fuselage/", diff --git a/packages/gazzodown/CHANGELOG.md b/packages/gazzodown/CHANGELOG.md index abb2b1b8395ea..1f2884159850b 100644 --- a/packages/gazzodown/CHANGELOG.md +++ b/packages/gazzodown/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/gazzodown +## 29.0.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/ui-client@29.0.0-rc.4 + - @rocket.chat/ui-contexts@29.0.0-rc.4 +
+ ## 29.0.0-rc.3 ### Patch Changes diff --git a/packages/gazzodown/package.json b/packages/gazzodown/package.json index 499d84e1eae0a..e24998d20dcb6 100644 --- a/packages/gazzodown/package.json +++ b/packages/gazzodown/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/gazzodown", - "version": "29.0.0-rc.3", + "version": "29.0.0-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/http-router/CHANGELOG.md b/packages/http-router/CHANGELOG.md index 1877af3f68c6e..6d6e9403499a1 100644 --- a/packages/http-router/CHANGELOG.md +++ b/packages/http-router/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/http-router +## 7.9.20-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 +
+ ## 7.9.20-rc.3 ### Patch Changes diff --git a/packages/http-router/package.json b/packages/http-router/package.json index d54edfc428733..0cb7192fd04d5 100644 --- a/packages/http-router/package.json +++ b/packages/http-router/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/http-router", - "version": "7.9.20-rc.3", + "version": "7.9.20-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/instance-status/CHANGELOG.md b/packages/instance-status/CHANGELOG.md index 4e6e653c86055..e032a56de0f7c 100644 --- a/packages/instance-status/CHANGELOG.md +++ b/packages/instance-status/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/instance-status +## 0.1.53-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/models@2.1.2-rc.4 +
+ ## 0.1.53-rc.3 ### Patch Changes diff --git a/packages/instance-status/package.json b/packages/instance-status/package.json index 29cdad407662a..83beb5c30c771 100644 --- a/packages/instance-status/package.json +++ b/packages/instance-status/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/instance-status", - "version": "0.1.53-rc.3", + "version": "0.1.53-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/livechat/CHANGELOG.md b/packages/livechat/CHANGELOG.md index 5a278ccf4472a..d2c3f8fe5bee3 100644 --- a/packages/livechat/CHANGELOG.md +++ b/packages/livechat/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/livechat Change Log +## 2.1.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/gazzodown@29.0.0-rc.4 +
+ ## 2.1.0-rc.3 ### Patch Changes diff --git a/packages/livechat/package.json b/packages/livechat/package.json index 0ee2d0bda5d22..d1720c7cfcb8a 100644 --- a/packages/livechat/package.json +++ b/packages/livechat/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/livechat", - "version": "2.1.0-rc.3", + "version": "2.1.0-rc.4", "homepage": "https://rocket.chat", "repository": { "type": "git", diff --git a/packages/mock-providers/CHANGELOG.md b/packages/mock-providers/CHANGELOG.md index 653320bc62be5..3ec062382cdcf 100644 --- a/packages/mock-providers/CHANGELOG.md +++ b/packages/mock-providers/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/mock-providers +## 0.4.13-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/ui-contexts@29.0.0-rc.4 +
+ ## 0.4.13-rc.3 ### Patch Changes diff --git a/packages/mock-providers/package.json b/packages/mock-providers/package.json index 0a60b8f2c146d..338de0816ca3a 100644 --- a/packages/mock-providers/package.json +++ b/packages/mock-providers/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/mock-providers", - "version": "0.4.13-rc.3", + "version": "0.4.13-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/model-typings/CHANGELOG.md b/packages/model-typings/CHANGELOG.md index ba91bc66b8594..80728292976cb 100644 --- a/packages/model-typings/CHANGELOG.md +++ b/packages/model-typings/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/model-typings +## 2.1.2-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 +
+ ## 2.1.2-rc.3 ### Patch Changes diff --git a/packages/model-typings/package.json b/packages/model-typings/package.json index c8434fdf33d9c..4156becf09d62 100644 --- a/packages/model-typings/package.json +++ b/packages/model-typings/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/model-typings", - "version": "2.1.2-rc.3", + "version": "2.1.2-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/models/CHANGELOG.md b/packages/models/CHANGELOG.md index 15c35fe23b4d6..f53ab7c06b5c4 100644 --- a/packages/models/CHANGELOG.md +++ b/packages/models/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/models +## 2.1.2-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/rest-typings@8.3.0-rc.4 + - @rocket.chat/model-typings@2.1.2-rc.4 +
+ ## 2.1.2-rc.3 ### Patch Changes diff --git a/packages/models/package.json b/packages/models/package.json index ee5a124c8059b..73ad9e7330d1d 100644 --- a/packages/models/package.json +++ b/packages/models/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/models", - "version": "2.1.2-rc.3", + "version": "2.1.2-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/omni-core/CHANGELOG.md b/packages/omni-core/CHANGELOG.md index b88a164fad208..2097c6d0ddb73 100644 --- a/packages/omni-core/CHANGELOG.md +++ b/packages/omni-core/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/omni-core +## 0.0.18-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/models@2.1.2-rc.4 +
+ ## 0.0.18-rc.3 ### Patch Changes diff --git a/packages/omni-core/package.json b/packages/omni-core/package.json index 8f34e2660acab..1c48140f80d0f 100644 --- a/packages/omni-core/package.json +++ b/packages/omni-core/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omni-core", - "version": "0.0.18-rc.3", + "version": "0.0.18-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/rest-typings/CHANGELOG.md b/packages/rest-typings/CHANGELOG.md index b1d2cc4ce1576..bf7106365ee04 100644 --- a/packages/rest-typings/CHANGELOG.md +++ b/packages/rest-typings/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/rest-typings +## 8.3.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 +
+ ## 8.3.0-rc.3 ### Patch Changes diff --git a/packages/rest-typings/package.json b/packages/rest-typings/package.json index 7ec50c06128cb..5ffcb33156a20 100644 --- a/packages/rest-typings/package.json +++ b/packages/rest-typings/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/rest-typings", - "version": "8.3.0-rc.3", + "version": "8.3.0-rc.4", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/server-fetch/CHANGELOG.md b/packages/server-fetch/CHANGELOG.md index 8e820b1cdf2a7..0ea6145009f99 100644 --- a/packages/server-fetch/CHANGELOG.md +++ b/packages/server-fetch/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/server-fetch +## 0.1.2-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/models@2.1.2-rc.4 +
+ ## 0.1.2-rc.3 ### Patch Changes diff --git a/packages/server-fetch/package.json b/packages/server-fetch/package.json index 5b80fb81c98a8..8e5ab109a6c9d 100644 --- a/packages/server-fetch/package.json +++ b/packages/server-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/server-fetch", - "version": "0.1.2-rc.3", + "version": "0.1.2-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-avatar/CHANGELOG.md b/packages/ui-avatar/CHANGELOG.md index 7ced66625026e..47da0cbb431c8 100644 --- a/packages/ui-avatar/CHANGELOG.md +++ b/packages/ui-avatar/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/ui-avatar +## 25.0.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/ui-contexts@29.0.0-rc.4 +
+ ## 25.0.0-rc.3 ### Patch Changes diff --git a/packages/ui-avatar/package.json b/packages/ui-avatar/package.json index 8f38c52502a9a..d8aec2b761238 100644 --- a/packages/ui-avatar/package.json +++ b/packages/ui-avatar/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-avatar", - "version": "25.0.0-rc.3", + "version": "25.0.0-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-client/CHANGELOG.md b/packages/ui-client/CHANGELOG.md index 3d9b1b2a36e5a..78a7415064ad4 100644 --- a/packages/ui-client/CHANGELOG.md +++ b/packages/ui-client/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/ui-client +## 29.0.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/ui-avatar@25.0.0-rc.4 + - @rocket.chat/ui-contexts@29.0.0-rc.4 +
+ ## 29.0.0-rc.3 ### Patch Changes diff --git a/packages/ui-client/package.json b/packages/ui-client/package.json index ce1d190db49c5..374465dccfed0 100644 --- a/packages/ui-client/package.json +++ b/packages/ui-client/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-client", - "version": "29.0.0-rc.3", + "version": "29.0.0-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-contexts/CHANGELOG.md b/packages/ui-contexts/CHANGELOG.md index 81e5495d5a196..56f6d2c8826d9 100644 --- a/packages/ui-contexts/CHANGELOG.md +++ b/packages/ui-contexts/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/ui-contexts +## 29.0.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.3.0-rc.4 + - @rocket.chat/rest-typings@8.3.0-rc.4 + - @rocket.chat/ddp-client@1.0.6-rc.4 +
+ ## 29.0.0-rc.3 ### Patch Changes diff --git a/packages/ui-contexts/package.json b/packages/ui-contexts/package.json index b55db1ae48dd4..8192cdb246dd1 100644 --- a/packages/ui-contexts/package.json +++ b/packages/ui-contexts/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-contexts", - "version": "29.0.0-rc.3", + "version": "29.0.0-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-video-conf/CHANGELOG.md b/packages/ui-video-conf/CHANGELOG.md index 9068eaf43ce65..5ef072fac264f 100644 --- a/packages/ui-video-conf/CHANGELOG.md +++ b/packages/ui-video-conf/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/ui-video-conf +## 29.0.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/ui-avatar@25.0.0-rc.4 + - @rocket.chat/ui-contexts@29.0.0-rc.4 +
+ ## 29.0.0-rc.3 ### Patch Changes diff --git a/packages/ui-video-conf/package.json b/packages/ui-video-conf/package.json index be24b453c529b..862db1de077fd 100644 --- a/packages/ui-video-conf/package.json +++ b/packages/ui-video-conf/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-video-conf", - "version": "29.0.0-rc.3", + "version": "29.0.0-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-voip/CHANGELOG.md b/packages/ui-voip/CHANGELOG.md index cec1e2ad60fc2..edeeaf877f143 100644 --- a/packages/ui-voip/CHANGELOG.md +++ b/packages/ui-voip/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/ui-voip +## 19.0.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/fuselage-ui-kit@29.0.0-rc.4 + - @rocket.chat/ui-avatar@25.0.0-rc.4 + - @rocket.chat/ui-client@29.0.0-rc.4 + - @rocket.chat/ui-contexts@29.0.0-rc.4 +
+ ## 19.0.0-rc.3 ### Patch Changes diff --git a/packages/ui-voip/package.json b/packages/ui-voip/package.json index f274e0781026a..f442786c1390a 100644 --- a/packages/ui-voip/package.json +++ b/packages/ui-voip/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-voip", - "version": "19.0.0-rc.3", + "version": "19.0.0-rc.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/web-ui-registration/CHANGELOG.md b/packages/web-ui-registration/CHANGELOG.md index d106812d6e8eb..a928e931f7bdd 100644 --- a/packages/web-ui-registration/CHANGELOG.md +++ b/packages/web-ui-registration/CHANGELOG.md @@ -1,5 +1,14 @@ # @rocket.chat/web-ui-registration +## 29.0.0-rc.4 + +### Patch Changes + +-
Updated dependencies []: + + - @rocket.chat/ui-contexts@29.0.0-rc.4 +
+ ## 29.0.0-rc.3 ### Patch Changes diff --git a/packages/web-ui-registration/package.json b/packages/web-ui-registration/package.json index 395ce757fe0a7..45843ad39fd29 100644 --- a/packages/web-ui-registration/package.json +++ b/packages/web-ui-registration/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/web-ui-registration", - "version": "29.0.0-rc.3", + "version": "29.0.0-rc.4", "private": true, "homepage": "https://rocket.chat", "main": "./dist/index.js", @@ -60,7 +60,7 @@ "peerDependencies": { "@rocket.chat/layout": "*", "@rocket.chat/tools": "0.2.5-rc.0", - "@rocket.chat/ui-contexts": "29.0.0-rc.3", + "@rocket.chat/ui-contexts": "29.0.0-rc.4", "@tanstack/react-query": "*", "react": "*", "react-hook-form": "*", From 788c161bb6c9544bec37034c93e2f60de1a6c316 Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Tue, 7 Apr 2026 09:01:34 -0300 Subject: [PATCH 21/51] feat: Remove Federation from Beta (#40006) Co-authored-by: Guilherme Gazzo --- .changeset/two-pianos-knock.md | 6 ++++++ apps/meteor/server/settings/federation-service.ts | 1 - packages/i18n/src/locales/en.i18n.json | 1 - packages/i18n/src/locales/nb.i18n.json | 1 - packages/i18n/src/locales/zh.i18n.json | 1 - 5 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 .changeset/two-pianos-knock.md diff --git a/.changeset/two-pianos-knock.md b/.changeset/two-pianos-knock.md new file mode 100644 index 0000000000000..abad913b9c5b4 --- /dev/null +++ b/.changeset/two-pianos-knock.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/i18n": minor +--- + +Removes the Federation beta callout as the feature leaves beta diff --git a/apps/meteor/server/settings/federation-service.ts b/apps/meteor/server/settings/federation-service.ts index 45205743b78a1..94e773c1c6e64 100644 --- a/apps/meteor/server/settings/federation-service.ts +++ b/apps/meteor/server/settings/federation-service.ts @@ -10,7 +10,6 @@ export const createFederationServiceSettings = async (): Promise => { enterprise: true, modules: ['federation'], invalidValue: false, - alert: 'Federation_Service_Alert', }); await this.add('Federation_Service_Domain', '', { diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index c6bb52defeaa6..4a66e6eb73290 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -2237,7 +2237,6 @@ "Federation_Service_EDU_Process_Receipt": "Process Receipt events", "Federation_Service_EDU_Process_Receipt_Alert": "Enabling receipt events may increase the load on your server and network traffic considerably, especially if you have many users. Only enable this option if you understand the implications and have the necessary resources to handle the additional load.", "Federation_Service_EDU_Process_Receipt_Description": "Send and receive events of message read receipts between federated servers.", - "Federation_Service_Alert": "Beta feature: Ready for Non-Critical Deployments
This feature is currently undergoing final performance and resilience audits and is not yet recommended for mission-critical production data. Functionality may still experience intermittent issues. Users must be explicitly granted the 'access-federation' permission by the Workspace Administrator to interact with federated rooms.", "Federation_Service_Domain": "Federated Domain", "Federation_Service_Domain_Description": "The domain that this server should respond to, for example: `acme.com`. This will be used as the suffix for user IDs (e.g., `@user:acme.com`).
If your chat server is accessible from a different domain than the one you want to use for federation, you should follow our documentation to configure the `.well-known` file on your web server.", "Federation_Service_Domain_Alert": "Inform only the domain, do not include http(s)://, slashes or any path after it.
Use something like `acme.com` and not `https://acme.com/chat`.", diff --git a/packages/i18n/src/locales/nb.i18n.json b/packages/i18n/src/locales/nb.i18n.json index ff9228060c876..d48782550d8f3 100644 --- a/packages/i18n/src/locales/nb.i18n.json +++ b/packages/i18n/src/locales/nb.i18n.json @@ -2224,7 +2224,6 @@ "Federation_Service_EDU_Process_Presence": "Prosess Tilstedeværelseshendelser", "Federation_Service_EDU_Process_Presence_Description": "Sende og motta hendelser om brukertilstedeværelse (online, offline osv.) mellom fødererte servere.", "Federation_Service_EDU_Process_Presence_Alert": "Hvis du aktiverer nærværshendelser, kan det øke belastningen på serveren og nettverkstrafikken betraktelig, spesielt hvis du har mange brukere. Aktiver dette alternativet bare hvis du forstår konsekvensene og har de nødvendige ressursene til å håndtere den ekstra belastningen.", - "Federation_Service_Alert": "Betafunksjon: Klar for ikke-kritiske distribusjoner
Denne funksjonen gjennomgår for øyeblikket de siste ytelses- og robusthetsrevisjonene, og anbefales ennå ikke for virksomhetskritiske produksjonsdata. Funksjonaliteten kan fortsatt oppleve periodiske problemer. Brukere må eksplisitt gis \"access-federation\"-tillatelse av Workspace Administrator for å kunne samhandle med fødererte rom.", "Federation_Service_Domain": "Føderert domene", "Federation_Service_Domain_Description": "Domenet som denne serveren skal svare til, for eksempel: `acme.com`. Dette vil bli brukt som suffiks for bruker-ID-er (f.eks. `@user:acme.com`).
Hvis chatteserveren din er tilgjengelig fra et annet domene enn det du ønsker å bruke for føderasjon, bør du følge dokumentasjonen vår for å konfigurere filen `.well-known` på webserveren din.", "Federation_Service_Domain_Alert": "Oppgi bare domenet, ikke inkluder http(s)://, skråstreker eller noen sti etter det.
Bruk noe sånt som `acme.com` og ikke `https://acme.com/chat`.", diff --git a/packages/i18n/src/locales/zh.i18n.json b/packages/i18n/src/locales/zh.i18n.json index 969dba1afbe34..b5be43299a0bb 100644 --- a/packages/i18n/src/locales/zh.i18n.json +++ b/packages/i18n/src/locales/zh.i18n.json @@ -2225,7 +2225,6 @@ "Federation_Service_EDU_Process_Presence": "处理在线状态事件", "Federation_Service_EDU_Process_Presence_Description": "在联邦服务器之间发送和接收用户在线状态(在线、离线等)事件。", "Federation_Service_EDU_Process_Presence_Alert": "启用在线状态事件可能会显著增加服务器负载和网络流量,尤其是在用户较多时。仅在你了解其影响并具备处理额外负载的资源时启用此选项。", - "Federation_Service_Alert": "测试功能:适用于非关键部署
此功能正在进行最终的性能与韧性审计,尚不推荐用于关键生产数据。 功能仍可能出现间歇性问题。用户必须由工作区管理员明确授予 'access-federation' 权限才能与联邦房间交互。", "Federation_Service_Domain": "联邦域名", "Federation_Service_Domain_Description": "此服务器应响应的域名,例如:`acme.com`。该域名将作为用户 ID 的后缀(如 `@user:acme.com`)。
如果你的聊天服务器可通过与联邦域名不同的域名访问,请按文档在 Web 服务器上配置 `.well-known` 文件。", "Federation_Service_Domain_Alert": "仅填写域名,不要包含 http(s)://、斜杠或其后的路径。
请使用 `acme.com`,而不是 `https://acme.com/chat`。", From 00a1efa3fde455359510349d827acd91ba67905e Mon Sep 17 00:00:00 2001 From: rocketchat-github-ci Date: Tue, 7 Apr 2026 12:12:37 +0000 Subject: [PATCH 22/51] Release 8.3.0 [no ci] --- .changeset/blue-points-dream.md | 5 - .changeset/blue-seals-leave.md | 7 - .changeset/bright-dots-march.md | 7 - .changeset/bump-patch-1774533301673.md | 5 - .changeset/bump-patch-1774666021169.md | 5 - .changeset/bump-patch-1774909627968.md | 5 - .changeset/bump-patch-1775173623076.md | 5 - .changeset/clean-ears-fly.md | 5 - .changeset/eight-colts-kiss.md | 6 - .changeset/five-chicken-invite.md | 6 - .changeset/fix-blockquote-empty-lines.md | 5 - .changeset/fix-message-parser-reduce-perf.md | 5 - .changeset/fix-register-workspace-i18n.md | 5 - .changeset/fix-trailing-punctuation-url.md | 5 - .changeset/fix-webhook-newline.md | 5 - .changeset/fluffy-turtles-admire.md | 6 - .changeset/healthy-dragons-crash.md | 9 - .changeset/honest-shrimps-cough.md | 5 - .changeset/hungry-monkeys-hang.md | 6 - .changeset/late-pots-teach.md | 6 - .changeset/little-eyes-kneel.md | 75 ------- .changeset/loud-weeks-protect.md | 5 - .changeset/many-glasses-care.md | 9 - .../migrate-chat-follow-unfollow-message.md | 6 - .../migrate-chat-star-unstar-message.md | 6 - .changeset/migrate-rooms-leave-endpoint.md | 6 - .changeset/nasty-candles-invent.md | 6 - .changeset/new-students-attack.md | 5 - .changeset/nice-penguins-rhyme.md | 5 - .changeset/nice-squids-smoke.md | 6 - .changeset/nine-otters-hug.md | 6 - .changeset/olive-hairs-report.md | 5 - .changeset/orange-paws-poke.md | 6 - .changeset/polite-plums-boil.md | 5 - .changeset/pre.json | 146 ------------- .changeset/pretty-jobs-juggle.md | 6 - .changeset/rare-planes-tan.md | 6 - .changeset/rare-waves-help.md | 6 - .changeset/red-windows-breathe.md | 5 - .../refactor-instances-api-chained-pattern.md | 5 - .../refactor-ldap-api-chained-pattern.md | 5 - .../refactor-presence-api-chained-pattern.md | 5 - .changeset/rude-plums-think.md | 5 - .changeset/shaggy-cars-watch.md | 6 - .changeset/shiny-pears-admire.md | 5 - .changeset/short-starfishes-provide.md | 6 - .changeset/small-pants-reflect.md | 5 - .changeset/spicy-drinks-carry.md | 6 - .changeset/spotty-news-burn.md | 9 - .changeset/spotty-poems-smash.md | 6 - .changeset/stale-elephants-type.md | 5 - .changeset/strict-ajv-coercion.md | 16 -- .changeset/sweet-terms-relax.md | 7 - .changeset/swift-badgers-try.md | 6 - .changeset/tame-dolphins-draw.md | 5 - .changeset/tame-humans-greet.md | 5 - .changeset/tame-tables-complain.md | 5 - .changeset/tender-papayas-jam.md | 5 - .changeset/thick-nails-exist.md | 5 - .changeset/tough-steaks-beam.md | 5 - .changeset/tricky-boxes-type.md | 6 - .changeset/twenty-colts-flash.md | 6 - .changeset/two-pianos-knock.md | 6 - .changeset/unlucky-impalas-matter.md | 5 - .changeset/weak-terms-shave.md | 6 - .changeset/wet-roses-call.md | 7 - .changeset/wicked-buckets-thank.md | 6 - apps/meteor/CHANGELOG.md | 195 ++++++++++++++++++ apps/meteor/app/utils/rocketchat.info | 2 +- apps/meteor/ee/server/services/CHANGELOG.md | 17 ++ apps/meteor/ee/server/services/package.json | 2 +- apps/meteor/package.json | 2 +- apps/uikit-playground/CHANGELOG.md | 14 ++ apps/uikit-playground/package.json | 2 +- ee/apps/account-service/CHANGELOG.md | 19 ++ ee/apps/account-service/package.json | 2 +- ee/apps/authorization-service/CHANGELOG.md | 19 ++ ee/apps/authorization-service/package.json | 2 +- ee/apps/ddp-streamer/CHANGELOG.md | 19 ++ ee/apps/ddp-streamer/package.json | 2 +- ee/apps/omnichannel-transcript/CHANGELOG.md | 21 ++ ee/apps/omnichannel-transcript/package.json | 2 +- ee/apps/presence-service/CHANGELOG.md | 18 ++ ee/apps/presence-service/package.json | 2 +- ee/apps/queue-worker/CHANGELOG.md | 18 ++ ee/apps/queue-worker/package.json | 2 +- ee/packages/abac/CHANGELOG.md | 14 ++ ee/packages/abac/package.json | 2 +- ee/packages/federation-matrix/CHANGELOG.md | 23 +++ ee/packages/federation-matrix/package.json | 2 +- ee/packages/license/CHANGELOG.md | 13 ++ ee/packages/license/package.json | 2 +- ee/packages/media-calls/CHANGELOG.md | 18 ++ ee/packages/media-calls/package.json | 2 +- ee/packages/network-broker/CHANGELOG.md | 11 + ee/packages/network-broker/package.json | 2 +- ee/packages/omni-core-ee/CHANGELOG.md | 14 ++ ee/packages/omni-core-ee/package.json | 2 +- ee/packages/omnichannel-services/CHANGELOG.md | 20 ++ ee/packages/omnichannel-services/package.json | 2 +- ee/packages/pdf-worker/CHANGELOG.md | 11 + ee/packages/pdf-worker/package.json | 2 +- ee/packages/presence/CHANGELOG.md | 13 ++ ee/packages/presence/package.json | 2 +- package.json | 2 +- packages/account-utils/CHANGELOG.md | 6 + packages/account-utils/package.json | 2 +- packages/agenda/CHANGELOG.md | 6 + packages/agenda/package.json | 2 +- packages/api-client/CHANGELOG.md | 12 ++ packages/api-client/package.json | 2 +- packages/apps-engine/CHANGELOG.md | 10 + packages/apps-engine/package.json | 2 +- packages/apps/CHANGELOG.md | 13 ++ packages/apps/package.json | 2 +- packages/base64/CHANGELOG.md | 6 + packages/base64/package.json | 2 +- packages/cas-validate/CHANGELOG.md | 6 + packages/cas-validate/package.json | 2 +- packages/core-services/CHANGELOG.md | 18 ++ packages/core-services/package.json | 2 +- packages/core-typings/CHANGELOG.md | 22 ++ packages/core-typings/package.json | 2 +- packages/cron/CHANGELOG.md | 15 ++ packages/cron/package.json | 2 +- packages/ddp-client/CHANGELOG.md | 14 ++ packages/ddp-client/package.json | 2 +- packages/desktop-api/CHANGELOG.md | 6 + packages/desktop-api/package.json | 2 +- packages/eslint-config/CHANGELOG.md | 6 + packages/eslint-config/package.json | 2 +- packages/favicon/CHANGELOG.md | 6 + packages/favicon/package.json | 2 +- packages/fuselage-ui-kit/CHANGELOG.md | 21 ++ packages/fuselage-ui-kit/package.json | 2 +- packages/gazzodown/CHANGELOG.md | 14 ++ packages/gazzodown/package.json | 4 +- packages/http-router/CHANGELOG.md | 13 ++ packages/http-router/package.json | 2 +- packages/i18n/CHANGELOG.md | 25 +++ packages/i18n/package.json | 2 +- packages/instance-status/CHANGELOG.md | 12 ++ packages/instance-status/package.json | 2 +- packages/jest-presets/CHANGELOG.md | 6 + packages/jest-presets/package.json | 2 +- packages/jwt/CHANGELOG.md | 6 + packages/jwt/package.json | 2 +- packages/livechat/CHANGELOG.md | 18 ++ packages/livechat/package.json | 2 +- packages/log-format/CHANGELOG.md | 6 + packages/log-format/package.json | 2 +- packages/logger/CHANGELOG.md | 6 + packages/logger/package.json | 2 +- packages/media-signaling/CHANGELOG.md | 10 + packages/media-signaling/package.json | 2 +- packages/message-parser/CHANGELOG.md | 14 ++ packages/message-parser/package.json | 2 +- packages/message-types/CHANGELOG.md | 6 + packages/message-types/package.json | 2 +- packages/mock-providers/CHANGELOG.md | 12 ++ packages/mock-providers/package.json | 2 +- packages/model-typings/CHANGELOG.md | 15 ++ packages/model-typings/package.json | 2 +- packages/models/CHANGELOG.md | 23 +++ packages/models/package.json | 2 +- packages/mongo-adapter/CHANGELOG.md | 6 + packages/mongo-adapter/package.json | 2 +- packages/node-poplib/CHANGELOG.md | 6 + packages/node-poplib/package.json | 2 +- packages/omni-core/CHANGELOG.md | 12 ++ packages/omni-core/package.json | 2 +- packages/password-policies/CHANGELOG.md | 6 + packages/password-policies/package.json | 2 +- packages/patch-injection/CHANGELOG.md | 6 + packages/patch-injection/package.json | 2 +- packages/peggy-loader/CHANGELOG.md | 6 + packages/peggy-loader/package.json | 2 +- packages/random/CHANGELOG.md | 6 + packages/random/package.json | 2 +- packages/release-action/CHANGELOG.md | 6 + packages/release-action/package.json | 2 +- packages/release-changelog/CHANGELOG.md | 6 + packages/release-changelog/package.json | 2 +- packages/rest-typings/CHANGELOG.md | 63 ++++++ packages/rest-typings/package.json | 2 +- .../server-cloud-communication/CHANGELOG.md | 6 + .../server-cloud-communication/package.json | 2 +- packages/server-fetch/CHANGELOG.md | 13 ++ packages/server-fetch/package.json | 2 +- packages/sha256/CHANGELOG.md | 6 + packages/sha256/package.json | 2 +- packages/storybook-config/CHANGELOG.md | 6 + packages/storybook-config/package.json | 2 +- packages/tools/CHANGELOG.md | 6 + packages/tools/package.json | 2 +- packages/tracing/CHANGELOG.md | 6 + packages/tracing/package.json | 2 +- packages/ui-avatar/CHANGELOG.md | 11 + packages/ui-avatar/package.json | 2 +- packages/ui-client/CHANGELOG.md | 12 ++ packages/ui-client/package.json | 2 +- packages/ui-composer/CHANGELOG.md | 10 + packages/ui-composer/package.json | 2 +- packages/ui-contexts/CHANGELOG.md | 17 ++ packages/ui-contexts/package.json | 2 +- packages/ui-kit/CHANGELOG.md | 10 + packages/ui-kit/package.json | 2 +- packages/ui-video-conf/CHANGELOG.md | 12 ++ packages/ui-video-conf/package.json | 2 +- packages/ui-voip/CHANGELOG.md | 22 ++ packages/ui-voip/package.json | 2 +- packages/web-ui-registration/CHANGELOG.md | 14 ++ packages/web-ui-registration/package.json | 6 +- yarn.lock | 2 +- 214 files changed, 1182 insertions(+), 680 deletions(-) delete mode 100644 .changeset/blue-points-dream.md delete mode 100644 .changeset/blue-seals-leave.md delete mode 100644 .changeset/bright-dots-march.md delete mode 100644 .changeset/bump-patch-1774533301673.md delete mode 100644 .changeset/bump-patch-1774666021169.md delete mode 100644 .changeset/bump-patch-1774909627968.md delete mode 100644 .changeset/bump-patch-1775173623076.md delete mode 100644 .changeset/clean-ears-fly.md delete mode 100644 .changeset/eight-colts-kiss.md delete mode 100644 .changeset/five-chicken-invite.md delete mode 100644 .changeset/fix-blockquote-empty-lines.md delete mode 100644 .changeset/fix-message-parser-reduce-perf.md delete mode 100644 .changeset/fix-register-workspace-i18n.md delete mode 100644 .changeset/fix-trailing-punctuation-url.md delete mode 100644 .changeset/fix-webhook-newline.md delete mode 100644 .changeset/fluffy-turtles-admire.md delete mode 100644 .changeset/healthy-dragons-crash.md delete mode 100644 .changeset/honest-shrimps-cough.md delete mode 100644 .changeset/hungry-monkeys-hang.md delete mode 100644 .changeset/late-pots-teach.md delete mode 100644 .changeset/little-eyes-kneel.md delete mode 100644 .changeset/loud-weeks-protect.md delete mode 100644 .changeset/many-glasses-care.md delete mode 100644 .changeset/migrate-chat-follow-unfollow-message.md delete mode 100644 .changeset/migrate-chat-star-unstar-message.md delete mode 100644 .changeset/migrate-rooms-leave-endpoint.md delete mode 100644 .changeset/nasty-candles-invent.md delete mode 100644 .changeset/new-students-attack.md delete mode 100644 .changeset/nice-penguins-rhyme.md delete mode 100644 .changeset/nice-squids-smoke.md delete mode 100644 .changeset/nine-otters-hug.md delete mode 100644 .changeset/olive-hairs-report.md delete mode 100644 .changeset/orange-paws-poke.md delete mode 100644 .changeset/polite-plums-boil.md delete mode 100644 .changeset/pre.json delete mode 100644 .changeset/pretty-jobs-juggle.md delete mode 100644 .changeset/rare-planes-tan.md delete mode 100644 .changeset/rare-waves-help.md delete mode 100644 .changeset/red-windows-breathe.md delete mode 100644 .changeset/refactor-instances-api-chained-pattern.md delete mode 100644 .changeset/refactor-ldap-api-chained-pattern.md delete mode 100644 .changeset/refactor-presence-api-chained-pattern.md delete mode 100644 .changeset/rude-plums-think.md delete mode 100644 .changeset/shaggy-cars-watch.md delete mode 100644 .changeset/shiny-pears-admire.md delete mode 100644 .changeset/short-starfishes-provide.md delete mode 100644 .changeset/small-pants-reflect.md delete mode 100644 .changeset/spicy-drinks-carry.md delete mode 100644 .changeset/spotty-news-burn.md delete mode 100644 .changeset/spotty-poems-smash.md delete mode 100644 .changeset/stale-elephants-type.md delete mode 100644 .changeset/strict-ajv-coercion.md delete mode 100644 .changeset/sweet-terms-relax.md delete mode 100644 .changeset/swift-badgers-try.md delete mode 100644 .changeset/tame-dolphins-draw.md delete mode 100644 .changeset/tame-humans-greet.md delete mode 100644 .changeset/tame-tables-complain.md delete mode 100644 .changeset/tender-papayas-jam.md delete mode 100644 .changeset/thick-nails-exist.md delete mode 100644 .changeset/tough-steaks-beam.md delete mode 100644 .changeset/tricky-boxes-type.md delete mode 100644 .changeset/twenty-colts-flash.md delete mode 100644 .changeset/two-pianos-knock.md delete mode 100644 .changeset/unlucky-impalas-matter.md delete mode 100644 .changeset/weak-terms-shave.md delete mode 100644 .changeset/wet-roses-call.md delete mode 100644 .changeset/wicked-buckets-thank.md diff --git a/.changeset/blue-points-dream.md b/.changeset/blue-points-dream.md deleted file mode 100644 index eacb88108a0f7..0000000000000 --- a/.changeset/blue-points-dream.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) diff --git a/.changeset/blue-seals-leave.md b/.changeset/blue-seals-leave.md deleted file mode 100644 index 62f6e7e9003fd..0000000000000 --- a/.changeset/blue-seals-leave.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/model-typings": patch -"@rocket.chat/models": patch ---- - -Fixes an authorization issue that allowed users to confirm uploads from other users diff --git a/.changeset/bright-dots-march.md b/.changeset/bright-dots-march.md deleted file mode 100644 index 771343eea43f4..0000000000000 --- a/.changeset/bright-dots-march.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/meteor': patch -'@rocket.chat/model-typings': patch -'@rocket.chat/models': patch ---- - -Fixes main channel scroll position changing when jumping to a thread message from search diff --git a/.changeset/bump-patch-1774533301673.md b/.changeset/bump-patch-1774533301673.md deleted file mode 100644 index e1eaa7980afb1..0000000000000 --- a/.changeset/bump-patch-1774533301673.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Bump @rocket.chat/meteor version. diff --git a/.changeset/bump-patch-1774666021169.md b/.changeset/bump-patch-1774666021169.md deleted file mode 100644 index e1eaa7980afb1..0000000000000 --- a/.changeset/bump-patch-1774666021169.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Bump @rocket.chat/meteor version. diff --git a/.changeset/bump-patch-1774909627968.md b/.changeset/bump-patch-1774909627968.md deleted file mode 100644 index e1eaa7980afb1..0000000000000 --- a/.changeset/bump-patch-1774909627968.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Bump @rocket.chat/meteor version. diff --git a/.changeset/bump-patch-1775173623076.md b/.changeset/bump-patch-1775173623076.md deleted file mode 100644 index e1eaa7980afb1..0000000000000 --- a/.changeset/bump-patch-1775173623076.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Bump @rocket.chat/meteor version. diff --git a/.changeset/clean-ears-fly.md b/.changeset/clean-ears-fly.md deleted file mode 100644 index 781a8a4da4466..0000000000000 --- a/.changeset/clean-ears-fly.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes a cross-resource access issue that allowed users to retrieve emojis from the Custom Sounds endpoint and sounds from the Custom Emojis endpoint when using the FileSystem storage mode. diff --git a/.changeset/eight-colts-kiss.md b/.changeset/eight-colts-kiss.md deleted file mode 100644 index a163dd3637426..0000000000000 --- a/.changeset/eight-colts-kiss.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/federation-matrix": patch -"@rocket.chat/meteor": patch ---- - -Fixes an issue on Federation where all domains ending with the pattern where being allowed to communicate, the feature is meant to work with a list, url by url diff --git a/.changeset/five-chicken-invite.md b/.changeset/five-chicken-invite.md deleted file mode 100644 index 0c13329c3f84d..0000000000000 --- a/.changeset/five-chicken-invite.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/federation-matrix': minor -'@rocket.chat/meteor': minor ---- - -Adds support to name changes on federated rooms diff --git a/.changeset/fix-blockquote-empty-lines.md b/.changeset/fix-blockquote-empty-lines.md deleted file mode 100644 index b3b463f3913a6..0000000000000 --- a/.changeset/fix-blockquote-empty-lines.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/message-parser': patch ---- - -Fixed blockquotes with empty lines between paragraphs not rendering as a single blockquote. Lines like `> ` or `>` (empty quote lines) are now treated as part of the surrounding blockquote rather than breaking it into separate quotes. diff --git a/.changeset/fix-message-parser-reduce-perf.md b/.changeset/fix-message-parser-reduce-perf.md deleted file mode 100644 index 6601f8f205c43..0000000000000 --- a/.changeset/fix-message-parser-reduce-perf.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/message-parser': patch ---- - -Replaces wasteful `filter().shift()` with `find(Boolean)` in `extractFirstResult` to avoid allocating an intermediate filtered array just to get the first truthy element. diff --git a/.changeset/fix-register-workspace-i18n.md b/.changeset/fix-register-workspace-i18n.md deleted file mode 100644 index 62eed988444d9..0000000000000 --- a/.changeset/fix-register-workspace-i18n.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes wrong i18n key in RegisterWorkspace confirmation step so the text is translated instead of showing a missing key. diff --git a/.changeset/fix-trailing-punctuation-url.md b/.changeset/fix-trailing-punctuation-url.md deleted file mode 100644 index f55255a46e574..0000000000000 --- a/.changeset/fix-trailing-punctuation-url.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/message-parser": patch ---- - -Fixes trailing punctuation (e.g. periods, exclamation marks) being incorrectly included in parsed URLs when they appear at the end of a message. For example, `go to https://www.google.com.` now correctly parses the URL as `https://www.google.com` without the trailing period. diff --git a/.changeset/fix-webhook-newline.md b/.changeset/fix-webhook-newline.md deleted file mode 100644 index c622c57eb235b..0000000000000 --- a/.changeset/fix-webhook-newline.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes incoming webhook messages ignoring literal `\n` escape sequences, and fixes the `MarkdownText` `document` variant not rendering newlines as line breaks. diff --git a/.changeset/fluffy-turtles-admire.md b/.changeset/fluffy-turtles-admire.md deleted file mode 100644 index 3d21fa3ed7910..0000000000000 --- a/.changeset/fluffy-turtles-admire.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/models': patch -'@rocket.chat/meteor': patch ---- - -Fixes race condition causing duplicate open livechat rooms per visitor token. diff --git a/.changeset/healthy-dragons-crash.md b/.changeset/healthy-dragons-crash.md deleted file mode 100644 index f08337723f544..0000000000000 --- a/.changeset/healthy-dragons-crash.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@rocket.chat/fuselage-ui-kit': minor -'@rocket.chat/ui-kit': major -'@rocket.chat/apps-engine': minor -'@rocket.chat/livechat': minor -'@rocket.chat/meteor': minor ---- - -refactor(ui-kit): Remove UiKit deprecations diff --git a/.changeset/honest-shrimps-cough.md b/.changeset/honest-shrimps-cough.md deleted file mode 100644 index c7711d4a8cc73..0000000000000 --- a/.changeset/honest-shrimps-cough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes inconsistent username formatting causing '@@username' for federated users diff --git a/.changeset/hungry-monkeys-hang.md b/.changeset/hungry-monkeys-hang.md deleted file mode 100644 index f128167d7cee7..0000000000000 --- a/.changeset/hungry-monkeys-hang.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/rest-typings": minor ---- - -Add OpenAPI support for the Rocket.Chat autotranslate translateMessage API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation diff --git a/.changeset/late-pots-teach.md b/.changeset/late-pots-teach.md deleted file mode 100644 index 77d715c51fb80..0000000000000 --- a/.changeset/late-pots-teach.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/i18n": patch -"@rocket.chat/ui-voip": patch ---- - -Fixes mismatched translations for Voice calling UI diff --git a/.changeset/little-eyes-kneel.md b/.changeset/little-eyes-kneel.md deleted file mode 100644 index 2582804405acc..0000000000000 --- a/.changeset/little-eyes-kneel.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -'@rocket.chat/eslint-config': minor -'@rocket.chat/server-cloud-communication': patch -'@rocket.chat/omnichannel-services': patch -'@rocket.chat/omnichannel-transcript': patch -'@rocket.chat/authorization-service': patch -'@rocket.chat/federation-matrix': patch -'@rocket.chat/web-ui-registration': patch -'@rocket.chat/network-broker': patch -'@rocket.chat/password-policies': patch -'@rocket.chat/release-changelog': patch -'@rocket.chat/storybook-config': patch -'@rocket.chat/presence-service': patch -'@rocket.chat/omni-core-ee': patch -'@rocket.chat/fuselage-ui-kit': patch -'@rocket.chat/instance-status': patch -'@rocket.chat/media-signaling': patch -'@rocket.chat/patch-injection': patch -'@rocket.chat/account-service': patch -'@rocket.chat/media-calls': patch -'@rocket.chat/message-parser': patch -'@rocket.chat/mock-providers': patch -'@rocket.chat/release-action': patch -'@rocket.chat/pdf-worker': patch -'@rocket.chat/account-utils': patch -'@rocket.chat/core-services': patch -'@rocket.chat/message-types': patch -'@rocket.chat/model-typings': patch -'@rocket.chat/mongo-adapter': patch -'@rocket.chat/ui-video-conf': patch -'@rocket.chat/uikit-playground': patch -'@rocket.chat/cas-validate': patch -'@rocket.chat/core-typings': patch -'@rocket.chat/jest-presets': patch -'@rocket.chat/peggy-loader': patch -'@rocket.chat/rest-typings': patch -'@rocket.chat/server-fetch': patch -'@rocket.chat/ddp-streamer': patch -'@rocket.chat/queue-worker': patch -'@rocket.chat/presence': patch -'@rocket.chat/apps-engine': patch -'@rocket.chat/desktop-api': patch -'@rocket.chat/http-router': patch -'@rocket.chat/poplib': patch -'@rocket.chat/ui-composer': patch -'@rocket.chat/ui-contexts': patch -'@rocket.chat/license': patch -'@rocket.chat/api-client': patch -'@rocket.chat/ddp-client': patch -'@rocket.chat/log-format': patch -'@rocket.chat/gazzodown': patch -'@rocket.chat/omni-core': patch -'@rocket.chat/ui-avatar': patch -'@rocket.chat/ui-client': patch -'@rocket.chat/livechat': patch -'@rocket.chat/abac': patch -'@rocket.chat/favicon': patch -'@rocket.chat/tracing': patch -'@rocket.chat/ui-voip': patch -'@rocket.chat/agenda': patch -'@rocket.chat/base64': patch -'@rocket.chat/logger': patch -'@rocket.chat/models': patch -'@rocket.chat/random': patch -'@rocket.chat/sha256': patch -'@rocket.chat/ui-kit': patch -'@rocket.chat/tools': patch -'@rocket.chat/apps': patch -'@rocket.chat/cron': patch -'@rocket.chat/i18n': patch -'@rocket.chat/jwt': patch -'@rocket.chat/meteor': patch ---- - -chore(eslint): Upgrades ESLint and its configuration diff --git a/.changeset/loud-weeks-protect.md b/.changeset/loud-weeks-protect.md deleted file mode 100644 index 3317177f72765..0000000000000 --- a/.changeset/loud-weeks-protect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/message-parser': patch ---- - -Fixes ordered list AST generation to preserve `number: 0` for list items that start at index `0`. diff --git a/.changeset/many-glasses-care.md b/.changeset/many-glasses-care.md deleted file mode 100644 index e57d57f5cbe61..0000000000000 --- a/.changeset/many-glasses-care.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/i18n": minor -"@rocket.chat/media-signaling": minor -"@rocket.chat/ui-voip": minor -"@rocket.chat/media-calls": minor ---- - -Introduces native screen sharing for internal voice calls. This feature is currently in beta and can be disabled through admin settings. diff --git a/.changeset/migrate-chat-follow-unfollow-message.md b/.changeset/migrate-chat-follow-unfollow-message.md deleted file mode 100644 index 875c2ed9d1443..0000000000000 --- a/.changeset/migrate-chat-follow-unfollow-message.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/rest-typings": minor ---- - -Add OpenAPI support for the chat.followMessage and chat.unfollowMessage API endpoints by migrating to a modern chained route definition syntax and utilizing AJV schemas for body and response validation. diff --git a/.changeset/migrate-chat-star-unstar-message.md b/.changeset/migrate-chat-star-unstar-message.md deleted file mode 100644 index 395b6422747a5..0000000000000 --- a/.changeset/migrate-chat-star-unstar-message.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/rest-typings": minor ---- - -Add OpenAPI support for the chat.starMessage and chat.unStarMessage API endpoints by migrating to a modern chained route definition syntax and utilizing AJV schemas for body and response validation. diff --git a/.changeset/migrate-rooms-leave-endpoint.md b/.changeset/migrate-rooms-leave-endpoint.md deleted file mode 100644 index 4f9a6263a9a19..0000000000000 --- a/.changeset/migrate-rooms-leave-endpoint.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/meteor': minor -'@rocket.chat/rest-typings': minor ---- - -Migrated rooms.leave endpoint to new OpenAPI pattern with AJV validation diff --git a/.changeset/nasty-candles-invent.md b/.changeset/nasty-candles-invent.md deleted file mode 100644 index 2af4dcf9cebf1..0000000000000 --- a/.changeset/nasty-candles-invent.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/web-ui-registration': patch -'@rocket.chat/i18n': patch ---- - -Fixes invalid email domain error not being displayed on the registration form. diff --git a/.changeset/new-students-attack.md b/.changeset/new-students-attack.md deleted file mode 100644 index b1d4b56d505e1..0000000000000 --- a/.changeset/new-students-attack.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes an issue when forwarding messages to a password-protected room. diff --git a/.changeset/nice-penguins-rhyme.md b/.changeset/nice-penguins-rhyme.md deleted file mode 100644 index 5e89a31ef9739..0000000000000 --- a/.changeset/nice-penguins-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fix marking a message as sent before the request finishes diff --git a/.changeset/nice-squids-smoke.md b/.changeset/nice-squids-smoke.md deleted file mode 100644 index a71f10d915f97..0000000000000 --- a/.changeset/nice-squids-smoke.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/rest-typings": patch ---- - -Add OpenAPI support for the Rocket.Chat e2e.getUsersOfRoomWithoutKey endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. diff --git a/.changeset/nine-otters-hug.md b/.changeset/nine-otters-hug.md deleted file mode 100644 index 78868e3057732..0000000000000 --- a/.changeset/nine-otters-hug.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/rest-typings': minor -'@rocket.chat/meteor': minor ---- - -migrated rooms.delete endpoint to new OpenAPI pattern with AJV validation diff --git a/.changeset/olive-hairs-report.md b/.changeset/olive-hairs-report.md deleted file mode 100644 index fff0535e67cbc..0000000000000 --- a/.changeset/olive-hairs-report.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes version update banner showing outdated versions after server upgrade. diff --git a/.changeset/orange-paws-poke.md b/.changeset/orange-paws-poke.md deleted file mode 100644 index 2b49cea8f1442..0000000000000 --- a/.changeset/orange-paws-poke.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/i18n': patch -'@rocket.chat/meteor': patch ---- - -Deprecates `Anonymous write`. Feature will be removed in version 9.0.0. diff --git a/.changeset/polite-plums-boil.md b/.changeset/polite-plums-boil.md deleted file mode 100644 index b9263d979581b..0000000000000 --- a/.changeset/polite-plums-boil.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes the intermittent behavior where the "New messages" indicator appears incorrectly after the user sends a message diff --git a/.changeset/pre.json b/.changeset/pre.json deleted file mode 100644 index 0da5f495d163a..0000000000000 --- a/.changeset/pre.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "mode": "pre", - "tag": "rc", - "initialVersions": { - "@rocket.chat/meteor": "8.3.0-develop", - "rocketchat-services": "2.0.43", - "@rocket.chat/uikit-playground": "0.7.8", - "@rocket.chat/account-service": "0.4.52", - "@rocket.chat/authorization-service": "0.5.5", - "@rocket.chat/ddp-streamer": "0.3.52", - "@rocket.chat/omnichannel-transcript": "0.4.52", - "@rocket.chat/presence-service": "0.4.52", - "@rocket.chat/queue-worker": "0.4.52", - "@rocket.chat/abac": "0.1.5", - "@rocket.chat/federation-matrix": "0.0.14", - "@rocket.chat/license": "1.1.12", - "@rocket.chat/media-calls": "0.2.5", - "@rocket.chat/network-broker": "0.2.31", - "@rocket.chat/omni-core-ee": "0.0.17", - "@rocket.chat/omnichannel-services": "0.3.49", - "@rocket.chat/pdf-worker": "0.3.31", - "@rocket.chat/presence": "0.2.52", - "@rocket.chat/account-utils": "0.0.2", - "@rocket.chat/agenda": "0.1.0", - "@rocket.chat/api-client": "0.2.52", - "@rocket.chat/apps": "0.6.5", - "@rocket.chat/apps-engine": "1.60.0", - "@rocket.chat/base64": "1.0.13", - "@rocket.chat/cas-validate": "0.0.3", - "@rocket.chat/core-services": "0.13.1", - "@rocket.chat/core-typings": "8.3.0-develop", - "@rocket.chat/cron": "0.1.52", - "@rocket.chat/ddp-client": "1.0.5", - "@rocket.chat/desktop-api": "1.1.0", - "@rocket.chat/eslint-config": "0.7.0", - "@rocket.chat/favicon": "0.0.4", - "@rocket.chat/fuselage-ui-kit": "28.0.1", - "@rocket.chat/gazzodown": "28.0.1", - "@rocket.chat/http-router": "7.9.19", - "@rocket.chat/i18n": "2.1.0", - "@rocket.chat/instance-status": "0.1.52", - "@rocket.chat/jest-presets": "0.0.1", - "@rocket.chat/jwt": "0.2.0", - "@rocket.chat/livechat": "2.0.5", - "@rocket.chat/log-format": "0.0.2", - "@rocket.chat/logger": "1.0.0", - "@rocket.chat/media-signaling": "0.1.1", - "@rocket.chat/message-parser": "0.31.34", - "@rocket.chat/message-types": "0.1.0", - "@rocket.chat/mock-providers": "0.4.12", - "@rocket.chat/model-typings": "2.1.1", - "@rocket.chat/models": "2.1.1", - "@rocket.chat/mongo-adapter": "0.0.2", - "@rocket.chat/poplib": "0.0.2", - "@rocket.chat/omni-core": "0.0.17", - "@rocket.chat/password-policies": "0.1.0", - "@rocket.chat/patch-injection": "0.0.1", - "@rocket.chat/peggy-loader": "0.31.27", - "@rocket.chat/random": "1.2.2", - "@rocket.chat/release-action": "2.2.3", - "@rocket.chat/release-changelog": "0.1.0", - "@rocket.chat/rest-typings": "8.3.0-develop", - "@rocket.chat/server-cloud-communication": "0.0.2", - "@rocket.chat/server-fetch": "0.1.1", - "@rocket.chat/sha256": "1.0.12", - "@rocket.chat/storybook-config": "0.0.2", - "@rocket.chat/tools": "0.2.4", - "@rocket.chat/tracing": "0.0.1", - "@rocket.chat/tsconfig": "0.0.0", - "@rocket.chat/ui-avatar": "24.0.1", - "@rocket.chat/ui-client": "28.0.1", - "@rocket.chat/ui-composer": "0.5.3", - "@rocket.chat/ui-contexts": "28.0.1", - "@rocket.chat/ui-kit": "0.39.0", - "@rocket.chat/ui-video-conf": "28.0.1", - "@rocket.chat/ui-voip": "18.0.1", - "@rocket.chat/web-ui-registration": "28.0.1" - }, - "changesets": [ - "blue-points-dream", - "blue-seals-leave", - "bright-dots-march", - "bump-patch-1774533301673", - "bump-patch-1774666021169", - "bump-patch-1774909627968", - "bump-patch-1775173623076", - "clean-ears-fly", - "eight-colts-kiss", - "five-chicken-invite", - "fix-blockquote-empty-lines", - "fix-message-parser-reduce-perf", - "fix-register-workspace-i18n", - "fix-trailing-punctuation-url", - "fix-webhook-newline", - "fluffy-turtles-admire", - "healthy-dragons-crash", - "honest-shrimps-cough", - "hungry-monkeys-hang", - "late-pots-teach", - "little-eyes-kneel", - "loud-weeks-protect", - "many-glasses-care", - "migrate-chat-follow-unfollow-message", - "migrate-chat-star-unstar-message", - "migrate-rooms-leave-endpoint", - "nasty-candles-invent", - "new-students-attack", - "nice-penguins-rhyme", - "nice-squids-smoke", - "nine-otters-hug", - "olive-hairs-report", - "orange-paws-poke", - "polite-plums-boil", - "pretty-jobs-juggle", - "rare-planes-tan", - "rare-waves-help", - "red-windows-breathe", - "refactor-instances-api-chained-pattern", - "refactor-ldap-api-chained-pattern", - "refactor-presence-api-chained-pattern", - "rude-plums-think", - "shaggy-cars-watch", - "shiny-pears-admire", - "short-starfishes-provide", - "small-pants-reflect", - "spicy-drinks-carry", - "spotty-news-burn", - "spotty-poems-smash", - "stale-elephants-type", - "strict-ajv-coercion", - "sweet-terms-relax", - "swift-badgers-try", - "tame-dolphins-draw", - "tame-humans-greet", - "tame-tables-complain", - "tender-papayas-jam", - "thick-nails-exist", - "tough-steaks-beam", - "tricky-boxes-type", - "twenty-colts-flash", - "unlucky-impalas-matter", - "weak-terms-shave", - "wet-roses-call", - "wicked-buckets-thank" - ] -} diff --git a/.changeset/pretty-jobs-juggle.md b/.changeset/pretty-jobs-juggle.md deleted file mode 100644 index 028fc592dd034..0000000000000 --- a/.changeset/pretty-jobs-juggle.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/rest-typings': minor -'@rocket.chat/meteor': minor ---- - -Adds OpenAPI support for the Rocket.Chat e2e.updateGroupKey endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. diff --git a/.changeset/rare-planes-tan.md b/.changeset/rare-planes-tan.md deleted file mode 100644 index f1874e99ac6fc..0000000000000 --- a/.changeset/rare-planes-tan.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/core-typings': patch -'@rocket.chat/meteor': patch ---- - -Fixes an issue where emails were not saved for users logging in via the GitHub OAuth provider. diff --git a/.changeset/rare-waves-help.md b/.changeset/rare-waves-help.md deleted file mode 100644 index 476f7e0839153..0000000000000 --- a/.changeset/rare-waves-help.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/rest-typings": minor ---- - -Add OpenAPI support for the Rocket.Chat users.getAvatarSuggestion API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. diff --git a/.changeset/red-windows-breathe.md b/.changeset/red-windows-breathe.md deleted file mode 100644 index a177574edea6b..0000000000000 --- a/.changeset/red-windows-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes calendar events modifying the wrong status property when attempting to sync `busy` status. diff --git a/.changeset/refactor-instances-api-chained-pattern.md b/.changeset/refactor-instances-api-chained-pattern.md deleted file mode 100644 index e38ef1235e7ef..0000000000000 --- a/.changeset/refactor-instances-api-chained-pattern.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - - adds `instances.get` API endpoint to new chained pattern with response schemas diff --git a/.changeset/refactor-ldap-api-chained-pattern.md b/.changeset/refactor-ldap-api-chained-pattern.md deleted file mode 100644 index e402e8609cb46..0000000000000 --- a/.changeset/refactor-ldap-api-chained-pattern.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -Migrates `ldap.testConnection` and `ldap.testSearch` REST API endpoints from legacy `addRoute` pattern to the new chained `.post()` API pattern with typed response schemas and AJV body validation (replacing Meteor `check()`). diff --git a/.changeset/refactor-presence-api-chained-pattern.md b/.changeset/refactor-presence-api-chained-pattern.md deleted file mode 100644 index cec1816fce98b..0000000000000 --- a/.changeset/refactor-presence-api-chained-pattern.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -Migrates `presence.getConnections` and `presence.enableBroadcast` REST API endpoints from legacy `addRoute` pattern to the new chained `.get()`/`.post()` API pattern with typed response schemas. diff --git a/.changeset/rude-plums-think.md b/.changeset/rude-plums-think.md deleted file mode 100644 index 6b5804f013757..0000000000000 --- a/.changeset/rude-plums-think.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -Fixes Custom Sounds Contextualbar state and refresh behavior diff --git a/.changeset/shaggy-cars-watch.md b/.changeset/shaggy-cars-watch.md deleted file mode 100644 index 56db9fd9b4e74..0000000000000 --- a/.changeset/shaggy-cars-watch.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/ui-contexts": patch ---- - -Fixes a mismatch in the room icons on the sidebar items, ABAC Managed rooms were not displaying the correct icon diff --git a/.changeset/shiny-pears-admire.md b/.changeset/shiny-pears-admire.md deleted file mode 100644 index 0e8287d708f4e..0000000000000 --- a/.changeset/shiny-pears-admire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Limits `Outgoing webhook` maximum response size to 10mb. diff --git a/.changeset/short-starfishes-provide.md b/.changeset/short-starfishes-provide.md deleted file mode 100644 index 2d70c789a69cd..0000000000000 --- a/.changeset/short-starfishes-provide.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/rest-typings": minor ---- - -Add OpenAPI support for the Rocket.Chat e2e.fetchMyKeys endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. diff --git a/.changeset/small-pants-reflect.md b/.changeset/small-pants-reflect.md deleted file mode 100644 index a086551f4c8a9..0000000000000 --- a/.changeset/small-pants-reflect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes the download of attachments with non-unicode names on E2EE rooms diff --git a/.changeset/spicy-drinks-carry.md b/.changeset/spicy-drinks-carry.md deleted file mode 100644 index 1b2119694d4cc..0000000000000 --- a/.changeset/spicy-drinks-carry.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/rest-typings": patch ---- - -Add OpenAPI support for the Rocket.Chat push.test API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. diff --git a/.changeset/spotty-news-burn.md b/.changeset/spotty-news-burn.md deleted file mode 100644 index ffdb604dd1ced..0000000000000 --- a/.changeset/spotty-news-burn.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@rocket.chat/core-typings': minor -'@rocket.chat/rest-typings': minor -'@rocket.chat/ui-composer': minor -'@rocket.chat/i18n': minor -'@rocket.chat/meteor': minor ---- - -Adds support for multiple files in message composer, improving file upload experience diff --git a/.changeset/spotty-poems-smash.md b/.changeset/spotty-poems-smash.md deleted file mode 100644 index 2899b84364ef8..0000000000000 --- a/.changeset/spotty-poems-smash.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/models": patch ---- - -Fixes an issue where, sometimes, updatedAt was not being set during the subscription creation diff --git a/.changeset/stale-elephants-type.md b/.changeset/stale-elephants-type.md deleted file mode 100644 index a49ea38cbccc1..0000000000000 --- a/.changeset/stale-elephants-type.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes main team channels being able to be converted into public or private with only the `create-team-channel` or `create-team-group` (the correct permission for main teams are `create-c` and `create-p`) diff --git a/.changeset/strict-ajv-coercion.md b/.changeset/strict-ajv-coercion.md deleted file mode 100644 index f34405032264b..0000000000000 --- a/.changeset/strict-ajv-coercion.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -"@rocket.chat/rest-typings": minor -"@rocket.chat/meteor": patch ---- - -Splits the single AJV validator instance into two: `ajv` (coerceTypes: false) for request **body** validation and `ajvQuery` (coerceTypes: true) for **query parameter** validation. - -**Why this matters:** Previously, a single AJV instance with `coerceTypes: true` was used everywhere. This silently accepted values with wrong types — for example, sending `{ "rid": 12345 }` (number) where a string was expected would pass validation because `12345` was coerced to `"12345"`. With this change, body validation is now strict: the server will reject payloads with incorrect types instead of silently coercing them. - -**What may break for API consumers:** - -- **Numeric values sent as strings in POST/PUT/PATCH bodies** (e.g., `{ "count": "10" }` instead of `{ "count": 10 }`) will now be rejected. Ensure JSON bodies use proper types. -- **Boolean values sent as strings in bodies** (e.g., `{ "readThreads": "true" }` instead of `{ "readThreads": true }`) will now be rejected. -- **`null` values where a string is expected** (e.g., `{ "name": null }` for a `type: 'string'` field without `nullable: true`) will no longer be coerced to `""`. - -**No change for query parameters:** GET query params (e.g., `?count=10&offset=0`) continue to be coerced via `ajvQuery`, since HTTP query strings are always strings. diff --git a/.changeset/sweet-terms-relax.md b/.changeset/sweet-terms-relax.md deleted file mode 100644 index 8861e65f43250..0000000000000 --- a/.changeset/sweet-terms-relax.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/meteor': minor -'@rocket.chat/core-typings': minor -'@rocket.chat/rest-typings': minor ---- - -Add OpenAPI support for the Rocket.Chat custom-user-status.list API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation diff --git a/.changeset/swift-badgers-try.md b/.changeset/swift-badgers-try.md deleted file mode 100644 index 368d41a127c83..0000000000000 --- a/.changeset/swift-badgers-try.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/rest-typings': minor -'@rocket.chat/meteor': minor ---- - -Add OpenAPI support for the Rocket.Chat e2e endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. diff --git a/.changeset/tame-dolphins-draw.md b/.changeset/tame-dolphins-draw.md deleted file mode 100644 index f42810fac68ce..0000000000000 --- a/.changeset/tame-dolphins-draw.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes `inquiries.take` not failing when attempting to take a chat while over chat limits diff --git a/.changeset/tame-humans-greet.md b/.changeset/tame-humans-greet.md deleted file mode 100644 index e5b0aa45eece6..0000000000000 --- a/.changeset/tame-humans-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes an issue where `Production` flag was not being respected when initializing Push Notifications configuration diff --git a/.changeset/tame-tables-complain.md b/.changeset/tame-tables-complain.md deleted file mode 100644 index 2d8c05a3f1432..0000000000000 --- a/.changeset/tame-tables-complain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes "Join" button on Outlook Calendar bubbling click event, also opening the calendar event details. diff --git a/.changeset/tender-papayas-jam.md b/.changeset/tender-papayas-jam.md deleted file mode 100644 index d9e85e6d29425..0000000000000 --- a/.changeset/tender-papayas-jam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Limits Omnichannel webhook maximum response size to 10mb. diff --git a/.changeset/thick-nails-exist.md b/.changeset/thick-nails-exist.md deleted file mode 100644 index 985c251a2044e..0000000000000 --- a/.changeset/thick-nails-exist.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -Adds support for ban management in rooms, enabling authorized users to ban and unban members via UI and slash commands. diff --git a/.changeset/tough-steaks-beam.md b/.changeset/tough-steaks-beam.md deleted file mode 100644 index cd0263fb496ed..0000000000000 --- a/.changeset/tough-steaks-beam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes reactivity of Custom Sounds and Custom Emojis storage settings diff --git a/.changeset/tricky-boxes-type.md b/.changeset/tricky-boxes-type.md deleted file mode 100644 index 084f3f79fe242..0000000000000 --- a/.changeset/tricky-boxes-type.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/rest-typings": patch ---- - -Add OpenAPI support for the Rocket.Chat rooms.favorite APIs endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. diff --git a/.changeset/twenty-colts-flash.md b/.changeset/twenty-colts-flash.md deleted file mode 100644 index 93729a19533f6..0000000000000 --- a/.changeset/twenty-colts-flash.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/rest-typings': minor -'@rocket.chat/meteor': minor ---- - -Adds new `custom-sounds.getOne` REST endpoint to retrieve a single custom sound by `_id` and updates client to consume it. diff --git a/.changeset/two-pianos-knock.md b/.changeset/two-pianos-knock.md deleted file mode 100644 index abad913b9c5b4..0000000000000 --- a/.changeset/two-pianos-knock.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/i18n": minor ---- - -Removes the Federation beta callout as the feature leaves beta diff --git a/.changeset/unlucky-impalas-matter.md b/.changeset/unlucky-impalas-matter.md deleted file mode 100644 index ed56575dcec7c..0000000000000 --- a/.changeset/unlucky-impalas-matter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes `ssrf` validation for oauth endpoints, which allows internal endpoints to be used during the auth flow. diff --git a/.changeset/weak-terms-shave.md b/.changeset/weak-terms-shave.md deleted file mode 100644 index 1813edcdb2b5b..0000000000000 --- a/.changeset/weak-terms-shave.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/rest-typings": patch ---- - -Add OpenAPI support for the Rocket.Chat emoji-custom.create API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. diff --git a/.changeset/wet-roses-call.md b/.changeset/wet-roses-call.md deleted file mode 100644 index 88cdcdb45362e..0000000000000 --- a/.changeset/wet-roses-call.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/rest-typings": patch -"@rocket.chat/core-typings": patch ---- - -Add OpenAPI support for the Rocket.Chat commands.get API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. diff --git a/.changeset/wicked-buckets-thank.md b/.changeset/wicked-buckets-thank.md deleted file mode 100644 index cc6f8af59fcce..0000000000000 --- a/.changeset/wicked-buckets-thank.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/rest-typings": patch ---- - -Add OpenAPI support for the Rocket.Chat dm.close/im.close API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. diff --git a/apps/meteor/CHANGELOG.md b/apps/meteor/CHANGELOG.md index ef99b7db28c6f..0d70a9271a780 100644 --- a/apps/meteor/CHANGELOG.md +++ b/apps/meteor/CHANGELOG.md @@ -1,5 +1,200 @@ # @rocket.chat/meteor +## 8.3.0 + +### Minor Changes + +- ([#39750](https://github.com/RocketChat/Rocket.Chat/pull/39750)) Adds support to name changes on federated rooms + +- ([#39268](https://github.com/RocketChat/Rocket.Chat/pull/39268)) refactor(ui-kit): Remove UiKit deprecations + +- ([#38978](https://github.com/RocketChat/Rocket.Chat/pull/38978) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat autotranslate translateMessage API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation + +- ([#37922](https://github.com/RocketChat/Rocket.Chat/pull/37922)) Introduces native screen sharing for internal voice calls. This feature is currently in beta and can be disabled through admin settings. + +- ([#39225](https://github.com/RocketChat/Rocket.Chat/pull/39225) by [@sezallagwal](https://github.com/sezallagwal)) Add OpenAPI support for the chat.followMessage and chat.unfollowMessage API endpoints by migrating to a modern chained route definition syntax and utilizing AJV schemas for body and response validation. + +- ([#39227](https://github.com/RocketChat/Rocket.Chat/pull/39227) by [@sezallagwal](https://github.com/sezallagwal)) Add OpenAPI support for the chat.starMessage and chat.unStarMessage API endpoints by migrating to a modern chained route definition syntax and utilizing AJV schemas for body and response validation. + +- ([#38957](https://github.com/RocketChat/Rocket.Chat/pull/38957) by [@Verifieddanny](https://github.com/Verifieddanny)) Migrated rooms.leave endpoint to new OpenAPI pattern with AJV validation + +- ([#38549](https://github.com/RocketChat/Rocket.Chat/pull/38549) by [@Rohitgiri02](https://github.com/Rohitgiri02)) migrated rooms.delete endpoint to new OpenAPI pattern with AJV validation + +- ([#39094](https://github.com/RocketChat/Rocket.Chat/pull/39094) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Adds OpenAPI support for the Rocket.Chat e2e.updateGroupKey endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#36402](https://github.com/RocketChat/Rocket.Chat/pull/36402) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat users.getAvatarSuggestion API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#38881](https://github.com/RocketChat/Rocket.Chat/pull/38881) by [@smirk-dev](https://github.com/smirk-dev)) adds `instances.get` API endpoint to new chained pattern with response schemas + +- ([#38883](https://github.com/RocketChat/Rocket.Chat/pull/38883) by [@smirk-dev](https://github.com/smirk-dev)) Migrates `ldap.testConnection` and `ldap.testSearch` REST API endpoints from legacy `addRoute` pattern to the new chained `.post()` API pattern with typed response schemas and AJV body validation (replacing Meteor `check()`). + +- ([#38882](https://github.com/RocketChat/Rocket.Chat/pull/38882) by [@smirk-dev](https://github.com/smirk-dev)) Migrates `presence.getConnections` and `presence.enableBroadcast` REST API endpoints from legacy `addRoute` pattern to the new chained `.get()`/`.post()` API pattern with typed response schemas. + +- ([#38610](https://github.com/RocketChat/Rocket.Chat/pull/38610)) Fixes Custom Sounds Contextualbar state and refresh behavior + +- ([#36779](https://github.com/RocketChat/Rocket.Chat/pull/36779) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat e2e.fetchMyKeys endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#39425](https://github.com/RocketChat/Rocket.Chat/pull/39425)) Adds support for multiple files in message composer, improving file upload experience + +- ([#36916](https://github.com/RocketChat/Rocket.Chat/pull/36916) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat custom-user-status.list API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation + +- ([#39219](https://github.com/RocketChat/Rocket.Chat/pull/39219) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat e2e endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#39678](https://github.com/RocketChat/Rocket.Chat/pull/39678)) Adds support for ban management in rooms, enabling authorized users to ban and unban members via UI and slash commands. + +- ([#38610](https://github.com/RocketChat/Rocket.Chat/pull/38610)) Adds new `custom-sounds.getOne` REST endpoint to retrieve a single custom sound by `_id` and updates client to consume it. + +- ([#40006](https://github.com/RocketChat/Rocket.Chat/pull/40006)) Removes the Federation beta callout as the feature leaves beta + +### Patch Changes + +- ([#39492](https://github.com/RocketChat/Rocket.Chat/pull/39492)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +- ([#39010](https://github.com/RocketChat/Rocket.Chat/pull/39010)) Fixes an authorization issue that allowed users to confirm uploads from other users + +- ([#39092](https://github.com/RocketChat/Rocket.Chat/pull/39092)) Fixes main channel scroll position changing when jumping to a thread message from search + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- ([#38531](https://github.com/RocketChat/Rocket.Chat/pull/38531)) Fixes a cross-resource access issue that allowed users to retrieve emojis from the Custom Sounds endpoint and sounds from the Custom Emojis endpoint when using the FileSystem storage mode. + +- ([#39752](https://github.com/RocketChat/Rocket.Chat/pull/39752)) Fixes an issue on Federation where all domains ending with the pattern where being allowed to communicate, the feature is meant to work with a list, url by url + +- ([#38662](https://github.com/RocketChat/Rocket.Chat/pull/38662) by [@TheRazorbill](https://github.com/TheRazorbill)) Fixes wrong i18n key in RegisterWorkspace confirmation step so the text is translated instead of showing a missing key. + +- ([#38983](https://github.com/RocketChat/Rocket.Chat/pull/38983) by [@copilot-swe-agent](https://github.com/copilot-swe-agent)) Fixes incoming webhook messages ignoring literal `\n` escape sequences, and fixes the `MarkdownText` `document` variant not rendering newlines as line breaks. + +- ([#39087](https://github.com/RocketChat/Rocket.Chat/pull/39087)) Fixes race condition causing duplicate open livechat rooms per visitor token. + +- ([#39460](https://github.com/RocketChat/Rocket.Chat/pull/39460)) Fixes inconsistent username formatting causing '@@username' for federated users + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +- ([#39541](https://github.com/RocketChat/Rocket.Chat/pull/39541)) Fixes an issue when forwarding messages to a password-protected room. + +- ([#39003](https://github.com/RocketChat/Rocket.Chat/pull/39003)) Fix marking a message as sent before the request finishes + +- ([#36786](https://github.com/RocketChat/Rocket.Chat/pull/36786) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat e2e.getUsersOfRoomWithoutKey endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#38932](https://github.com/RocketChat/Rocket.Chat/pull/38932)) Fixes version update banner showing outdated versions after server upgrade. + +- ([#39461](https://github.com/RocketChat/Rocket.Chat/pull/39461)) Deprecates `Anonymous write`. Feature will be removed in version 9.0.0. + +- ([#39545](https://github.com/RocketChat/Rocket.Chat/pull/39545)) Fixes the intermittent behavior where the "New messages" indicator appears incorrectly after the user sends a message + +- ([#39753](https://github.com/RocketChat/Rocket.Chat/pull/39753)) Fixes an issue where emails were not saved for users logging in via the GitHub OAuth provider. + +- ([#39491](https://github.com/RocketChat/Rocket.Chat/pull/39491)) Fixes calendar events modifying the wrong status property when attempting to sync `busy` status. + +- ([#39054](https://github.com/RocketChat/Rocket.Chat/pull/39054)) Fixes a mismatch in the room icons on the sidebar items, ABAC Managed rooms were not displaying the correct icon + +- ([#38760](https://github.com/RocketChat/Rocket.Chat/pull/38760) by [@Khizarshah01](https://github.com/Khizarshah01)) Limits `Outgoing webhook` maximum response size to 10mb. + +- ([#39612](https://github.com/RocketChat/Rocket.Chat/pull/39612)) Fixes the download of attachments with non-unicode names on E2EE rooms + +- ([#36882](https://github.com/RocketChat/Rocket.Chat/pull/36882) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat push.test API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#39718](https://github.com/RocketChat/Rocket.Chat/pull/39718)) Fixes an issue where, sometimes, updatedAt was not being set during the subscription creation + +- ([#39557](https://github.com/RocketChat/Rocket.Chat/pull/39557)) Fixes main team channels being able to be converted into public or private with only the `create-team-channel` or `create-team-group` (the correct permission for main teams are `create-c` and `create-p`) + +- ([#39559](https://github.com/RocketChat/Rocket.Chat/pull/39559) by [@copilot-swe-agent](https://github.com/copilot-swe-agent)) Splits the single AJV validator instance into two: `ajv` (coerceTypes: false) for request **body** validation and `ajvQuery` (coerceTypes: true) for **query parameter** validation. + + **Why this matters:** Previously, a single AJV instance with `coerceTypes: true` was used everywhere. This silently accepted values with wrong types — for example, sending `{ "rid": 12345 }` (number) where a string was expected would pass validation because `12345` was coerced to `"12345"`. With this change, body validation is now strict: the server will reject payloads with incorrect types instead of silently coercing them. + + **What may break for API consumers:** + + - **Numeric values sent as strings in POST/PUT/PATCH bodies** (e.g., `{ "count": "10" }` instead of `{ "count": 10 }`) will now be rejected. Ensure JSON bodies use proper types. + - **Boolean values sent as strings in bodies** (e.g., `{ "readThreads": "true" }` instead of `{ "readThreads": true }`) will now be rejected. + - **`null` values where a string is expected** (e.g., `{ "name": null }` for a `type: 'string'` field without `nullable: true`) will no longer be coerced to `""`. + + **No change for query parameters:** GET query params (e.g., `?count=10&offset=0`) continue to be coerced via `ajvQuery`, since HTTP query strings are always strings. + +- ([#39250](https://github.com/RocketChat/Rocket.Chat/pull/39250)) Fixes `inquiries.take` not failing when attempting to take a chat while over chat limits + +- ([#38852](https://github.com/RocketChat/Rocket.Chat/pull/38852)) Fixes an issue where `Production` flag was not being respected when initializing Push Notifications configuration + +- ([#39363](https://github.com/RocketChat/Rocket.Chat/pull/39363) by [@gauravsingh001-cyber](https://github.com/gauravsingh001-cyber)) Fixes "Join" button on Outlook Calendar bubbling click event, also opening the calendar event details. + +- ([#38944](https://github.com/RocketChat/Rocket.Chat/pull/38944) by [@Khizarshah01](https://github.com/Khizarshah01)) Limits Omnichannel webhook maximum response size to 10mb. + +- ([#38954](https://github.com/RocketChat/Rocket.Chat/pull/38954)) Fixes reactivity of Custom Sounds and Custom Emojis storage settings + +- ([#35995](https://github.com/RocketChat/Rocket.Chat/pull/35995) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat rooms.favorite APIs endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#39505](https://github.com/RocketChat/Rocket.Chat/pull/39505)) Fixes `ssrf` validation for oauth endpoints, which allows internal endpoints to be used during the auth flow. + +- ([#36523](https://github.com/RocketChat/Rocket.Chat/pull/36523) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat emoji-custom.create API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#36953](https://github.com/RocketChat/Rocket.Chat/pull/36953) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat commands.get API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#38974](https://github.com/RocketChat/Rocket.Chat/pull/38974) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat dm.close/im.close API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, e65b1764aad1ece3d770599e2ba0e216f41457cf, 6b80941a610085bac643d6958f6efa7c018f4bdf, d1bf2cc675e80403659d388a1fbbdc6f73889dad, 02b1e6e6a184850d21e335077ca30382a1c7a66b, 9a70095296dbf516b0113a9a65e09f25137b2eaf, cd2fc208d351032c0b729755af4886665dca08b6, 87f9262af4a543d52642a54e1ef546d509a79e23, a4e3c1635d55ec4ce04cbde741426770e43581fb, 652ff8cfe26b9068a776c39132c0eb5440702894, 539659af22bc19880eda047dfc0b152472ccb65c, b1b1d6ccd81c90d231a7e594f834965c6e5f4fae, 1741a20dd86c353755becfc706cd9ad63df09cfa, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 85c0ac7d8c7a5b7b89ef58f4a42b18467a8e2dd4, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, c217b0bde182e5f76dbe1892d9b37d61ffab71db, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, 43d0cfc6a70e8a31d5f3d24162216dae6b07efdd, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 788c161bb6c9544bec37034c93e2f60de1a6c316, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/model-typings@2.1.2 + - @rocket.chat/models@2.1.2 + - @rocket.chat/federation-matrix@0.1.0 + - @rocket.chat/message-parser@0.31.35 + - @rocket.chat/fuselage-ui-kit@29.0.0 + - @rocket.chat/ui-kit@1.0.0 + - @rocket.chat/apps-engine@1.61.0 + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/i18n@2.2.0 + - @rocket.chat/ui-voip@19.0.0 + - @rocket.chat/server-cloud-communication@0.0.3 + - @rocket.chat/omnichannel-services@0.3.50 + - @rocket.chat/web-ui-registration@29.0.0 + - @rocket.chat/network-broker@0.2.32 + - @rocket.chat/password-policies@0.1.1 + - @rocket.chat/omni-core-ee@0.0.18 + - @rocket.chat/instance-status@0.1.53 + - @rocket.chat/media-signaling@0.2.0 + - @rocket.chat/patch-injection@0.0.2 + - @rocket.chat/media-calls@0.3.0 + - @rocket.chat/pdf-worker@0.3.32 + - @rocket.chat/account-utils@0.0.3 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/message-types@0.1.1 + - @rocket.chat/mongo-adapter@0.0.3 + - @rocket.chat/ui-video-conf@29.0.0 + - @rocket.chat/cas-validate@0.0.4 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/server-fetch@0.1.2 + - @rocket.chat/presence@0.2.53 + - @rocket.chat/http-router@7.9.20 + - @rocket.chat/poplib@0.0.3 + - @rocket.chat/ui-composer@0.6.0 + - @rocket.chat/ui-contexts@29.0.0 + - @rocket.chat/license@1.1.13 + - @rocket.chat/api-client@0.2.53 + - @rocket.chat/log-format@0.0.3 + - @rocket.chat/gazzodown@29.0.0 + - @rocket.chat/omni-core@0.0.18 + - @rocket.chat/ui-avatar@25.0.0 + - @rocket.chat/ui-client@29.0.0 + - @rocket.chat/abac@0.1.6 + - @rocket.chat/favicon@0.0.5 + - @rocket.chat/tracing@0.0.2 + - @rocket.chat/agenda@0.1.1 + - @rocket.chat/base64@1.0.14 + - @rocket.chat/logger@1.0.1 + - @rocket.chat/random@1.2.3 + - @rocket.chat/sha256@1.0.13 + - @rocket.chat/tools@0.2.5 + - @rocket.chat/apps@0.6.6 + - @rocket.chat/cron@0.1.53 + - @rocket.chat/jwt@0.2.1 +
+ ## 8.3.0-rc.4 ### Patch Changes diff --git a/apps/meteor/app/utils/rocketchat.info b/apps/meteor/app/utils/rocketchat.info index 547de34360c67..af4e0a52c34cf 100644 --- a/apps/meteor/app/utils/rocketchat.info +++ b/apps/meteor/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "8.3.0-rc.4" + "version": "8.3.0" } diff --git a/apps/meteor/ee/server/services/CHANGELOG.md b/apps/meteor/ee/server/services/CHANGELOG.md index 3432573049d4e..ac80ec2b80e57 100644 --- a/apps/meteor/ee/server/services/CHANGELOG.md +++ b/apps/meteor/ee/server/services/CHANGELOG.md @@ -1,5 +1,22 @@ # rocketchat-services +## 2.0.44 + +### Patch Changes + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, d1bf2cc675e80403659d388a1fbbdc6f73889dad, 02b1e6e6a184850d21e335077ca30382a1c7a66b, 9a70095296dbf516b0113a9a65e09f25137b2eaf, cd2fc208d351032c0b729755af4886665dca08b6, 87f9262af4a543d52642a54e1ef546d509a79e23, a4e3c1635d55ec4ce04cbde741426770e43581fb, 539659af22bc19880eda047dfc0b152472ccb65c, b1b1d6ccd81c90d231a7e594f834965c6e5f4fae, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/model-typings@2.1.2 + - @rocket.chat/models@2.1.2 + - @rocket.chat/message-parser@0.31.35 + - @rocket.chat/ui-kit@1.0.0 + - @rocket.chat/apps-engine@1.61.0 + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/network-broker@0.2.32 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/core-typings@8.3.0 +
+ ## 2.0.44-rc.4 ### Patch Changes diff --git a/apps/meteor/ee/server/services/package.json b/apps/meteor/ee/server/services/package.json index 2357f6a80aa70..763ef88766e9c 100644 --- a/apps/meteor/ee/server/services/package.json +++ b/apps/meteor/ee/server/services/package.json @@ -1,7 +1,7 @@ { "name": "rocketchat-services", "private": true, - "version": "2.0.44-rc.4", + "version": "2.0.44", "description": "Rocket.Chat Authorization service", "main": "index.js", "scripts": { diff --git a/apps/meteor/package.json b/apps/meteor/package.json index 1ca6d29a563c7..5ccff1c93c9b5 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/meteor", - "version": "8.3.0-rc.4", + "version": "8.3.0", "private": true, "description": "The Ultimate Open Source WebChat Platform", "keywords": [ diff --git a/apps/uikit-playground/CHANGELOG.md b/apps/uikit-playground/CHANGELOG.md index 7fa2672121492..ce005659edd48 100644 --- a/apps/uikit-playground/CHANGELOG.md +++ b/apps/uikit-playground/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/uikit-playground +## 0.7.9 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [87f9262af4a543d52642a54e1ef546d509a79e23, 539659af22bc19880eda047dfc0b152472ccb65c, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 43d0cfc6a70e8a31d5f3d24162216dae6b07efdd, d83a1a9753464ee916845b3c88757bbcf76884a5, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/fuselage-ui-kit@29.0.0 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/ui-contexts@29.0.0 + - @rocket.chat/ui-avatar@25.0.0 +
+ ## 0.7.9-rc.4 ### Patch Changes diff --git a/apps/uikit-playground/package.json b/apps/uikit-playground/package.json index 47c9b73b9b2ac..f12980e9d7e38 100644 --- a/apps/uikit-playground/package.json +++ b/apps/uikit-playground/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/uikit-playground", - "version": "0.7.9-rc.4", + "version": "0.7.9", "private": true, "type": "module", "scripts": { diff --git a/ee/apps/account-service/CHANGELOG.md b/ee/apps/account-service/CHANGELOG.md index e8990a99a1de3..12ee27336e738 100644 --- a/ee/apps/account-service/CHANGELOG.md +++ b/ee/apps/account-service/CHANGELOG.md @@ -1,5 +1,24 @@ # @rocket.chat/account-service +## 0.4.53 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, a4e3c1635d55ec4ce04cbde741426770e43581fb, 539659af22bc19880eda047dfc0b152472ccb65c, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/model-typings@2.1.2 + - @rocket.chat/models@2.1.2 + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/network-broker@0.2.32 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/tracing@0.0.2 + - @rocket.chat/logger@1.0.1 + - @rocket.chat/tools@0.2.5 +
+ ## 0.4.53-rc.4 ### Patch Changes diff --git a/ee/apps/account-service/package.json b/ee/apps/account-service/package.json index 15a4f1fe22fbe..ce690c1577491 100644 --- a/ee/apps/account-service/package.json +++ b/ee/apps/account-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/account-service", - "version": "0.4.53-rc.4", + "version": "0.4.53", "private": true, "description": "Rocket.Chat Account service", "keywords": [ diff --git a/ee/apps/authorization-service/CHANGELOG.md b/ee/apps/authorization-service/CHANGELOG.md index 5095bdf0bbca5..ecaec999cc513 100644 --- a/ee/apps/authorization-service/CHANGELOG.md +++ b/ee/apps/authorization-service/CHANGELOG.md @@ -1,5 +1,24 @@ # @rocket.chat/authorization-service +## 0.5.6 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, a4e3c1635d55ec4ce04cbde741426770e43581fb, 539659af22bc19880eda047dfc0b152472ccb65c, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/model-typings@2.1.2 + - @rocket.chat/models@2.1.2 + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/network-broker@0.2.32 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/abac@0.1.6 + - @rocket.chat/tracing@0.0.2 + - @rocket.chat/logger@1.0.1 +
+ ## 0.5.6-rc.4 ### Patch Changes diff --git a/ee/apps/authorization-service/package.json b/ee/apps/authorization-service/package.json index 451421a2d7dc6..868ba01721872 100644 --- a/ee/apps/authorization-service/package.json +++ b/ee/apps/authorization-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/authorization-service", - "version": "0.5.6-rc.4", + "version": "0.5.6", "private": true, "description": "Rocket.Chat Authorization service", "keywords": [ diff --git a/ee/apps/ddp-streamer/CHANGELOG.md b/ee/apps/ddp-streamer/CHANGELOG.md index dd94fc18b8c0a..c8e7c0cb6e45f 100644 --- a/ee/apps/ddp-streamer/CHANGELOG.md +++ b/ee/apps/ddp-streamer/CHANGELOG.md @@ -1,5 +1,24 @@ # @rocket.chat/ddp-streamer +## 0.3.53 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, a4e3c1635d55ec4ce04cbde741426770e43581fb, 539659af22bc19880eda047dfc0b152472ccb65c, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/model-typings@2.1.2 + - @rocket.chat/models@2.1.2 + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/network-broker@0.2.32 + - @rocket.chat/instance-status@0.1.53 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/tracing@0.0.2 + - @rocket.chat/logger@1.0.1 +
+ ## 0.3.53-rc.4 ### Patch Changes diff --git a/ee/apps/ddp-streamer/package.json b/ee/apps/ddp-streamer/package.json index d1b34a6bd6b26..36ad0bea51a83 100644 --- a/ee/apps/ddp-streamer/package.json +++ b/ee/apps/ddp-streamer/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ddp-streamer", - "version": "0.3.53-rc.4", + "version": "0.3.53", "private": true, "description": "Rocket.Chat DDP-Streamer service", "keywords": [ diff --git a/ee/apps/omnichannel-transcript/CHANGELOG.md b/ee/apps/omnichannel-transcript/CHANGELOG.md index 0048a1b35ef0a..3ed3ae449ebe1 100644 --- a/ee/apps/omnichannel-transcript/CHANGELOG.md +++ b/ee/apps/omnichannel-transcript/CHANGELOG.md @@ -1,5 +1,26 @@ # @rocket.chat/omnichannel-transcript +## 0.4.53 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 652ff8cfe26b9068a776c39132c0eb5440702894, 539659af22bc19880eda047dfc0b152472ccb65c, 1741a20dd86c353755becfc706cd9ad63df09cfa, 85c0ac7d8c7a5b7b89ef58f4a42b18467a8e2dd4, c217b0bde182e5f76dbe1892d9b37d61ffab71db, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 788c161bb6c9544bec37034c93e2f60de1a6c316, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/model-typings@2.1.2 + - @rocket.chat/models@2.1.2 + - @rocket.chat/i18n@2.2.0 + - @rocket.chat/omnichannel-services@0.3.50 + - @rocket.chat/network-broker@0.2.32 + - @rocket.chat/pdf-worker@0.3.32 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/tracing@0.0.2 + - @rocket.chat/logger@1.0.1 + - @rocket.chat/tools@0.2.5 +
+ ## 0.4.53-rc.4 ### Patch Changes diff --git a/ee/apps/omnichannel-transcript/package.json b/ee/apps/omnichannel-transcript/package.json index 9a76feb464c81..f865d00e60bb9 100644 --- a/ee/apps/omnichannel-transcript/package.json +++ b/ee/apps/omnichannel-transcript/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omnichannel-transcript", - "version": "0.4.53-rc.4", + "version": "0.4.53", "private": true, "description": "Rocket.Chat service", "keywords": [ diff --git a/ee/apps/presence-service/CHANGELOG.md b/ee/apps/presence-service/CHANGELOG.md index b023bf136efb6..438a9b6d710d4 100644 --- a/ee/apps/presence-service/CHANGELOG.md +++ b/ee/apps/presence-service/CHANGELOG.md @@ -1,5 +1,23 @@ # @rocket.chat/presence-service +## 0.4.53 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/model-typings@2.1.2 + - @rocket.chat/models@2.1.2 + - @rocket.chat/network-broker@0.2.32 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/presence@0.2.53 + - @rocket.chat/tracing@0.0.2 + - @rocket.chat/logger@1.0.1 +
+ ## 0.4.53-rc.4 ### Patch Changes diff --git a/ee/apps/presence-service/package.json b/ee/apps/presence-service/package.json index 857925e9bf807..d92a016a488b4 100644 --- a/ee/apps/presence-service/package.json +++ b/ee/apps/presence-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/presence-service", - "version": "0.4.53-rc.4", + "version": "0.4.53", "private": true, "description": "Rocket.Chat Presence service", "keywords": [ diff --git a/ee/apps/queue-worker/CHANGELOG.md b/ee/apps/queue-worker/CHANGELOG.md index 072e95aff25f3..c97b20b5d0126 100644 --- a/ee/apps/queue-worker/CHANGELOG.md +++ b/ee/apps/queue-worker/CHANGELOG.md @@ -1,5 +1,23 @@ # @rocket.chat/queue-worker +## 0.4.53 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/model-typings@2.1.2 + - @rocket.chat/models@2.1.2 + - @rocket.chat/omnichannel-services@0.3.50 + - @rocket.chat/network-broker@0.2.32 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/tracing@0.0.2 + - @rocket.chat/logger@1.0.1 +
+ ## 0.4.53-rc.4 ### Patch Changes diff --git a/ee/apps/queue-worker/package.json b/ee/apps/queue-worker/package.json index ece00ab46372a..c25488b5c907a 100644 --- a/ee/apps/queue-worker/package.json +++ b/ee/apps/queue-worker/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/queue-worker", - "version": "0.4.53-rc.4", + "version": "0.4.53", "private": true, "description": "Rocket.Chat service", "keywords": [ diff --git a/ee/packages/abac/CHANGELOG.md b/ee/packages/abac/CHANGELOG.md index 8e3a63ff8ed5f..6c3f3f5c8edc5 100644 --- a/ee/packages/abac/CHANGELOG.md +++ b/ee/packages/abac/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/abac +## 0.1.6 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/models@2.1.2 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/logger@1.0.1 +
+ ## 0.1.6-rc.4 ### Patch Changes diff --git a/ee/packages/abac/package.json b/ee/packages/abac/package.json index af34f15869b08..026e965a4b886 100644 --- a/ee/packages/abac/package.json +++ b/ee/packages/abac/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/abac", - "version": "0.1.6-rc.4", + "version": "0.1.6", "private": true, "description": "Rocket.Chat - Attribute Based Access Control (ABAC) support utilities", "main": "./dist/index.js", diff --git a/ee/packages/federation-matrix/CHANGELOG.md b/ee/packages/federation-matrix/CHANGELOG.md index d928159ca1c2a..6865e20d98384 100644 --- a/ee/packages/federation-matrix/CHANGELOG.md +++ b/ee/packages/federation-matrix/CHANGELOG.md @@ -1,5 +1,28 @@ # @rocket.chat/federation-matrix +## 0.1.0 + +### Minor Changes + +- ([#39750](https://github.com/RocketChat/Rocket.Chat/pull/39750)) Adds support to name changes on federated rooms + +### Patch Changes + +- ([#39752](https://github.com/RocketChat/Rocket.Chat/pull/39752)) Fixes an issue on Federation where all domains ending with the pattern where being allowed to communicate, the feature is meant to work with a list, url by url + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, a4e3c1635d55ec4ce04cbde741426770e43581fb, 539659af22bc19880eda047dfc0b152472ccb65c, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/models@2.1.2 + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/network-broker@0.2.32 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/http-router@7.9.20 + - @rocket.chat/license@1.1.13 +
+ ## 0.1.0-rc.4 ### Patch Changes diff --git a/ee/packages/federation-matrix/package.json b/ee/packages/federation-matrix/package.json index 90a319b9ec5ea..a38b3b7020529 100644 --- a/ee/packages/federation-matrix/package.json +++ b/ee/packages/federation-matrix/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/federation-matrix", - "version": "0.1.0-rc.4", + "version": "0.1.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/license/CHANGELOG.md b/ee/packages/license/CHANGELOG.md index 4c3b65cd3a2ce..b7d312acb7b2d 100644 --- a/ee/packages/license/CHANGELOG.md +++ b/ee/packages/license/CHANGELOG.md @@ -1,5 +1,18 @@ # @rocket.chat/license +## 1.1.13 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [539659af22bc19880eda047dfc0b152472ccb65c, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/logger@1.0.1 + - @rocket.chat/jwt@0.2.1 +
+ ## 1.1.13-rc.4 ### Patch Changes diff --git a/ee/packages/license/package.json b/ee/packages/license/package.json index e8dfbd3952004..c707b5c8812aa 100644 --- a/ee/packages/license/package.json +++ b/ee/packages/license/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/license", - "version": "1.1.13-rc.4", + "version": "1.1.13", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/media-calls/CHANGELOG.md b/ee/packages/media-calls/CHANGELOG.md index 872f8abe541c6..8378e4005c2a4 100644 --- a/ee/packages/media-calls/CHANGELOG.md +++ b/ee/packages/media-calls/CHANGELOG.md @@ -1,5 +1,23 @@ # @rocket.chat/media-calls +## 0.3.0 + +### Minor Changes + +- ([#37922](https://github.com/RocketChat/Rocket.Chat/pull/37922)) Introduces native screen sharing for internal voice calls. This feature is currently in beta and can be disabled through admin settings. + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, 1741a20dd86c353755becfc706cd9ad63df09cfa, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/models@2.1.2 + - @rocket.chat/media-signaling@0.2.0 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/logger@1.0.1 +
+ ## 0.3.0-rc.4 ### Patch Changes diff --git a/ee/packages/media-calls/package.json b/ee/packages/media-calls/package.json index 9e91e31e3036c..9e56f9c71d958 100644 --- a/ee/packages/media-calls/package.json +++ b/ee/packages/media-calls/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/media-calls", - "version": "0.3.0-rc.4", + "version": "0.3.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/network-broker/CHANGELOG.md b/ee/packages/network-broker/CHANGELOG.md index 7e9b2e3827fbb..e8e44f337d759 100644 --- a/ee/packages/network-broker/CHANGELOG.md +++ b/ee/packages/network-broker/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/network-broker +## 0.2.32 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [539659af22bc19880eda047dfc0b152472ccb65c]: + + - @rocket.chat/core-services@0.13.2 +
+ ## 0.2.32-rc.4 ### Patch Changes diff --git a/ee/packages/network-broker/package.json b/ee/packages/network-broker/package.json index ea58ec1ca06ad..0de857cffc0b4 100644 --- a/ee/packages/network-broker/package.json +++ b/ee/packages/network-broker/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/network-broker", - "version": "0.2.32-rc.4", + "version": "0.2.32", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/omni-core-ee/CHANGELOG.md b/ee/packages/omni-core-ee/CHANGELOG.md index eaf672d9f41be..1eb52064e2eca 100644 --- a/ee/packages/omni-core-ee/CHANGELOG.md +++ b/ee/packages/omni-core-ee/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/omni-core-ee +## 0.0.18 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, eae3fb3136bd0b48294c050a71b0a36d05ca02b0]: + + - @rocket.chat/models@2.1.2 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/omni-core@0.0.18 + - @rocket.chat/logger@1.0.1 +
+ ## 0.0.18-rc.4 ### Patch Changes diff --git a/ee/packages/omni-core-ee/package.json b/ee/packages/omni-core-ee/package.json index 4289c77fe3d1c..e2d699febd96d 100644 --- a/ee/packages/omni-core-ee/package.json +++ b/ee/packages/omni-core-ee/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omni-core-ee", - "version": "0.0.18-rc.4", + "version": "0.0.18", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/omnichannel-services/CHANGELOG.md b/ee/packages/omnichannel-services/CHANGELOG.md index 288d91d179469..cb4d4cd58b942 100644 --- a/ee/packages/omnichannel-services/CHANGELOG.md +++ b/ee/packages/omnichannel-services/CHANGELOG.md @@ -1,5 +1,25 @@ # @rocket.chat/omnichannel-services +## 0.3.50 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, a4e3c1635d55ec4ce04cbde741426770e43581fb, 652ff8cfe26b9068a776c39132c0eb5440702894, 539659af22bc19880eda047dfc0b152472ccb65c, 1741a20dd86c353755becfc706cd9ad63df09cfa, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 85c0ac7d8c7a5b7b89ef58f4a42b18467a8e2dd4, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, c217b0bde182e5f76dbe1892d9b37d61ffab71db, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 788c161bb6c9544bec37034c93e2f60de1a6c316, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/model-typings@2.1.2 + - @rocket.chat/models@2.1.2 + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/i18n@2.2.0 + - @rocket.chat/pdf-worker@0.3.32 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/message-types@0.1.1 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/logger@1.0.1 + - @rocket.chat/tools@0.2.5 +
+ ## 0.3.50-rc.4 ### Patch Changes diff --git a/ee/packages/omnichannel-services/package.json b/ee/packages/omnichannel-services/package.json index 94987195643b7..081019d8abf36 100644 --- a/ee/packages/omnichannel-services/package.json +++ b/ee/packages/omnichannel-services/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omnichannel-services", - "version": "0.3.50-rc.4", + "version": "0.3.50", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/pdf-worker/CHANGELOG.md b/ee/packages/pdf-worker/CHANGELOG.md index 0d16dd87bbba3..82483053cdd4d 100644 --- a/ee/packages/pdf-worker/CHANGELOG.md +++ b/ee/packages/pdf-worker/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/pdf-worker +## 0.3.32 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [539659af22bc19880eda047dfc0b152472ccb65c, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/core-typings@8.3.0 +
+ ## 0.3.32-rc.4 ### Patch Changes diff --git a/ee/packages/pdf-worker/package.json b/ee/packages/pdf-worker/package.json index 0f084d20a6270..c6a01f2b256f3 100644 --- a/ee/packages/pdf-worker/package.json +++ b/ee/packages/pdf-worker/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/pdf-worker", - "version": "0.3.32-rc.4", + "version": "0.3.32", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/presence/CHANGELOG.md b/ee/packages/presence/CHANGELOG.md index 13a0e26dc5ec7..41055fa5bdb56 100644 --- a/ee/packages/presence/CHANGELOG.md +++ b/ee/packages/presence/CHANGELOG.md @@ -1,5 +1,18 @@ # @rocket.chat/presence +## 0.2.53 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/models@2.1.2 + - @rocket.chat/core-services@0.13.2 + - @rocket.chat/core-typings@8.3.0 +
+ ## 0.2.53-rc.4 ### Patch Changes diff --git a/ee/packages/presence/package.json b/ee/packages/presence/package.json index 86934bb75bda5..3511ab29258f6 100644 --- a/ee/packages/presence/package.json +++ b/ee/packages/presence/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/presence", - "version": "0.2.53-rc.4", + "version": "0.2.53", "private": true, "main": "./dist/Presence.js", "typings": "./dist/Presence.d.ts", diff --git a/package.json b/package.json index 0554ce138a6a3..f810f9df695e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rocket.chat", - "version": "8.3.0-rc.4", + "version": "8.3.0", "private": true, "description": "Rocket.Chat Monorepo", "homepage": "https://github.com/RocketChat/Rocket.Chat#readme", diff --git a/packages/account-utils/CHANGELOG.md b/packages/account-utils/CHANGELOG.md index 9570036363df0..b51c5cd58e7a2 100644 --- a/packages/account-utils/CHANGELOG.md +++ b/packages/account-utils/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/account-utils +## 0.0.3 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.0.3-rc.0 ### Patch Changes diff --git a/packages/account-utils/package.json b/packages/account-utils/package.json index 150e08ef4bace..775de4bda8266 100644 --- a/packages/account-utils/package.json +++ b/packages/account-utils/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/account-utils", - "version": "0.0.3-rc.0", + "version": "0.0.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/agenda/CHANGELOG.md b/packages/agenda/CHANGELOG.md index d7776d978a191..04b44b2dd0c6f 100644 --- a/packages/agenda/CHANGELOG.md +++ b/packages/agenda/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/agenda +## 0.1.1 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.1.1-rc.0 ### Patch Changes diff --git a/packages/agenda/package.json b/packages/agenda/package.json index a866c54145b86..773bac6339927 100644 --- a/packages/agenda/package.json +++ b/packages/agenda/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/agenda", - "version": "0.1.1-rc.0", + "version": "0.1.1", "private": true, "description": "Fork of https://github.com/agenda/agenda", "main": "./dist/index.js", diff --git a/packages/api-client/CHANGELOG.md b/packages/api-client/CHANGELOG.md index 0717fc0c9cdac..1a1d51891150d 100644 --- a/packages/api-client/CHANGELOG.md +++ b/packages/api-client/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/api-client +## 0.2.53 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [a4e3c1635d55ec4ce04cbde741426770e43581fb, 539659af22bc19880eda047dfc0b152472ccb65c, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/core-typings@8.3.0 +
+ ## 0.2.53-rc.4 ### Patch Changes diff --git a/packages/api-client/package.json b/packages/api-client/package.json index 99c32dd305bb0..94e18b7bf4edc 100644 --- a/packages/api-client/package.json +++ b/packages/api-client/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/api-client", - "version": "0.2.53-rc.4", + "version": "0.2.53", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/apps-engine/CHANGELOG.md b/packages/apps-engine/CHANGELOG.md index f9ad390cbe8ba..7c4c4d831c05d 100644 --- a/packages/apps-engine/CHANGELOG.md +++ b/packages/apps-engine/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/apps-engine +## 1.61.0 + +### Minor Changes + +- ([#39268](https://github.com/RocketChat/Rocket.Chat/pull/39268)) refactor(ui-kit): Remove UiKit deprecations + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 1.61.0-rc.0 ### Minor Changes diff --git a/packages/apps-engine/package.json b/packages/apps-engine/package.json index 1fea6fc60e8a9..8b9f5131ec170 100644 --- a/packages/apps-engine/package.json +++ b/packages/apps-engine/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/apps-engine", - "version": "1.61.0-rc.0", + "version": "1.61.0", "description": "The engine code for the Rocket.Chat Apps which manages, runs, translates, coordinates and all of that.", "keywords": [ "rocket.chat", diff --git a/packages/apps/CHANGELOG.md b/packages/apps/CHANGELOG.md index 689e49eb0f245..3dd51464f7cc0 100644 --- a/packages/apps/CHANGELOG.md +++ b/packages/apps/CHANGELOG.md @@ -1,5 +1,18 @@ # @rocket.chat/apps +## 0.6.6 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, 87f9262af4a543d52642a54e1ef546d509a79e23, 539659af22bc19880eda047dfc0b152472ccb65c, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/model-typings@2.1.2 + - @rocket.chat/apps-engine@1.61.0 + - @rocket.chat/core-typings@8.3.0 +
+ ## 0.6.6-rc.4 ### Patch Changes diff --git a/packages/apps/package.json b/packages/apps/package.json index 87dfdb9161882..8354a0adc1ed6 100644 --- a/packages/apps/package.json +++ b/packages/apps/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/apps", - "version": "0.6.6-rc.4", + "version": "0.6.6", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/base64/CHANGELOG.md b/packages/base64/CHANGELOG.md index 26f4403cf7a5e..4d1f891eab93f 100644 --- a/packages/base64/CHANGELOG.md +++ b/packages/base64/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/base64 +## 1.0.14 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 1.0.14-rc.0 ### Patch Changes diff --git a/packages/base64/package.json b/packages/base64/package.json index 4e7dea650222f..0aa51c1aa6bff 100644 --- a/packages/base64/package.json +++ b/packages/base64/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/base64", - "version": "1.0.14-rc.0", + "version": "1.0.14", "private": true, "description": "Base64 encoding and decoding; Fork of Meteor's Base64 package", "main": "./dist/base64.js", diff --git a/packages/cas-validate/CHANGELOG.md b/packages/cas-validate/CHANGELOG.md index bc2c3bc471659..db7901116bf13 100644 --- a/packages/cas-validate/CHANGELOG.md +++ b/packages/cas-validate/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/cas-validate +## 0.0.4 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.0.4-rc.0 ### Patch Changes diff --git a/packages/cas-validate/package.json b/packages/cas-validate/package.json index 15876601e5931..43c00e16ec4dc 100644 --- a/packages/cas-validate/package.json +++ b/packages/cas-validate/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/cas-validate", - "version": "0.0.4-rc.0", + "version": "0.0.4", "private": true, "description": "Fork of https://github.com/kcbanner/node-cas", "main": "./dist/index.js", diff --git a/packages/core-services/CHANGELOG.md b/packages/core-services/CHANGELOG.md index 34e24af61a53c..a4bdeb51a1d1d 100644 --- a/packages/core-services/CHANGELOG.md +++ b/packages/core-services/CHANGELOG.md @@ -1,5 +1,23 @@ # @rocket.chat/core-services +## 0.13.2 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, d1bf2cc675e80403659d388a1fbbdc6f73889dad, 02b1e6e6a184850d21e335077ca30382a1c7a66b, 9a70095296dbf516b0113a9a65e09f25137b2eaf, cd2fc208d351032c0b729755af4886665dca08b6, 87f9262af4a543d52642a54e1ef546d509a79e23, a4e3c1635d55ec4ce04cbde741426770e43581fb, 539659af22bc19880eda047dfc0b152472ccb65c, b1b1d6ccd81c90d231a7e594f834965c6e5f4fae, 1741a20dd86c353755becfc706cd9ad63df09cfa, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/models@2.1.2 + - @rocket.chat/message-parser@0.31.35 + - @rocket.chat/ui-kit@1.0.0 + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/media-signaling@0.2.0 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/http-router@7.9.20 + - @rocket.chat/tracing@0.0.2 +
+ ## 0.13.2-rc.4 ### Patch Changes diff --git a/packages/core-services/package.json b/packages/core-services/package.json index b26479c469c96..541e2376e9161 100644 --- a/packages/core-services/package.json +++ b/packages/core-services/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/core-services", - "version": "0.13.2-rc.4", + "version": "0.13.2", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/core-typings/CHANGELOG.md b/packages/core-typings/CHANGELOG.md index 30482e5955265..2e25bd5ca3e95 100644 --- a/packages/core-typings/CHANGELOG.md +++ b/packages/core-typings/CHANGELOG.md @@ -1,5 +1,27 @@ # @rocket.chat/core-typings +## 8.3.0 + +### Minor Changes + +- ([#39425](https://github.com/RocketChat/Rocket.Chat/pull/39425)) Adds support for multiple files in message composer, improving file upload experience + +- ([#36916](https://github.com/RocketChat/Rocket.Chat/pull/36916) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat custom-user-status.list API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +- ([#39753](https://github.com/RocketChat/Rocket.Chat/pull/39753)) Fixes an issue where emails were not saved for users logging in via the GitHub OAuth provider. + +- ([#36953](https://github.com/RocketChat/Rocket.Chat/pull/36953) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat commands.get API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +-
Updated dependencies [d1bf2cc675e80403659d388a1fbbdc6f73889dad, 02b1e6e6a184850d21e335077ca30382a1c7a66b, 9a70095296dbf516b0113a9a65e09f25137b2eaf, 87f9262af4a543d52642a54e1ef546d509a79e23, 539659af22bc19880eda047dfc0b152472ccb65c, b1b1d6ccd81c90d231a7e594f834965c6e5f4fae]: + + - @rocket.chat/message-parser@0.31.35 + - @rocket.chat/ui-kit@1.0.0 +
+ ## 8.3.0-rc.4 ## 8.3.0-rc.3 diff --git a/packages/core-typings/package.json b/packages/core-typings/package.json index 7909d35db1058..1e7a3fd262cee 100644 --- a/packages/core-typings/package.json +++ b/packages/core-typings/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package", "name": "@rocket.chat/core-typings", - "version": "8.3.0-rc.4", + "version": "8.3.0", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/cron/CHANGELOG.md b/packages/cron/CHANGELOG.md index 82a24f3330f43..ace9921aa4dff 100644 --- a/packages/cron/CHANGELOG.md +++ b/packages/cron/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/cron +## 0.1.53 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, eae3fb3136bd0b48294c050a71b0a36d05ca02b0, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/models@2.1.2 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/agenda@0.1.1 + - @rocket.chat/logger@1.0.1 + - @rocket.chat/random@1.2.3 +
+ ## 0.1.53-rc.4 ### Patch Changes diff --git a/packages/cron/package.json b/packages/cron/package.json index 881b191d6d3bf..f04ba65e9c31e 100644 --- a/packages/cron/package.json +++ b/packages/cron/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/cron", - "version": "0.1.53-rc.4", + "version": "0.1.53", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ddp-client/CHANGELOG.md b/packages/ddp-client/CHANGELOG.md index da99070fa01f6..00550f0741835 100644 --- a/packages/ddp-client/CHANGELOG.md +++ b/packages/ddp-client/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/ddp-client +## 1.0.6 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [a4e3c1635d55ec4ce04cbde741426770e43581fb, 539659af22bc19880eda047dfc0b152472ccb65c, 1741a20dd86c353755becfc706cd9ad63df09cfa, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/media-signaling@0.2.0 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/api-client@0.2.53 +
+ ## 1.0.6-rc.4 ### Patch Changes diff --git a/packages/ddp-client/package.json b/packages/ddp-client/package.json index 0b7fbcd114037..85316a096ef3d 100644 --- a/packages/ddp-client/package.json +++ b/packages/ddp-client/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ddp-client", - "version": "1.0.6-rc.4", + "version": "1.0.6", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/desktop-api/CHANGELOG.md b/packages/desktop-api/CHANGELOG.md index 86c6f72564699..afb32ffd788fd 100644 --- a/packages/desktop-api/CHANGELOG.md +++ b/packages/desktop-api/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/desktop-api +## 1.1.1 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 1.1.1-rc.0 ### Patch Changes diff --git a/packages/desktop-api/package.json b/packages/desktop-api/package.json index bca8935bae5d8..9d929d279a18a 100644 --- a/packages/desktop-api/package.json +++ b/packages/desktop-api/package.json @@ -1,7 +1,7 @@ { "$schema": "https://www.schemastore.org/package", "name": "@rocket.chat/desktop-api", - "version": "1.1.1-rc.0", + "version": "1.1.1", "type": "module", "exports": { ".": { diff --git a/packages/eslint-config/CHANGELOG.md b/packages/eslint-config/CHANGELOG.md index c9aa6fdfa408a..4afaf7247bd90 100644 --- a/packages/eslint-config/CHANGELOG.md +++ b/packages/eslint-config/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/eslint-config +## 0.8.0 + +### Minor Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.8.0-rc.0 ### Minor Changes diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 3b29617fd8132..6c2827261393e 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/eslint-config", - "version": "0.8.0-rc.0", + "version": "0.8.0", "description": "Rocket.Chat's JS/TS ESLint config", "type": "module", "main": "./index.js", diff --git a/packages/favicon/CHANGELOG.md b/packages/favicon/CHANGELOG.md index fbcaafd50840c..50adfba814841 100644 --- a/packages/favicon/CHANGELOG.md +++ b/packages/favicon/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/favicon +## 0.0.5 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.0.5-rc.0 ### Patch Changes diff --git a/packages/favicon/package.json b/packages/favicon/package.json index 32890d4b50f98..5248000151b77 100644 --- a/packages/favicon/package.json +++ b/packages/favicon/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/favicon", - "version": "0.0.5-rc.0", + "version": "0.0.5", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/fuselage-ui-kit/CHANGELOG.md b/packages/fuselage-ui-kit/CHANGELOG.md index 2147228ae123e..95e4378ce7e04 100644 --- a/packages/fuselage-ui-kit/CHANGELOG.md +++ b/packages/fuselage-ui-kit/CHANGELOG.md @@ -1,5 +1,26 @@ # Change Log +## 29.0.0 + +### Minor Changes + +- ([#39268](https://github.com/RocketChat/Rocket.Chat/pull/39268)) refactor(ui-kit): Remove UiKit deprecations + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [87f9262af4a543d52642a54e1ef546d509a79e23, 539659af22bc19880eda047dfc0b152472ccb65c, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 43d0cfc6a70e8a31d5f3d24162216dae6b07efdd, d83a1a9753464ee916845b3c88757bbcf76884a5, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/ui-kit@1.0.0 + - @rocket.chat/apps-engine@1.61.0 + - @rocket.chat/ui-video-conf@29.0.0 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/ui-contexts@29.0.0 + - @rocket.chat/gazzodown@29.0.0 + - @rocket.chat/ui-avatar@25.0.0 +
+ ## 29.0.0-rc.4 ### Patch Changes diff --git a/packages/fuselage-ui-kit/package.json b/packages/fuselage-ui-kit/package.json index 736c46265f046..67d50d223ca3c 100644 --- a/packages/fuselage-ui-kit/package.json +++ b/packages/fuselage-ui-kit/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/fuselage-ui-kit", - "version": "29.0.0-rc.4", + "version": "29.0.0", "private": true, "description": "UiKit elements for Rocket.Chat Apps built under Fuselage design system", "homepage": "https://rocketchat.github.io/Rocket.Chat.Fuselage/", diff --git a/packages/gazzodown/CHANGELOG.md b/packages/gazzodown/CHANGELOG.md index 1f2884159850b..d970d1a6be749 100644 --- a/packages/gazzodown/CHANGELOG.md +++ b/packages/gazzodown/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/gazzodown +## 29.0.0 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [d1bf2cc675e80403659d388a1fbbdc6f73889dad, 02b1e6e6a184850d21e335077ca30382a1c7a66b, 9a70095296dbf516b0113a9a65e09f25137b2eaf, 539659af22bc19880eda047dfc0b152472ccb65c, b1b1d6ccd81c90d231a7e594f834965c6e5f4fae, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 43d0cfc6a70e8a31d5f3d24162216dae6b07efdd, d83a1a9753464ee916845b3c88757bbcf76884a5, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/message-parser@0.31.35 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/ui-contexts@29.0.0 + - @rocket.chat/ui-client@29.0.0 +
+ ## 29.0.0-rc.4 ### Patch Changes diff --git a/packages/gazzodown/package.json b/packages/gazzodown/package.json index e24998d20dcb6..64bddd9ca8189 100644 --- a/packages/gazzodown/package.json +++ b/packages/gazzodown/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/gazzodown", - "version": "29.0.0-rc.4", + "version": "29.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", @@ -76,7 +76,7 @@ "@rocket.chat/css-in-js": "*", "@rocket.chat/fuselage": "*", "@rocket.chat/fuselage-tokens": "*", - "@rocket.chat/message-parser": "0.31.35-rc.0", + "@rocket.chat/message-parser": "0.31.35", "@rocket.chat/styled": "*", "@rocket.chat/ui-client": "workspace:^", "@rocket.chat/ui-contexts": "workspace:^", diff --git a/packages/http-router/CHANGELOG.md b/packages/http-router/CHANGELOG.md index 6d6e9403499a1..ea38709f2fe17 100644 --- a/packages/http-router/CHANGELOG.md +++ b/packages/http-router/CHANGELOG.md @@ -1,5 +1,18 @@ # @rocket.chat/http-router +## 7.9.20 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [a4e3c1635d55ec4ce04cbde741426770e43581fb, 539659af22bc19880eda047dfc0b152472ccb65c, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/logger@1.0.1 +
+ ## 7.9.20-rc.4 ### Patch Changes diff --git a/packages/http-router/package.json b/packages/http-router/package.json index 0cb7192fd04d5..4ddb286e62c01 100644 --- a/packages/http-router/package.json +++ b/packages/http-router/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/http-router", - "version": "7.9.20-rc.4", + "version": "7.9.20", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index f6289309b77fd..bc14cdb03fd3a 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -1,5 +1,30 @@ # @rocket.chat/i18n +## 2.2.0 + +### Minor Changes + +- ([#37922](https://github.com/RocketChat/Rocket.Chat/pull/37922)) Introduces native screen sharing for internal voice calls. This feature is currently in beta and can be disabled through admin settings. + +- ([#39425](https://github.com/RocketChat/Rocket.Chat/pull/39425)) Adds support for multiple files in message composer, improving file upload experience + +- ([#40006](https://github.com/RocketChat/Rocket.Chat/pull/40006)) Removes the Federation beta callout as the feature leaves beta + +### Patch Changes + +- ([#39670](https://github.com/RocketChat/Rocket.Chat/pull/39670)) Fixes mismatched translations for Voice calling UI + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +- ([#38955](https://github.com/RocketChat/Rocket.Chat/pull/38955) by [@mossae](https://github.com/mossae)) Fixes invalid email domain error not being displayed on the registration form. + +- ([#39461](https://github.com/RocketChat/Rocket.Chat/pull/39461)) Deprecates `Anonymous write`. Feature will be removed in version 9.0.0. + +-
Updated dependencies [539659af22bc19880eda047dfc0b152472ccb65c]: + + - @rocket.chat/tools@0.2.5 +
+ ## 2.2.0-rc.0 ### Minor Changes diff --git a/packages/i18n/package.json b/packages/i18n/package.json index aa9b89c7be9fb..3064f1751f390 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/i18n", - "version": "2.2.0-rc.0", + "version": "2.2.0", "private": true, "type": "module", "exports": { diff --git a/packages/instance-status/CHANGELOG.md b/packages/instance-status/CHANGELOG.md index e032a56de0f7c..dd61bf419f309 100644 --- a/packages/instance-status/CHANGELOG.md +++ b/packages/instance-status/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/instance-status +## 0.1.53 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, eae3fb3136bd0b48294c050a71b0a36d05ca02b0]: + + - @rocket.chat/models@2.1.2 + - @rocket.chat/tracing@0.0.2 +
+ ## 0.1.53-rc.4 ### Patch Changes diff --git a/packages/instance-status/package.json b/packages/instance-status/package.json index 83beb5c30c771..5f09cbb3335f4 100644 --- a/packages/instance-status/package.json +++ b/packages/instance-status/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/instance-status", - "version": "0.1.53-rc.4", + "version": "0.1.53", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/jest-presets/CHANGELOG.md b/packages/jest-presets/CHANGELOG.md index a68c78daf6eee..7575c645b357f 100644 --- a/packages/jest-presets/CHANGELOG.md +++ b/packages/jest-presets/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/jest-presets +## 0.0.2 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.0.2-rc.0 ### Patch Changes diff --git a/packages/jest-presets/package.json b/packages/jest-presets/package.json index 22a9aa46a5ce0..ac7b52c84c660 100644 --- a/packages/jest-presets/package.json +++ b/packages/jest-presets/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/jest-presets", - "version": "0.0.2-rc.0", + "version": "0.0.2", "private": true, "type": "module", "exports": { diff --git a/packages/jwt/CHANGELOG.md b/packages/jwt/CHANGELOG.md index 2b0a64cb15db2..52e7223396c9e 100644 --- a/packages/jwt/CHANGELOG.md +++ b/packages/jwt/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/jwt +## 0.2.1 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.2.1-rc.0 ### Patch Changes diff --git a/packages/jwt/package.json b/packages/jwt/package.json index 6a126a50b2811..6e803c7162cb2 100644 --- a/packages/jwt/package.json +++ b/packages/jwt/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/jwt", - "version": "0.2.1-rc.0", + "version": "0.2.1", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/livechat/CHANGELOG.md b/packages/livechat/CHANGELOG.md index d2c3f8fe5bee3..acdb362f407f3 100644 --- a/packages/livechat/CHANGELOG.md +++ b/packages/livechat/CHANGELOG.md @@ -1,5 +1,23 @@ # @rocket.chat/livechat Change Log +## 2.1.0 + +### Minor Changes + +- ([#39268](https://github.com/RocketChat/Rocket.Chat/pull/39268)) refactor(ui-kit): Remove UiKit deprecations + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [d1bf2cc675e80403659d388a1fbbdc6f73889dad, 02b1e6e6a184850d21e335077ca30382a1c7a66b, 9a70095296dbf516b0113a9a65e09f25137b2eaf, 87f9262af4a543d52642a54e1ef546d509a79e23, 539659af22bc19880eda047dfc0b152472ccb65c, b1b1d6ccd81c90d231a7e594f834965c6e5f4fae]: + + - @rocket.chat/message-parser@0.31.35 + - @rocket.chat/ui-kit@1.0.0 + - @rocket.chat/gazzodown@29.0.0 + - @rocket.chat/random@1.2.3 +
+ ## 2.1.0-rc.4 ### Patch Changes diff --git a/packages/livechat/package.json b/packages/livechat/package.json index d1720c7cfcb8a..75ce55a0c516f 100644 --- a/packages/livechat/package.json +++ b/packages/livechat/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/livechat", - "version": "2.1.0-rc.4", + "version": "2.1.0", "homepage": "https://rocket.chat", "repository": { "type": "git", diff --git a/packages/log-format/CHANGELOG.md b/packages/log-format/CHANGELOG.md index 6044f0dc01486..442bd1fa4a701 100644 --- a/packages/log-format/CHANGELOG.md +++ b/packages/log-format/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/log-format +## 0.0.3 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.0.3-rc.0 ### Patch Changes diff --git a/packages/log-format/package.json b/packages/log-format/package.json index 0e95b1ef1f019..dc10f047aced4 100644 --- a/packages/log-format/package.json +++ b/packages/log-format/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/log-format", - "version": "0.0.3-rc.0", + "version": "0.0.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/logger/CHANGELOG.md b/packages/logger/CHANGELOG.md index d402c819e96a0..94eea78fd30c3 100644 --- a/packages/logger/CHANGELOG.md +++ b/packages/logger/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/logger +## 1.0.1 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 1.0.1-rc.0 ### Patch Changes diff --git a/packages/logger/package.json b/packages/logger/package.json index befba71fe9a06..c5f7d0333779f 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/logger", - "version": "1.0.1-rc.0", + "version": "1.0.1", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/media-signaling/CHANGELOG.md b/packages/media-signaling/CHANGELOG.md index 839f3c04dd57a..48261c6e2e362 100644 --- a/packages/media-signaling/CHANGELOG.md +++ b/packages/media-signaling/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/media-signaling +## 0.2.0 + +### Minor Changes + +- ([#37922](https://github.com/RocketChat/Rocket.Chat/pull/37922)) Introduces native screen sharing for internal voice calls. This feature is currently in beta and can be disabled through admin settings. + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.2.0-rc.0 ### Minor Changes diff --git a/packages/media-signaling/package.json b/packages/media-signaling/package.json index 3a0827990896a..20b6d78295ada 100644 --- a/packages/media-signaling/package.json +++ b/packages/media-signaling/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/media-signaling", - "version": "0.2.0-rc.0", + "version": "0.2.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/message-parser/CHANGELOG.md b/packages/message-parser/CHANGELOG.md index 89ea5070a46b8..9591d524ddcac 100644 --- a/packages/message-parser/CHANGELOG.md +++ b/packages/message-parser/CHANGELOG.md @@ -1,5 +1,19 @@ # Change Log +## 0.31.35 + +### Patch Changes + +- ([#39062](https://github.com/RocketChat/Rocket.Chat/pull/39062) by [@copilot-swe-agent](https://github.com/copilot-swe-agent)) Fixed blockquotes with empty lines between paragraphs not rendering as a single blockquote. Lines like `> ` or `>` (empty quote lines) are now treated as part of the surrounding blockquote rather than breaking it into separate quotes. + +- ([#39046](https://github.com/RocketChat/Rocket.Chat/pull/39046) by [@smirk-dev](https://github.com/smirk-dev)) Replaces wasteful `filter().shift()` with `find(Boolean)` in `extractFirstResult` to avoid allocating an intermediate filtered array just to get the first truthy element. + +- ([#39069](https://github.com/RocketChat/Rocket.Chat/pull/39069) by [@copilot-swe-agent](https://github.com/copilot-swe-agent)) Fixes trailing punctuation (e.g. periods, exclamation marks) being incorrectly included in parsed URLs when they appear at the end of a message. For example, `go to https://www.google.com.` now correctly parses the URL as `https://www.google.com` without the trailing period. + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +- ([#39052](https://github.com/RocketChat/Rocket.Chat/pull/39052) by [@Shreyas2004wagh](https://github.com/Shreyas2004wagh)) Fixes ordered list AST generation to preserve `number: 0` for list items that start at index `0`. + ## 0.31.35-rc.0 ### Patch Changes diff --git a/packages/message-parser/package.json b/packages/message-parser/package.json index 0ce59628aca70..ad11efa6e43a3 100644 --- a/packages/message-parser/package.json +++ b/packages/message-parser/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/message-parser", - "version": "0.31.35-rc.0", + "version": "0.31.35", "description": "Rocket.Chat parser for messages", "homepage": "https://github.com/RocketChat/fuselage#readme", "bugs": { diff --git a/packages/message-types/CHANGELOG.md b/packages/message-types/CHANGELOG.md index d1cb2d6961daf..cbd7dae062e2f 100644 --- a/packages/message-types/CHANGELOG.md +++ b/packages/message-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/message-types +## 0.1.1 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.1.1-rc.0 ### Patch Changes diff --git a/packages/message-types/package.json b/packages/message-types/package.json index 2e7933ccf5a0d..a08296c0a1d20 100644 --- a/packages/message-types/package.json +++ b/packages/message-types/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/message-types", - "version": "0.1.1-rc.0", + "version": "0.1.1", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/mock-providers/CHANGELOG.md b/packages/mock-providers/CHANGELOG.md index 3ec062382cdcf..c69f93ebb41d9 100644 --- a/packages/mock-providers/CHANGELOG.md +++ b/packages/mock-providers/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/mock-providers +## 0.4.13 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [652ff8cfe26b9068a776c39132c0eb5440702894, 539659af22bc19880eda047dfc0b152472ccb65c, 1741a20dd86c353755becfc706cd9ad63df09cfa, 85c0ac7d8c7a5b7b89ef58f4a42b18467a8e2dd4, c217b0bde182e5f76dbe1892d9b37d61ffab71db, 43d0cfc6a70e8a31d5f3d24162216dae6b07efdd, d83a1a9753464ee916845b3c88757bbcf76884a5, 788c161bb6c9544bec37034c93e2f60de1a6c316]: + + - @rocket.chat/i18n@2.2.0 + - @rocket.chat/ui-contexts@29.0.0 +
+ ## 0.4.13-rc.4 ### Patch Changes diff --git a/packages/mock-providers/package.json b/packages/mock-providers/package.json index 338de0816ca3a..a9aa725513645 100644 --- a/packages/mock-providers/package.json +++ b/packages/mock-providers/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/mock-providers", - "version": "0.4.13-rc.4", + "version": "0.4.13", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/model-typings/CHANGELOG.md b/packages/model-typings/CHANGELOG.md index 80728292976cb..44dd7c94e47ad 100644 --- a/packages/model-typings/CHANGELOG.md +++ b/packages/model-typings/CHANGELOG.md @@ -1,5 +1,20 @@ # @rocket.chat/model-typings +## 2.1.2 + +### Patch Changes + +- ([#39010](https://github.com/RocketChat/Rocket.Chat/pull/39010)) Fixes an authorization issue that allowed users to confirm uploads from other users + +- ([#39092](https://github.com/RocketChat/Rocket.Chat/pull/39092)) Fixes main channel scroll position changing when jumping to a thread message from search + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [539659af22bc19880eda047dfc0b152472ccb65c, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/core-typings@8.3.0 +
+ ## 2.1.2-rc.4 ### Patch Changes diff --git a/packages/model-typings/package.json b/packages/model-typings/package.json index 4156becf09d62..37306d326b1cc 100644 --- a/packages/model-typings/package.json +++ b/packages/model-typings/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/model-typings", - "version": "2.1.2-rc.4", + "version": "2.1.2", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/models/CHANGELOG.md b/packages/models/CHANGELOG.md index f53ab7c06b5c4..b8611952d546e 100644 --- a/packages/models/CHANGELOG.md +++ b/packages/models/CHANGELOG.md @@ -1,5 +1,28 @@ # @rocket.chat/models +## 2.1.2 + +### Patch Changes + +- ([#39010](https://github.com/RocketChat/Rocket.Chat/pull/39010)) Fixes an authorization issue that allowed users to confirm uploads from other users + +- ([#39092](https://github.com/RocketChat/Rocket.Chat/pull/39092)) Fixes main channel scroll position changing when jumping to a thread message from search + +- ([#39087](https://github.com/RocketChat/Rocket.Chat/pull/39087)) Fixes race condition causing duplicate open livechat rooms per visitor token. + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +- ([#39718](https://github.com/RocketChat/Rocket.Chat/pull/39718)) Fixes an issue where, sometimes, updatedAt was not being set during the subscription creation + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, a4e3c1635d55ec4ce04cbde741426770e43581fb, 539659af22bc19880eda047dfc0b152472ccb65c, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, 2a2701098536b32143003be8d267891978c708c9, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/model-typings@2.1.2 + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/tracing@0.0.2 + - @rocket.chat/random@1.2.3 + - @rocket.chat/sha256@1.0.13 +
+ ## 2.1.2-rc.4 ### Patch Changes diff --git a/packages/models/package.json b/packages/models/package.json index 73ad9e7330d1d..5bc182f020652 100644 --- a/packages/models/package.json +++ b/packages/models/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/models", - "version": "2.1.2-rc.4", + "version": "2.1.2", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/mongo-adapter/CHANGELOG.md b/packages/mongo-adapter/CHANGELOG.md index 9570036363df0..b51c5cd58e7a2 100644 --- a/packages/mongo-adapter/CHANGELOG.md +++ b/packages/mongo-adapter/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/account-utils +## 0.0.3 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.0.3-rc.0 ### Patch Changes diff --git a/packages/mongo-adapter/package.json b/packages/mongo-adapter/package.json index e5955435faec9..21f46de72eae2 100644 --- a/packages/mongo-adapter/package.json +++ b/packages/mongo-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/mongo-adapter", - "version": "0.0.3-rc.0", + "version": "0.0.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/node-poplib/CHANGELOG.md b/packages/node-poplib/CHANGELOG.md index 65ea0403f33b7..531e44c26ea89 100644 --- a/packages/node-poplib/CHANGELOG.md +++ b/packages/node-poplib/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/poplib +## 0.0.3 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.0.3-rc.0 ### Patch Changes diff --git a/packages/node-poplib/package.json b/packages/node-poplib/package.json index 5fb10829ecc36..6b88e7ce3581e 100644 --- a/packages/node-poplib/package.json +++ b/packages/node-poplib/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/poplib", - "version": "0.0.3-rc.0", + "version": "0.0.3", "private": true, "main": "./src/index.js", "devDependencies": { diff --git a/packages/omni-core/CHANGELOG.md b/packages/omni-core/CHANGELOG.md index 2097c6d0ddb73..d7d52f6e69e1b 100644 --- a/packages/omni-core/CHANGELOG.md +++ b/packages/omni-core/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/omni-core +## 0.0.18 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, eae3fb3136bd0b48294c050a71b0a36d05ca02b0]: + + - @rocket.chat/models@2.1.2 + - @rocket.chat/patch-injection@0.0.2 +
+ ## 0.0.18-rc.4 ### Patch Changes diff --git a/packages/omni-core/package.json b/packages/omni-core/package.json index 1c48140f80d0f..9e21fc69b5055 100644 --- a/packages/omni-core/package.json +++ b/packages/omni-core/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omni-core", - "version": "0.0.18-rc.4", + "version": "0.0.18", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/password-policies/CHANGELOG.md b/packages/password-policies/CHANGELOG.md index 00f5502f72b72..aae7ec07f7bec 100644 --- a/packages/password-policies/CHANGELOG.md +++ b/packages/password-policies/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/password-policies +## 0.1.1 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.1.1-rc.0 ### Patch Changes diff --git a/packages/password-policies/package.json b/packages/password-policies/package.json index 78360c4040ffb..b080e87a0bb29 100644 --- a/packages/password-policies/package.json +++ b/packages/password-policies/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/password-policies", - "version": "0.1.1-rc.0", + "version": "0.1.1", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/patch-injection/CHANGELOG.md b/packages/patch-injection/CHANGELOG.md index 96c991d01c735..844e47ee498d9 100644 --- a/packages/patch-injection/CHANGELOG.md +++ b/packages/patch-injection/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/patch-injection +## 0.0.2 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.0.2-rc.0 ### Patch Changes diff --git a/packages/patch-injection/package.json b/packages/patch-injection/package.json index f3928383bea85..58dac06fcc00f 100644 --- a/packages/patch-injection/package.json +++ b/packages/patch-injection/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/patch-injection", - "version": "0.0.2-rc.0", + "version": "0.0.2", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/peggy-loader/CHANGELOG.md b/packages/peggy-loader/CHANGELOG.md index 36eef4ef20d78..7226c16c2bff8 100644 --- a/packages/peggy-loader/CHANGELOG.md +++ b/packages/peggy-loader/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 0.31.28 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.31.28-rc.0 ### Patch Changes diff --git a/packages/peggy-loader/package.json b/packages/peggy-loader/package.json index 40f9d4888d61a..2378fe9297a70 100644 --- a/packages/peggy-loader/package.json +++ b/packages/peggy-loader/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/peggy-loader", - "version": "0.31.28-rc.0", + "version": "0.31.28", "description": "Peggy loader for webpack", "keywords": [ "peggy", diff --git a/packages/random/CHANGELOG.md b/packages/random/CHANGELOG.md index 6b66d1d9f77bf..0d2963e021a22 100644 --- a/packages/random/CHANGELOG.md +++ b/packages/random/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/random +## 1.2.3 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 1.2.3-rc.0 ### Patch Changes diff --git a/packages/random/package.json b/packages/random/package.json index 0b06e29fb249c..96b77bb8d2508 100644 --- a/packages/random/package.json +++ b/packages/random/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/random", - "version": "1.2.3-rc.0", + "version": "1.2.3", "private": true, "description": "Random number generator and utilities; Fork of Meteor's Random package", "main": "./dist/main.server.js", diff --git a/packages/release-action/CHANGELOG.md b/packages/release-action/CHANGELOG.md index 869c04ed9b820..caef877a9f73d 100644 --- a/packages/release-action/CHANGELOG.md +++ b/packages/release-action/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/release-action +## 2.2.4 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 2.2.4-rc.0 ### Patch Changes diff --git a/packages/release-action/package.json b/packages/release-action/package.json index b46a85c928f9d..6d50669bbe7d0 100644 --- a/packages/release-action/package.json +++ b/packages/release-action/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/release-action", - "version": "2.2.4-rc.0", + "version": "2.2.4", "private": true, "main": "dist/index.js", "scripts": { diff --git a/packages/release-changelog/CHANGELOG.md b/packages/release-changelog/CHANGELOG.md index f2697f52df282..9a6669951ddec 100644 --- a/packages/release-changelog/CHANGELOG.md +++ b/packages/release-changelog/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/release-changelog +## 0.1.1 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.1.1-rc.0 ### Patch Changes diff --git a/packages/release-changelog/package.json b/packages/release-changelog/package.json index af1e7e7fb3849..413c34e27f870 100644 --- a/packages/release-changelog/package.json +++ b/packages/release-changelog/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/release-changelog", - "version": "0.1.1-rc.0", + "version": "0.1.1", "private": true, "main": "dist/index.js", "scripts": { diff --git a/packages/rest-typings/CHANGELOG.md b/packages/rest-typings/CHANGELOG.md index bf7106365ee04..45d155c9d1dcb 100644 --- a/packages/rest-typings/CHANGELOG.md +++ b/packages/rest-typings/CHANGELOG.md @@ -1,5 +1,68 @@ # @rocket.chat/rest-typings +## 8.3.0 + +### Minor Changes + +- ([#38978](https://github.com/RocketChat/Rocket.Chat/pull/38978) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat autotranslate translateMessage API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation + +- ([#39225](https://github.com/RocketChat/Rocket.Chat/pull/39225) by [@sezallagwal](https://github.com/sezallagwal)) Add OpenAPI support for the chat.followMessage and chat.unfollowMessage API endpoints by migrating to a modern chained route definition syntax and utilizing AJV schemas for body and response validation. + +- ([#39227](https://github.com/RocketChat/Rocket.Chat/pull/39227) by [@sezallagwal](https://github.com/sezallagwal)) Add OpenAPI support for the chat.starMessage and chat.unStarMessage API endpoints by migrating to a modern chained route definition syntax and utilizing AJV schemas for body and response validation. + +- ([#38957](https://github.com/RocketChat/Rocket.Chat/pull/38957) by [@Verifieddanny](https://github.com/Verifieddanny)) Migrated rooms.leave endpoint to new OpenAPI pattern with AJV validation + +- ([#38549](https://github.com/RocketChat/Rocket.Chat/pull/38549) by [@Rohitgiri02](https://github.com/Rohitgiri02)) migrated rooms.delete endpoint to new OpenAPI pattern with AJV validation + +- ([#39094](https://github.com/RocketChat/Rocket.Chat/pull/39094) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Adds OpenAPI support for the Rocket.Chat e2e.updateGroupKey endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#36402](https://github.com/RocketChat/Rocket.Chat/pull/36402) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat users.getAvatarSuggestion API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#36779](https://github.com/RocketChat/Rocket.Chat/pull/36779) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat e2e.fetchMyKeys endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#39425](https://github.com/RocketChat/Rocket.Chat/pull/39425)) Adds support for multiple files in message composer, improving file upload experience + +- ([#39559](https://github.com/RocketChat/Rocket.Chat/pull/39559) by [@copilot-swe-agent](https://github.com/copilot-swe-agent)) Splits the single AJV validator instance into two: `ajv` (coerceTypes: false) for request **body** validation and `ajvQuery` (coerceTypes: true) for **query parameter** validation. + + **Why this matters:** Previously, a single AJV instance with `coerceTypes: true` was used everywhere. This silently accepted values with wrong types — for example, sending `{ "rid": 12345 }` (number) where a string was expected would pass validation because `12345` was coerced to `"12345"`. With this change, body validation is now strict: the server will reject payloads with incorrect types instead of silently coercing them. + + **What may break for API consumers:** + + - **Numeric values sent as strings in POST/PUT/PATCH bodies** (e.g., `{ "count": "10" }` instead of `{ "count": 10 }`) will now be rejected. Ensure JSON bodies use proper types. + - **Boolean values sent as strings in bodies** (e.g., `{ "readThreads": "true" }` instead of `{ "readThreads": true }`) will now be rejected. + - **`null` values where a string is expected** (e.g., `{ "name": null }` for a `type: 'string'` field without `nullable: true`) will no longer be coerced to `""`. + + **No change for query parameters:** GET query params (e.g., `?count=10&offset=0`) continue to be coerced via `ajvQuery`, since HTTP query strings are always strings. + +- ([#36916](https://github.com/RocketChat/Rocket.Chat/pull/36916) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat custom-user-status.list API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation + +- ([#39219](https://github.com/RocketChat/Rocket.Chat/pull/39219) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat e2e endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#38610](https://github.com/RocketChat/Rocket.Chat/pull/38610)) Adds new `custom-sounds.getOne` REST endpoint to retrieve a single custom sound by `_id` and updates client to consume it. + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +- ([#36786](https://github.com/RocketChat/Rocket.Chat/pull/36786) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat e2e.getUsersOfRoomWithoutKey endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#36882](https://github.com/RocketChat/Rocket.Chat/pull/36882) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat push.test API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#35995](https://github.com/RocketChat/Rocket.Chat/pull/35995) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat rooms.favorite APIs endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#36523](https://github.com/RocketChat/Rocket.Chat/pull/36523) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat emoji-custom.create API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#36953](https://github.com/RocketChat/Rocket.Chat/pull/36953) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat commands.get API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +- ([#38974](https://github.com/RocketChat/Rocket.Chat/pull/38974) by [@ahmed-n-abdeltwab](https://github.com/ahmed-n-abdeltwab)) Add OpenAPI support for the Rocket.Chat dm.close/im.close API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. + +-
Updated dependencies [d1bf2cc675e80403659d388a1fbbdc6f73889dad, 02b1e6e6a184850d21e335077ca30382a1c7a66b, 9a70095296dbf516b0113a9a65e09f25137b2eaf, 87f9262af4a543d52642a54e1ef546d509a79e23, 539659af22bc19880eda047dfc0b152472ccb65c, b1b1d6ccd81c90d231a7e594f834965c6e5f4fae, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, d83a1a9753464ee916845b3c88757bbcf76884a5, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, c117492ad90d291a361eedc929506f557495caf7]: + + - @rocket.chat/message-parser@0.31.35 + - @rocket.chat/ui-kit@1.0.0 + - @rocket.chat/core-typings@8.3.0 +
+ ## 8.3.0-rc.4 ### Patch Changes diff --git a/packages/rest-typings/package.json b/packages/rest-typings/package.json index 5ffcb33156a20..73e3b81c67438 100644 --- a/packages/rest-typings/package.json +++ b/packages/rest-typings/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/rest-typings", - "version": "8.3.0-rc.4", + "version": "8.3.0", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/server-cloud-communication/CHANGELOG.md b/packages/server-cloud-communication/CHANGELOG.md index 075ac1873ad22..a655ff75f6d74 100644 --- a/packages/server-cloud-communication/CHANGELOG.md +++ b/packages/server-cloud-communication/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/server-cloud-communication +## 0.0.3 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.0.3-rc.0 ### Patch Changes diff --git a/packages/server-cloud-communication/package.json b/packages/server-cloud-communication/package.json index e78c26bd0155e..f8d5080e26757 100644 --- a/packages/server-cloud-communication/package.json +++ b/packages/server-cloud-communication/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/server-cloud-communication", - "version": "0.0.3-rc.0", + "version": "0.0.3", "private": true, "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/server-fetch/CHANGELOG.md b/packages/server-fetch/CHANGELOG.md index 0ea6145009f99..229d7b90d3f33 100644 --- a/packages/server-fetch/CHANGELOG.md +++ b/packages/server-fetch/CHANGELOG.md @@ -1,5 +1,18 @@ # @rocket.chat/server-fetch +## 0.1.2 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, eae3fb3136bd0b48294c050a71b0a36d05ca02b0]: + + - @rocket.chat/models@2.1.2 + - @rocket.chat/logger@1.0.1 + - @rocket.chat/tools@0.2.5 +
+ ## 0.1.2-rc.4 ### Patch Changes diff --git a/packages/server-fetch/package.json b/packages/server-fetch/package.json index 8e5ab109a6c9d..67eff072e2aec 100644 --- a/packages/server-fetch/package.json +++ b/packages/server-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/server-fetch", - "version": "0.1.2-rc.4", + "version": "0.1.2", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/sha256/CHANGELOG.md b/packages/sha256/CHANGELOG.md index a49f4e8a8a000..d31c84c3533f3 100644 --- a/packages/sha256/CHANGELOG.md +++ b/packages/sha256/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/sha256 +## 1.0.13 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 1.0.13-rc.0 ### Patch Changes diff --git a/packages/sha256/package.json b/packages/sha256/package.json index ac0d5ad87b2f3..5babb6fe05c02 100644 --- a/packages/sha256/package.json +++ b/packages/sha256/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/sha256", - "version": "1.0.13-rc.0", + "version": "1.0.13", "private": true, "description": "SHA256 implementation; Fork of Meteor's SHA256 package", "main": "./dist/sha256.js", diff --git a/packages/storybook-config/CHANGELOG.md b/packages/storybook-config/CHANGELOG.md index 9766db6dd5e4b..0ac1498f09a81 100644 --- a/packages/storybook-config/CHANGELOG.md +++ b/packages/storybook-config/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/storybook-config +## 0.0.3 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.0.3-rc.0 ### Patch Changes diff --git a/packages/storybook-config/package.json b/packages/storybook-config/package.json index 0ea282269824f..5e3a3dc92aee5 100644 --- a/packages/storybook-config/package.json +++ b/packages/storybook-config/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/storybook-config", - "version": "0.0.3-rc.0", + "version": "0.0.3", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/tools/CHANGELOG.md b/packages/tools/CHANGELOG.md index 0efaeaf32a000..2866523d2880a 100644 --- a/packages/tools/CHANGELOG.md +++ b/packages/tools/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/tools +## 0.2.5 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.2.5-rc.0 ### Patch Changes diff --git a/packages/tools/package.json b/packages/tools/package.json index 6bb22d20c3af3..286be26730976 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/tools", - "version": "0.2.5-rc.0", + "version": "0.2.5", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/tracing/CHANGELOG.md b/packages/tracing/CHANGELOG.md index 359799ca15d64..bf12bfcac5dbe 100644 --- a/packages/tracing/CHANGELOG.md +++ b/packages/tracing/CHANGELOG.md @@ -1,5 +1,11 @@ # @rocket.chat/tracing +## 0.0.2 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.0.2-rc.0 ### Patch Changes diff --git a/packages/tracing/package.json b/packages/tracing/package.json index ff9fd7be428d6..90f5dd9ec6151 100644 --- a/packages/tracing/package.json +++ b/packages/tracing/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/tracing", - "version": "0.0.2-rc.0", + "version": "0.0.2", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-avatar/CHANGELOG.md b/packages/ui-avatar/CHANGELOG.md index 47da0cbb431c8..cce9fec4a6ec6 100644 --- a/packages/ui-avatar/CHANGELOG.md +++ b/packages/ui-avatar/CHANGELOG.md @@ -1,5 +1,16 @@ # @rocket.chat/ui-avatar +## 25.0.0 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [539659af22bc19880eda047dfc0b152472ccb65c, 43d0cfc6a70e8a31d5f3d24162216dae6b07efdd]: + + - @rocket.chat/ui-contexts@29.0.0 +
+ ## 25.0.0-rc.4 ### Patch Changes diff --git a/packages/ui-avatar/package.json b/packages/ui-avatar/package.json index d8aec2b761238..b65f157b1a1b5 100644 --- a/packages/ui-avatar/package.json +++ b/packages/ui-avatar/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-avatar", - "version": "25.0.0-rc.4", + "version": "25.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-client/CHANGELOG.md b/packages/ui-client/CHANGELOG.md index 78a7415064ad4..c35fb4476be46 100644 --- a/packages/ui-client/CHANGELOG.md +++ b/packages/ui-client/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/ui-client +## 29.0.0 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [539659af22bc19880eda047dfc0b152472ccb65c, 43d0cfc6a70e8a31d5f3d24162216dae6b07efdd]: + + - @rocket.chat/ui-contexts@29.0.0 + - @rocket.chat/ui-avatar@25.0.0 +
+ ## 29.0.0-rc.4 ### Patch Changes diff --git a/packages/ui-client/package.json b/packages/ui-client/package.json index 374465dccfed0..3f03fa7e2dbfe 100644 --- a/packages/ui-client/package.json +++ b/packages/ui-client/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-client", - "version": "29.0.0-rc.4", + "version": "29.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-composer/CHANGELOG.md b/packages/ui-composer/CHANGELOG.md index 7abe9c9414b40..a6b88e44f66e8 100644 --- a/packages/ui-composer/CHANGELOG.md +++ b/packages/ui-composer/CHANGELOG.md @@ -1,5 +1,15 @@ # @rocket.chat/ui-composer +## 0.6.0 + +### Minor Changes + +- ([#39425](https://github.com/RocketChat/Rocket.Chat/pull/39425)) Adds support for multiple files in message composer, improving file upload experience + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 0.6.0-rc.0 ### Minor Changes diff --git a/packages/ui-composer/package.json b/packages/ui-composer/package.json index 3ae993cec607e..8c81f33b7e9cb 100644 --- a/packages/ui-composer/package.json +++ b/packages/ui-composer/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-composer", - "version": "0.6.0-rc.0", + "version": "0.6.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-contexts/CHANGELOG.md b/packages/ui-contexts/CHANGELOG.md index 56f6d2c8826d9..d6a756563ff30 100644 --- a/packages/ui-contexts/CHANGELOG.md +++ b/packages/ui-contexts/CHANGELOG.md @@ -1,5 +1,22 @@ # @rocket.chat/ui-contexts +## 29.0.0 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +- ([#39054](https://github.com/RocketChat/Rocket.Chat/pull/39054)) Fixes a mismatch in the room icons on the sidebar items, ABAC Managed rooms were not displaying the correct icon + +-
Updated dependencies [a4e3c1635d55ec4ce04cbde741426770e43581fb, 652ff8cfe26b9068a776c39132c0eb5440702894, 539659af22bc19880eda047dfc0b152472ccb65c, 1741a20dd86c353755becfc706cd9ad63df09cfa, 5518503736b72674753e711ba4089d177ab988a5, a4341ec67d1f0413f30bbabfd292d1b0a41728b2, 40253146de8d8f83737e71b0ade7c67e0c295a28, 85c0ac7d8c7a5b7b89ef58f4a42b18467a8e2dd4, 803b8075514de54c9ff34ba0c9aa3ee5fc3bbe61, 1361a1f4f1e3c0cc3f2a191cef8eccc12a714cde, c217b0bde182e5f76dbe1892d9b37d61ffab71db, 2a2701098536b32143003be8d267891978c708c9, 78e37dc3deae4ff05f5e33f9134c7094fd6c1330, 37acece030bc9f39bdaa86ab0130eb818332033e, d8baf395181b70fef9ce448eb509f65b66049615, ddc0ed34b03072362d166f1160104a9332b362e8, d83a1a9753464ee916845b3c88757bbcf76884a5, 4c2e444216efd514ab406fe8e9cd127ef971d566, 722df6f60bc86c51b204e28a39acb3dc8710bdeb, 78b3fe3ef20e3a545b84551ba3f85cb40e862ba7, 98a6c58a38c053c60db2b4d53a9df0e94fecf0ba, 29b453e1def8092a8d78c28736e2bfb24229717b, 788c161bb6c9544bec37034c93e2f60de1a6c316, 39f2e87e1caa6842e69155f033205cfdc4767b9e, c117492ad90d291a361eedc929506f557495caf7, 7c7324184589a15bf3e67b4f0c1cc222f8d48db3]: + + - @rocket.chat/rest-typings@8.3.0 + - @rocket.chat/i18n@2.2.0 + - @rocket.chat/password-policies@0.1.1 + - @rocket.chat/core-typings@8.3.0 + - @rocket.chat/ddp-client@1.0.6 +
+ ## 29.0.0-rc.4 ### Patch Changes diff --git a/packages/ui-contexts/package.json b/packages/ui-contexts/package.json index 8192cdb246dd1..a2dca53a45111 100644 --- a/packages/ui-contexts/package.json +++ b/packages/ui-contexts/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-contexts", - "version": "29.0.0-rc.4", + "version": "29.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-kit/CHANGELOG.md b/packages/ui-kit/CHANGELOG.md index 3c78d5ff40294..894e366a019c7 100644 --- a/packages/ui-kit/CHANGELOG.md +++ b/packages/ui-kit/CHANGELOG.md @@ -1,5 +1,15 @@ # Change Log +## 1.0.0 + +### Major Changes + +- ([#39268](https://github.com/RocketChat/Rocket.Chat/pull/39268)) refactor(ui-kit): Remove UiKit deprecations + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + ## 1.0.0-rc.0 ### Major Changes diff --git a/packages/ui-kit/package.json b/packages/ui-kit/package.json index bf464a1a96d1d..94c69c58b407b 100644 --- a/packages/ui-kit/package.json +++ b/packages/ui-kit/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-kit", - "version": "1.0.0-rc.0", + "version": "1.0.0", "description": "Interactive UI elements for Rocket.Chat Apps", "homepage": "https://rocket.chat", "bugs": { diff --git a/packages/ui-video-conf/CHANGELOG.md b/packages/ui-video-conf/CHANGELOG.md index 5ef072fac264f..b36bdeb29c4b7 100644 --- a/packages/ui-video-conf/CHANGELOG.md +++ b/packages/ui-video-conf/CHANGELOG.md @@ -1,5 +1,17 @@ # @rocket.chat/ui-video-conf +## 29.0.0 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [539659af22bc19880eda047dfc0b152472ccb65c, 43d0cfc6a70e8a31d5f3d24162216dae6b07efdd]: + + - @rocket.chat/ui-contexts@29.0.0 + - @rocket.chat/ui-avatar@25.0.0 +
+ ## 29.0.0-rc.4 ### Patch Changes diff --git a/packages/ui-video-conf/package.json b/packages/ui-video-conf/package.json index 862db1de077fd..9751d2b2f8459 100644 --- a/packages/ui-video-conf/package.json +++ b/packages/ui-video-conf/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-video-conf", - "version": "29.0.0-rc.4", + "version": "29.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-voip/CHANGELOG.md b/packages/ui-voip/CHANGELOG.md index edeeaf877f143..20314a8a724a3 100644 --- a/packages/ui-voip/CHANGELOG.md +++ b/packages/ui-voip/CHANGELOG.md @@ -1,5 +1,27 @@ # @rocket.chat/ui-voip +## 19.0.0 + +### Minor Changes + +- ([#37922](https://github.com/RocketChat/Rocket.Chat/pull/37922)) Introduces native screen sharing for internal voice calls. This feature is currently in beta and can be disabled through admin settings. + +### Patch Changes + +- ([#39670](https://github.com/RocketChat/Rocket.Chat/pull/39670)) Fixes mismatched translations for Voice calling UI + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +-
Updated dependencies [87f9262af4a543d52642a54e1ef546d509a79e23, 539659af22bc19880eda047dfc0b152472ccb65c, 1741a20dd86c353755becfc706cd9ad63df09cfa, 43d0cfc6a70e8a31d5f3d24162216dae6b07efdd]: + + - @rocket.chat/fuselage-ui-kit@29.0.0 + - @rocket.chat/media-signaling@0.2.0 + - @rocket.chat/desktop-api@1.1.1 + - @rocket.chat/ui-contexts@29.0.0 + - @rocket.chat/ui-avatar@25.0.0 + - @rocket.chat/ui-client@29.0.0 +
+ ## 19.0.0-rc.4 ### Patch Changes diff --git a/packages/ui-voip/package.json b/packages/ui-voip/package.json index f442786c1390a..a1321d4846eec 100644 --- a/packages/ui-voip/package.json +++ b/packages/ui-voip/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-voip", - "version": "19.0.0-rc.4", + "version": "19.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/web-ui-registration/CHANGELOG.md b/packages/web-ui-registration/CHANGELOG.md index a928e931f7bdd..d53ab86584492 100644 --- a/packages/web-ui-registration/CHANGELOG.md +++ b/packages/web-ui-registration/CHANGELOG.md @@ -1,5 +1,19 @@ # @rocket.chat/web-ui-registration +## 29.0.0 + +### Patch Changes + +- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration + +- ([#38955](https://github.com/RocketChat/Rocket.Chat/pull/38955) by [@mossae](https://github.com/mossae)) Fixes invalid email domain error not being displayed on the registration form. + +-
Updated dependencies [539659af22bc19880eda047dfc0b152472ccb65c, 43d0cfc6a70e8a31d5f3d24162216dae6b07efdd]: + + - @rocket.chat/ui-contexts@29.0.0 + - @rocket.chat/tools@0.2.5 +
+ ## 29.0.0-rc.4 ### Patch Changes diff --git a/packages/web-ui-registration/package.json b/packages/web-ui-registration/package.json index 45843ad39fd29..c5718a746863c 100644 --- a/packages/web-ui-registration/package.json +++ b/packages/web-ui-registration/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/web-ui-registration", - "version": "29.0.0-rc.4", + "version": "29.0.0", "private": true, "homepage": "https://rocket.chat", "main": "./dist/index.js", @@ -59,8 +59,8 @@ }, "peerDependencies": { "@rocket.chat/layout": "*", - "@rocket.chat/tools": "0.2.5-rc.0", - "@rocket.chat/ui-contexts": "29.0.0-rc.4", + "@rocket.chat/tools": "0.2.5", + "@rocket.chat/ui-contexts": "29.0.0", "@tanstack/react-query": "*", "react": "*", "react-hook-form": "*", diff --git a/yarn.lock b/yarn.lock index f24e6b61ad2ba..b5d473b51178e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11366,7 +11366,7 @@ __metadata: peerDependencies: "@rocket.chat/layout": "*" "@rocket.chat/tools": 0.2.5-rc.0 - "@rocket.chat/ui-contexts": 29.0.0-rc.3 + "@rocket.chat/ui-contexts": 29.0.0-rc.4 "@tanstack/react-query": "*" react: "*" react-hook-form: "*" From 2031ba8986e6d15b0988b195bcd0a7c44d605153 Mon Sep 17 00:00:00 2001 From: Douglas Fabris Date: Tue, 7 Apr 2026 14:14:19 -0300 Subject: [PATCH 23/51] test: Reorg flextabs locators (#38533) --- .../client/components/UserInfo/UserInfo.tsx | 14 +- .../__snapshots__/UserInfo.spec.tsx.snap | 60 ++++---- .../AddExistingModal/AddExistingModal.tsx | 6 +- apps/meteor/tests/e2e/account-profile.spec.ts | 4 +- apps/meteor/tests/e2e/avatar-settings.ts | 4 +- .../tests/e2e/channel-management.spec.ts | 38 ++--- .../e2ee-encrypted-channels.spec.ts | 35 ++--- .../e2e-encryption/e2ee-pdf-export.spec.ts | 6 +- apps/meteor/tests/e2e/export-messages.spec.ts | 113 ++++++-------- apps/meteor/tests/e2e/feature-preview.spec.ts | 75 ++++----- apps/meteor/tests/e2e/message-actions.spec.ts | 16 +- .../page-objects/admin-device-management.ts | 2 +- .../tests/e2e/page-objects/admin-emojis.ts | 2 +- .../tests/e2e/page-objects/admin-rooms.ts | 6 +- .../tests/e2e/page-objects/encrypted-room.ts | 28 ++-- .../fragments/edit-room-flextab.ts | 91 ----------- .../flextabs/admin-edit-room-flextab.ts | 49 ++++++ .../{ => flextabs}/admin-flextab-emoji.ts | 0 .../fragments/flextabs/channels-flextab.ts | 83 ++++++++++ .../{ => flextabs}/device-info-flextab.ts | 0 .../edit-contact-flextab.ts} | 0 .../fragments/flextabs/edit-room-flextab.ts | 114 ++++++++++++++ .../{ => flextabs}/edit-user-flextab.ts | 0 .../export-messages-flextab.ts} | 2 +- .../fragments/{ => flextabs}/files-flextab.ts | 4 +- .../fragments/{ => flextabs}/flextab.ts | 5 +- .../page-objects/fragments/flextabs/index.ts | 16 ++ .../fragments/flextabs/members-flextab.ts | 145 ++++++++++++++++++ .../notification-preferences-flextab.ts} | 26 ++-- .../flextabs/prune-messages-flextab.ts | 37 +++++ .../fragments/flextabs/room-info-flextab.ts | 124 +++++++++++++++ .../search-messages-flextab.ts} | 0 .../fragments/flextabs/threads-flextab.ts | 17 ++ .../{ => flextabs}/user-info-flextab.ts | 10 +- .../page-objects/fragments/home-content.ts | 8 - .../fragments/home-flextab-channels.ts | 57 ------- .../fragments/home-flextab-members.ts | 91 ----------- .../fragments/home-flextab-pruneMessages.ts | 29 ---- .../fragments/home-flextab-room.ts | 138 ----------------- .../page-objects/fragments/home-flextab.ts | 86 ----------- .../tests/e2e/page-objects/fragments/index.ts | 5 +- .../fragments/modals/confirm-delete-modal.ts | 30 ++++ .../fragments/modals/confirm-remove-modal.ts | 18 +++ .../page-objects/fragments/modals/index.ts | 1 + .../fragments/room-info-flextab.ts | 31 ---- .../e2e/page-objects/fragments/toolbar.ts | 64 +++++--- .../e2e/page-objects/fragments/user-card.ts | 31 ++++ .../tests/e2e/page-objects/home-channel.ts | 57 ++++++- .../tests/e2e/page-objects/home-discussion.ts | 37 +---- .../e2e/page-objects/home-omnichannel.ts | 4 +- .../tests/e2e/page-objects/home-team.ts | 29 ++-- .../omnichannel/omnichannel-agents.ts | 2 +- .../omnichannel-contact-center-chats.ts | 2 +- .../omnichannel-contact-center-contacts.ts | 2 +- .../omnichannel/omnichannel-custom-fields.ts | 2 +- .../omnichannel/omnichannel-info.ts | 2 +- .../omnichannel/omnichannel-priorities.ts | 2 +- .../omnichannel/omnichannel-sla-policies.ts | 2 +- .../omnichannel/omnichannel-tags.ts | 2 +- .../omnichannel/omnichannel-triggers.ts | 2 +- .../omnichannel/omnichannel-units.ts | 2 +- apps/meteor/tests/e2e/prune-messages.spec.ts | 29 ++-- .../meteor/tests/e2e/retention-policy.spec.ts | 65 ++++---- apps/meteor/tests/e2e/team-management.spec.ts | 99 +++++------- .../components/InfoPanel/InfoPanelField.tsx | 8 +- 65 files changed, 1108 insertions(+), 961 deletions(-) delete mode 100644 apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/flextabs/admin-edit-room-flextab.ts rename apps/meteor/tests/e2e/page-objects/fragments/{ => flextabs}/admin-flextab-emoji.ts (100%) create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/flextabs/channels-flextab.ts rename apps/meteor/tests/e2e/page-objects/fragments/{ => flextabs}/device-info-flextab.ts (100%) rename apps/meteor/tests/e2e/page-objects/fragments/{edit-contact-flaxtab.ts => flextabs/edit-contact-flextab.ts} (100%) create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/flextabs/edit-room-flextab.ts rename apps/meteor/tests/e2e/page-objects/fragments/{ => flextabs}/edit-user-flextab.ts (100%) rename apps/meteor/tests/e2e/page-objects/fragments/{export-messages-tab.ts => flextabs/export-messages-flextab.ts} (97%) rename apps/meteor/tests/e2e/page-objects/fragments/{ => flextabs}/files-flextab.ts (90%) rename apps/meteor/tests/e2e/page-objects/fragments/{ => flextabs}/flextab.ts (82%) create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/flextabs/index.ts create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/flextabs/members-flextab.ts rename apps/meteor/tests/e2e/page-objects/fragments/{home-flextab-notificationPreferences.ts => flextabs/notification-preferences-flextab.ts} (53%) create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/flextabs/prune-messages-flextab.ts create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/flextabs/room-info-flextab.ts rename apps/meteor/tests/e2e/page-objects/fragments/{searchMessages-flextab.ts => flextabs/search-messages-flextab.ts} (100%) create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/flextabs/threads-flextab.ts rename apps/meteor/tests/e2e/page-objects/fragments/{ => flextabs}/user-info-flextab.ts (76%) delete mode 100644 apps/meteor/tests/e2e/page-objects/fragments/home-flextab-channels.ts delete mode 100644 apps/meteor/tests/e2e/page-objects/fragments/home-flextab-members.ts delete mode 100644 apps/meteor/tests/e2e/page-objects/fragments/home-flextab-pruneMessages.ts delete mode 100644 apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts delete mode 100644 apps/meteor/tests/e2e/page-objects/fragments/home-flextab.ts create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/modals/confirm-remove-modal.ts delete mode 100644 apps/meteor/tests/e2e/page-objects/fragments/room-info-flextab.ts create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/user-card.ts diff --git a/apps/meteor/client/components/UserInfo/UserInfo.tsx b/apps/meteor/client/components/UserInfo/UserInfo.tsx index 59ddb7710a921..1f32888e901cf 100644 --- a/apps/meteor/client/components/UserInfo/UserInfo.tsx +++ b/apps/meteor/client/components/UserInfo/UserInfo.tsx @@ -14,7 +14,7 @@ import { } from '@rocket.chat/ui-client'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import type { ReactElement, ReactNode } from 'react'; -import { memo } from 'react'; +import { memo, useId } from 'react'; import { useTranslation } from 'react-i18next'; import { useTimeAgo } from '../../hooks/useTimeAgo'; @@ -84,6 +84,8 @@ const UserInfo = ({ const userDisplayName = useUserDisplayName({ name, username }); const userCustomFields = useUserCustomFields(customFields); + const usernameId = useId(); + return ( @@ -128,9 +130,13 @@ const UserInfo = ({ )} {username && username !== name && ( - - {t('Username')} - {username} + + + {t('Username')} + + + {username} + )} diff --git a/apps/meteor/client/components/UserInfo/__snapshots__/UserInfo.spec.tsx.snap b/apps/meteor/client/components/UserInfo/__snapshots__/UserInfo.spec.tsx.snap index 7f31acf80c25b..d9a9819ddbc26 100644 --- a/apps/meteor/client/components/UserInfo/__snapshots__/UserInfo.spec.tsx.snap +++ b/apps/meteor/client/components/UserInfo/__snapshots__/UserInfo.spec.tsx.snap @@ -164,21 +164,22 @@ exports[`renders Default without crashing 1`] = ` -
-
Username -
-
+
guilherme.gazzo -
-
+ +
@@ -467,21 +468,22 @@ exports[`renders InvitedUser without crashing 1`] = `
-
-
Username -
-
+
guilherme.gazzo -
-
+ +
@@ -784,21 +786,22 @@ exports[`renders WithABACAttributes without crashing 1`] = `
-
-
Username -
-
+
guilherme.gazzo -
-
+ +
@@ -1147,21 +1150,22 @@ exports[`renders WithVoiceCallExtension without crashing 1`] = `
-
-
Username -
-
+
guilherme.gazzo -
-
+ +
diff --git a/apps/meteor/client/views/teams/contextualBar/channels/AddExistingModal/AddExistingModal.tsx b/apps/meteor/client/views/teams/contextualBar/channels/AddExistingModal/AddExistingModal.tsx index c780a00a135f3..25ea5043d1d15 100644 --- a/apps/meteor/client/views/teams/contextualBar/channels/AddExistingModal/AddExistingModal.tsx +++ b/apps/meteor/client/views/teams/contextualBar/channels/AddExistingModal/AddExistingModal.tsx @@ -29,6 +29,7 @@ type AddExistingModalProps = { reload?: () => void; }; +// TODO: Use GenericModal instead of Modal const AddExistingModal = ({ teamId, onClose, reload }: AddExistingModalProps) => { const { t } = useTranslation(); const dispatchToastMessage = useToastMessageDispatch(); @@ -61,7 +62,10 @@ const AddExistingModal = ({ teamId, onClose, reload }: AddExistingModalProps) => ); return ( - }> + } + > {t('Team_Add_existing_channels')} diff --git a/apps/meteor/tests/e2e/account-profile.spec.ts b/apps/meteor/tests/e2e/account-profile.spec.ts index 809764ff507bf..6e3c1e33073db 100644 --- a/apps/meteor/tests/e2e/account-profile.spec.ts +++ b/apps/meteor/tests/e2e/account-profile.spec.ts @@ -37,9 +37,9 @@ test.describe.serial('settings-account-profile', () => { await expect(poHomeChannel.content.lastUserMessageNotSequential).toContainText(newUsername); await poHomeChannel.content.lastUserMessageNotSequential.locator('figure').click(); - await poHomeChannel.content.linkUserCard.click(); + await poHomeChannel.userCard.openUserInfo(); - await expect(poHomeChannel.tabs.userInfoUsername).toHaveText(newUsername); + await expect(poHomeChannel.tabs.userInfo.username).toHaveText(newUsername); }); test.describe('Avatar', () => { diff --git a/apps/meteor/tests/e2e/avatar-settings.ts b/apps/meteor/tests/e2e/avatar-settings.ts index cf9527f2259f6..f5ab84f3885dc 100644 --- a/apps/meteor/tests/e2e/avatar-settings.ts +++ b/apps/meteor/tests/e2e/avatar-settings.ts @@ -86,12 +86,12 @@ test.describe('avatar-settings', () => { testAvatars(poHomeChannel, channelName, avatarUrl); test('expect message avatar to have provider prefix', async () => { - expect(poHomeChannel.content.lastUserMessage.locator('img').getAttribute('src')).toBe(avatarUrl); + await expect(poHomeChannel.content.lastUserMessage.locator('img')).toHaveAttribute('src', avatarUrl); }); test('expect user card avatar to have provider prefix', async () => { await poHomeChannel.content.lastUserMessage.locator('.rcx-message-header__name-container').click(); - expect(poHomeChannel.content.userCard.locator('img').getAttribute('src')).toBe(avatarUrl); + await expect(poHomeChannel.userCard.imgUserCard).toHaveAttribute('src', avatarUrl); }); }); }); diff --git a/apps/meteor/tests/e2e/channel-management.spec.ts b/apps/meteor/tests/e2e/channel-management.spec.ts index a6b3a064835c0..d74e91acab303 100644 --- a/apps/meteor/tests/e2e/channel-management.spec.ts +++ b/apps/meteor/tests/e2e/channel-management.spec.ts @@ -62,13 +62,13 @@ test.describe.serial('channel-management', () => { await poHomeChannel.navbar.openChat(targetChannel); await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await poHomeChannel.tabs.room.inputTopic.fill('hello-topic-edited'); - await poHomeChannel.tabs.room.btnSave.click(); + await poHomeChannel.tabs.editRoom.inputTopic.fill('hello-topic-edited'); + await poHomeChannel.tabs.editRoom.btnSave.click(); await poHomeChannel.toastMessage.dismissToast(); await poHomeChannel.roomToolbar.openRoomInfo(); - await expect(poHomeChannel.tabs.room.panelChannelInfo).toContainText('hello-topic-edited'); + await expect(poHomeChannel.tabs.room.root).toContainText('hello-topic-edited'); await expect(poHomeChannel.content.getSystemMessageByText('changed room topic to hello-topic-edited')).toBeVisible(); }); @@ -76,12 +76,12 @@ test.describe.serial('channel-management', () => { await poHomeChannel.navbar.openChat(targetChannel); await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await poHomeChannel.tabs.room.inputAnnouncement.fill('hello-announcement-edited'); - await poHomeChannel.tabs.room.btnSave.click(); + await poHomeChannel.tabs.editRoom.inputAnnouncement.fill('hello-announcement-edited'); + await poHomeChannel.tabs.editRoom.btnSave.click(); await poHomeChannel.toastMessage.dismissToast(); await poHomeChannel.roomToolbar.openRoomInfo(); - await expect(poHomeChannel.tabs.room.panelChannelInfo).toContainText('hello-announcement-edited'); + await expect(poHomeChannel.tabs.room.root).toContainText('hello-announcement-edited'); await expect(poHomeChannel.content.getSystemMessageByText('changed room announcement to: hello-announcement-edited')).toBeVisible(); }); @@ -89,12 +89,12 @@ test.describe.serial('channel-management', () => { await poHomeChannel.navbar.openChat(targetChannel); await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await poHomeChannel.tabs.room.inputDescription.fill('hello-description-edited'); - await poHomeChannel.tabs.room.btnSave.click(); + await poHomeChannel.tabs.editRoom.inputDescription.fill('hello-description-edited'); + await poHomeChannel.tabs.editRoom.btnSave.click(); await poHomeChannel.toastMessage.dismissToast(); await poHomeChannel.roomToolbar.openRoomInfo(); - await expect(poHomeChannel.tabs.room.panelChannelInfo).toContainText('hello-description-edited'); + await expect(poHomeChannel.tabs.room.root).toContainText('hello-description-edited'); await expect(poHomeChannel.content.getSystemMessageByText('changed room description to: hello-description-edited')).toBeVisible(); }); @@ -102,8 +102,8 @@ test.describe.serial('channel-management', () => { await poHomeChannel.navbar.openChat(targetChannel); await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await poHomeChannel.tabs.room.inputName.fill(`NAME-EDITED-${targetChannel}`); - await poHomeChannel.tabs.room.btnSave.click(); + await poHomeChannel.tabs.editRoom.inputName.fill(`NAME-EDITED-${targetChannel}`); + await poHomeChannel.tabs.editRoom.btnSave.click(); targetChannel = `NAME-EDITED-${targetChannel}`; await expect(page.getByRole('main').getByRole('heading', { name: targetChannel })).toBeVisible(); @@ -117,8 +117,8 @@ test.describe.serial('channel-management', () => { await poHomeChannel.navbar.openChat(targetChannel); await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await poHomeChannel.tabs.room.inputName.fill(hugeName); - await poHomeChannel.tabs.room.btnSave.click(); + await poHomeChannel.tabs.editRoom.inputName.fill(hugeName); + await poHomeChannel.tabs.editRoom.btnSave.click(); targetChannel = hugeName; await page.setViewportSize({ width: 640, height: 460 }); @@ -166,8 +166,8 @@ test.describe.serial('channel-management', () => { test('should edit notification preferences of targetChannel', async () => { await poHomeChannel.navbar.openChat(targetChannel); - await poHomeChannel.tabs.kebab.click({ force: true }); - await poHomeChannel.tabs.btnNotificationPreferences.click({ force: true }); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemNotificationsPreferences.click(); await poHomeChannel.tabs.notificationPreferences.updateAllNotificationPreferences(); await poHomeChannel.tabs.notificationPreferences.btnSave.click(); @@ -256,8 +256,8 @@ test.describe.serial('channel-management', () => { await poHomeChannel.tabs.members.showAllUsers(); await poHomeChannel.tabs.members.ignoreUser('user1'); - await poHomeChannel.tabs.members.openMoreActions(); - await expect(poHomeChannel.tabs.members.getMenuItemAction('Unignore')).toBeVisible(); + await poHomeChannel.tabs.members.userInfo.openMoreActions(); + await expect(poHomeChannel.tabs.members.userInfo.menu.getMenuItem('Unignore')).toBeVisible(); await page.keyboard.press('Escape'); const user1Channel = new HomeChannel(user1Page); @@ -296,8 +296,8 @@ test.describe.serial('channel-management', () => { await poHomeChannel.tabs.members.showAllUsers(); await poHomeChannel.tabs.members.unignoreUser('user1'); - await poHomeChannel.tabs.members.openMoreActions(); - await expect(poHomeChannel.tabs.members.getMenuItemAction('Ignore')).toBeVisible(); + await poHomeChannel.tabs.members.userInfo.openMoreActions(); + await expect(poHomeChannel.tabs.members.userInfo.menu.getMenuItem('Ignore')).toBeVisible(); await page.keyboard.press('Escape'); await user1Channel.content.sendMessage('message after being unignored'); diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts index 489a46d3b2951..84bd4c5959054 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts @@ -51,10 +51,8 @@ test.describe('E2EE Encrypted Channels', () => { await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); await toastMessages.dismissToast(); - await poHomeChannel.tabs.kebab.click({ force: true }); - - await expect(poHomeChannel.tabs.btnDisableE2E).toBeVisible(); - await poHomeChannel.tabs.btnDisableE2E.click({ force: true }); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemDisableE2EEncryption.click(); await expect(page.getByRole('dialog', { name: 'Disable encryption' })).toBeVisible(); await page.getByRole('button', { name: 'Disable encryption' }).click(); await poHomeChannel.toastMessage.dismissToast(); @@ -65,9 +63,9 @@ test.describe('E2EE Encrypted Channels', () => { await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world not encrypted'); await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).not.toBeVisible(); - await poHomeChannel.tabs.kebab.click({ force: true }); - await expect(poHomeChannel.tabs.btnEnableE2E).toBeVisible(); - await poHomeChannel.tabs.btnEnableE2E.click({ force: true }); + await poHomeChannel.roomToolbar.openMoreOptions(); + await expect(poHomeChannel.roomToolbar.menuItemEnableE2EEncryption).toBeVisible(); + await poHomeChannel.roomToolbar.menuItemEnableE2EEncryption.click(); await expect(page.getByRole('dialog', { name: 'Enable encryption' })).toBeVisible(); await page.getByRole('button', { name: 'Enable encryption' }).click(); await poHomeChannel.toastMessage.dismissToast(); @@ -142,12 +140,12 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.toastMessage.waitForDisplay(); await poHomeChannel.toastMessage.dismissToast(); - await poHomeChannel.tabs.kebab.click(); + await poHomeChannel.roomToolbar.openMoreOptions(); // TODO(@jessicaschelly/@dougfabris): fix this flaky behavior - if (!(await poHomeChannel.tabs.btnEnableE2E.isVisible())) { - await poHomeChannel.tabs.kebab.click(); + if (!(await poHomeChannel.roomToolbar.menuItemEnableE2EEncryption.isVisible())) { + await poHomeChannel.roomToolbar.openMoreOptions(); } - await poHomeChannel.tabs.btnEnableE2E.click(); + await poHomeChannel.roomToolbar.menuItemEnableE2EEncryption.click(); await expect(page.getByRole('dialog', { name: 'Enable encryption' })).toBeVisible(); await page.getByRole('button', { name: 'Enable encryption' }).click(); await page.waitForTimeout(1000); @@ -243,9 +241,9 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.sendMessage('second unencrypted message'); // Encrypt channel - await poHomeChannel.tabs.kebab.click({ force: true }); - await expect(poHomeChannel.tabs.btnEnableE2E).toBeVisible(); - await poHomeChannel.tabs.btnEnableE2E.click({ force: true }); + await poHomeChannel.roomToolbar.openMoreOptions(); + await expect(poHomeChannel.roomToolbar.menuItemEnableE2EEncryption).toBeVisible(); + await poHomeChannel.roomToolbar.menuItemEnableE2EEncryption.click(); await expect(page.getByRole('dialog', { name: 'Enable encryption' })).toBeVisible(); await page.getByRole('button', { name: 'Enable encryption' }).click(); await page.waitForTimeout(1000); @@ -301,8 +299,8 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.toastMessage.waitForDisplay(); await poHomeChannel.toastMessage.dismissToast(); - await poHomeChannel.tabs.kebab.click(); - await poHomeChannel.tabs.btnPinnedMessagesList.click(); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemPinnedMessages.click(); await expect(page.getByRole('dialog', { name: 'Pinned Messages' })).toBeVisible(); @@ -317,9 +315,8 @@ test.describe('E2EE Encrypted Channels', () => { await expect(page.locator('role=menuitem[name="Copy link"]')).toHaveClass(/disabled/); await poHomeChannel.btnContextualbarClose.click(); - - await poHomeChannel.tabs.kebab.click(); - await poHomeChannel.tabs.btnStarredMessageList.click(); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemStarredMessages.click(); const lastStarredMessage = page .getByRole('dialog', { name: 'Starred Messages' }) diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-pdf-export.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-pdf-export.spec.ts index 8ce3b3685ea66..3574549178db2 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-pdf-export.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-pdf-export.spec.ts @@ -3,7 +3,7 @@ import { faker } from '@faker-js/faker'; import { Users } from '../fixtures/userStates'; import { EncryptedRoomPage } from '../page-objects/encrypted-room'; import { Navbar } from '../page-objects/fragments'; -import { ExportMessagesTab } from '../page-objects/fragments/export-messages-tab'; +import { ExportMessagesFlexTab } from '../page-objects/fragments/flextabs'; import { LoginPage } from '../page-objects/login'; import { preserveSettings } from '../utils/preserveSettings'; import { test, expect } from '../utils/test'; @@ -43,7 +43,7 @@ test.describe('E2EE PDF Export', () => { test('should display only the download file method when exporting messages in an e2ee room', async ({ page }) => { const navbar = new Navbar(page); const encryptedRoomPage = new EncryptedRoomPage(page); - const exportMessagesTab = new ExportMessagesTab(page); + const exportMessagesTab = new ExportMessagesFlexTab(page); const channelName = faker.string.uuid(); @@ -59,7 +59,7 @@ test.describe('E2EE PDF Export', () => { test('should allow exporting messages as PDF in an encrypted room', async ({ page }) => { const navbar = new Navbar(page); const encryptedRoomPage = new EncryptedRoomPage(page); - const exportMessagesTab = new ExportMessagesTab(page); + const exportMessagesTab = new ExportMessagesFlexTab(page); const channelName = faker.string.uuid(); diff --git a/apps/meteor/tests/e2e/export-messages.spec.ts b/apps/meteor/tests/e2e/export-messages.spec.ts index 344dad4e723b5..eb5c5f5fa474b 100644 --- a/apps/meteor/tests/e2e/export-messages.spec.ts +++ b/apps/meteor/tests/e2e/export-messages.spec.ts @@ -2,7 +2,6 @@ import { faker } from '@faker-js/faker'; import { Users } from './fixtures/userStates'; import { HomeChannel } from './page-objects'; -import { ExportMessagesTab } from './page-objects/fragments'; import { createTargetChannel, deleteChannel } from './utils'; import { test, expect } from './utils/test'; @@ -31,85 +30,76 @@ test.describe('export-messages', () => { ]); }); - test('should all export methods be available in targetChannel', async ({ page }) => { - const exportMessagesTab = new ExportMessagesTab(page); - + test('should all export methods be available in targetChannel', async () => { await poHomeChannel.navbar.openChat(targetChannel); - await poHomeChannel.tabs.kebab.click({ force: true }); - await poHomeChannel.tabs.btnExportMessages.click(); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemExportMessages.click(); - await exportMessagesTab.exposeMethods(); - await expect(exportMessagesTab.getMethodOptionByName('Send email')).toBeVisible(); - await expect(exportMessagesTab.getMethodOptionByName('Send file via email')).toBeVisible(); - await expect(exportMessagesTab.getMethodOptionByName('Download file')).toBeVisible(); + await poHomeChannel.tabs.exportMessages.exposeMethods(); + await expect(poHomeChannel.tabs.exportMessages.getMethodOptionByName('Send email')).toBeVisible(); + await expect(poHomeChannel.tabs.exportMessages.getMethodOptionByName('Send file via email')).toBeVisible(); + await expect(poHomeChannel.tabs.exportMessages.getMethodOptionByName('Download file')).toBeVisible(); }); - test('should display export output format correctly depending on the selected method', async ({ page }) => { - const exportMessagesTab = new ExportMessagesTab(page); - + test('should display export output format correctly depending on the selected method', async () => { await poHomeChannel.navbar.openChat(targetChannel); - await poHomeChannel.tabs.kebab.click({ force: true }); - await poHomeChannel.tabs.btnExportMessages.click(); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemExportMessages.click(); // TODO: Fix the base component to have a disabled statement and not only a class attribute // Here we are checking for a button because the internal select element is not accessible // and the higher component that is a button doesn't appear as disabled. - await expect(exportMessagesTab.outputFormat).toContainClass('disabled'); + await expect(poHomeChannel.tabs.exportMessages.outputFormat).toContainClass('disabled'); - await exportMessagesTab.setMethod('Send file via email'); + await poHomeChannel.tabs.exportMessages.setMethod('Send file via email'); - await exportMessagesTab.exposeOutputFormats(); - await expect(exportMessagesTab.getOutputFormatOptionByName('html')).toBeVisible(); - await expect(exportMessagesTab.getOutputFormatOptionByName('json')).toBeVisible(); - await expect(exportMessagesTab.getOutputFormatOptionByName('pdf')).not.toBeVisible(); + await poHomeChannel.tabs.exportMessages.exposeOutputFormats(); + await expect(poHomeChannel.tabs.exportMessages.getOutputFormatOptionByName('html')).toBeVisible(); + await expect(poHomeChannel.tabs.exportMessages.getOutputFormatOptionByName('json')).toBeVisible(); + await expect(poHomeChannel.tabs.exportMessages.getOutputFormatOptionByName('pdf')).not.toBeVisible(); - await exportMessagesTab.setOutputFormat('html'); + await poHomeChannel.tabs.exportMessages.setOutputFormat('html'); - await exportMessagesTab.setMethod('Download file'); + await poHomeChannel.tabs.exportMessages.setMethod('Download file'); - await exportMessagesTab.exposeOutputFormats(); - await expect(exportMessagesTab.getOutputFormatOptionByName('html')).not.toBeVisible(); - await expect(exportMessagesTab.getOutputFormatOptionByName('json')).toBeVisible(); - await expect(exportMessagesTab.getOutputFormatOptionByName('pdf')).toBeVisible(); + await poHomeChannel.tabs.exportMessages.exposeOutputFormats(); + await expect(poHomeChannel.tabs.exportMessages.getOutputFormatOptionByName('html')).not.toBeVisible(); + await expect(poHomeChannel.tabs.exportMessages.getOutputFormatOptionByName('json')).toBeVisible(); + await expect(poHomeChannel.tabs.exportMessages.getOutputFormatOptionByName('pdf')).toBeVisible(); }); - test('when trying to send email without filling to users or to additional emails, should mark both fields as invalid', async ({ - page, - }) => { - const exportMessagesTab = new ExportMessagesTab(page); + test('when trying to send email without filling to users or to additional emails, should mark both fields as invalid', async () => { const testMessage = uniqueMessage(); await poHomeChannel.navbar.openChat(targetChannel); await poHomeChannel.content.sendMessage(testMessage); - await poHomeChannel.tabs.kebab.click({ force: true }); - await poHomeChannel.tabs.btnExportMessages.click(); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemExportMessages.click(); await expect(poHomeChannel.btnContextualbarClose).toBeVisible(); await poHomeChannel.content.getMessageByText(testMessage).click(); - await exportMessagesTab.send(); + await poHomeChannel.tabs.exportMessages.send(); - const usersField = exportMessagesTab.inputUsers; - const additionalEmailsField = exportMessagesTab.inputAdditionalEmails; + const usersField = poHomeChannel.tabs.exportMessages.inputUsers; + const additionalEmailsField = poHomeChannel.tabs.exportMessages.inputAdditionalEmails; await expect(usersField).toHaveAttribute('aria-invalid', 'true'); await expect(additionalEmailsField).toHaveAttribute('aria-invalid', 'true'); - const errorMessages = exportMessagesTab.errorMessage( + const errorMessages = poHomeChannel.tabs.exportMessages.errorMessage( 'You must select one or more users or provide one or more email addresses, separated by commas', ); await expect(errorMessages).toHaveCount(2); }); test('should display an error when trying to send email without selecting any message', async ({ page }) => { - const exportMessagesTab = new ExportMessagesTab(page); - await poHomeChannel.navbar.openChat(targetChannel); - await poHomeChannel.tabs.kebab.click({ force: true }); - await poHomeChannel.tabs.btnExportMessages.click(); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemExportMessages.click(); - await exportMessagesTab.setAdditionalEmail('mail@mail.com'); - await exportMessagesTab.send(); + await poHomeChannel.tabs.exportMessages.setAdditionalEmail('mail@mail.com'); + await poHomeChannel.tabs.exportMessages.send(); await expect( page.locator('[role="alert"]', { @@ -124,8 +114,8 @@ test.describe('export-messages', () => { await poHomeChannel.navbar.openChat(targetChannel); await poHomeChannel.content.sendMessage(message1); - await poHomeChannel.tabs.kebab.click({ force: true }); - await poHomeChannel.tabs.btnExportMessages.click(); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemExportMessages.click(); await poHomeChannel.content.getMessageByText(message1).click(); await poHomeChannel.btnContextualbarClose.click(); @@ -134,8 +124,7 @@ test.describe('export-messages', () => { await expect(poHomeChannel.content.getMessageByText(message2)).toBeVisible(); }); - test('should be able to select a single message to export', async ({ page }) => { - const exportMessagesTab = new ExportMessagesTab(page); + test('should be able to select a single message to export', async () => { const message1 = uniqueMessage(); const message2 = uniqueMessage(); @@ -143,20 +132,20 @@ test.describe('export-messages', () => { await poHomeChannel.content.sendMessage(message1); await poHomeChannel.content.sendMessage(message2); - await poHomeChannel.tabs.kebab.click({ force: true }); - await poHomeChannel.tabs.btnExportMessages.click(); - await exportMessagesTab.waitForDisplay(); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemExportMessages.click(); + await poHomeChannel.tabs.exportMessages.waitForDisplay(); await poHomeChannel.content.getMessageByText(message1).click(); - await expect(exportMessagesTab.getMessageCheckbox(message1)).toBeChecked(); - await expect(exportMessagesTab.getMessageCheckbox(message2)).not.toBeChecked(); - await expect(exportMessagesTab.clearSelectionButton).toBeEnabled(); + await expect(poHomeChannel.tabs.exportMessages.getMessageCheckbox(message1)).toBeChecked(); + await expect(poHomeChannel.tabs.exportMessages.getMessageCheckbox(message2)).not.toBeChecked(); + await expect(poHomeChannel.tabs.exportMessages.clearSelectionButton).toBeEnabled(); - await expect(exportMessagesTab.sendButton).toBeEnabled(); + await expect(poHomeChannel.tabs.exportMessages.sendButton).toBeEnabled(); }); - test('should be able to select a single message to export with hide contextual bar preference enabled', async ({ page, api }) => { + test('should be able to select a single message to export with hide contextual bar preference enabled', async ({ api }) => { await api.post('/users.setPreferences', { userId: 'rocketchat.internal.admin.test', data: { hideFlexTab: true }, @@ -164,21 +153,19 @@ test.describe('export-messages', () => { const message1 = uniqueMessage(); const message2 = uniqueMessage(); - const exportMessagesTab = new ExportMessagesTab(page); - await poHomeChannel.navbar.openChat(targetChannel); await poHomeChannel.content.sendMessage(message1); await poHomeChannel.content.sendMessage(message2); - await poHomeChannel.tabs.kebab.click({ force: true }); - await poHomeChannel.tabs.btnExportMessages.click(); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemExportMessages.click(); - await exportMessagesTab.waitForDisplay(); + await poHomeChannel.tabs.exportMessages.waitForDisplay(); await poHomeChannel.content.getMessageByText(message1).click(); - await expect(exportMessagesTab.getMessageCheckbox(message1)).toBeChecked(); - await expect(exportMessagesTab.clearSelectionButton).toBeEnabled(); + await expect(poHomeChannel.tabs.exportMessages.getMessageCheckbox(message1)).toBeChecked(); + await expect(poHomeChannel.tabs.exportMessages.clearSelectionButton).toBeEnabled(); - await expect(exportMessagesTab.sendButton).toBeEnabled(); + await expect(poHomeChannel.tabs.exportMessages.sendButton).toBeEnabled(); }); }); diff --git a/apps/meteor/tests/e2e/feature-preview.spec.ts b/apps/meteor/tests/e2e/feature-preview.spec.ts index b0481e8cfdd18..4697b83ed4060 100644 --- a/apps/meteor/tests/e2e/feature-preview.spec.ts +++ b/apps/meteor/tests/e2e/feature-preview.spec.ts @@ -1,7 +1,7 @@ import { faker } from '@faker-js/faker'; import { Users } from './fixtures/userStates'; -import { AdminInfo, HomeChannel } from './page-objects'; +import { AdminInfo, HomeChannel, HomeDiscussion, HomeTeam } from './page-objects'; import { CreateNewChannelModal } from './page-objects/fragments/modals'; import { createTargetChannel, @@ -19,6 +19,7 @@ test.use({ storageState: Users.admin.state }); test.describe.serial('feature preview', () => { let poHomeChannel: HomeChannel; + let poHomeTeam: HomeTeam; let targetChannel: string; let targetDiscussion: Record; let sidepanelTeam: string; @@ -55,6 +56,7 @@ test.describe.serial('feature preview', () => { test.beforeEach(async ({ page }) => { poHomeChannel = new HomeChannel(page); + poHomeTeam = new HomeTeam(page); }); test('should show "Navigation" feature section', async ({ page }) => { @@ -105,17 +107,17 @@ test.describe.serial('feature preview', () => { newChannelModal = new CreateNewChannelModal(page); await page.goto(`/group/${sidepanelTeam}`); - await poHomeChannel.content.waitForChannel(); + await poHomeTeam.content.waitForChannel(); - await poHomeChannel.roomToolbar.openTeamChannels(); - await poHomeChannel.tabs.channels.btnCreateNew.click(); + await poHomeTeam.headerToolbar.openTeamChannels(); + await poHomeTeam.tabs.channels.btnCreateNew.click(); await newChannelModal.inputName.fill(targetChannelNameInTeam); await newChannelModal.checkboxPrivate.click(); await newChannelModal.btnCreate.click(); - await expect(poHomeChannel.sidepanel.sidepanelList).toBeVisible(); - await expect(poHomeChannel.sidepanel.getItemByName(targetChannelNameInTeam)).toBeVisible(); + await expect(poHomeTeam.sidepanel.sidepanelList).toBeVisible(); + await expect(poHomeTeam.sidepanel.getItemByName(targetChannelNameInTeam)).toBeVisible(); await deleteChannel(api, targetChannelNameInTeam); }); @@ -144,20 +146,10 @@ test.describe.serial('feature preview', () => { test('should show channel in sidepanel after adding existing one', async ({ page }) => { await page.goto(`/group/${sidepanelTeam}`); - await poHomeChannel.roomToolbar.openTeamChannels(); - await poHomeChannel.tabs.channels.btnAddExisting.click(); - // flaky: workarround for when AutoComplete does not close the list box before trying to click `Add` - await expect(async () => { - await poHomeChannel.tabs.channels.inputChannels.fill(targetChannel); - const option = poHomeChannel.tabs.channels.getListboxOption(targetChannel); - await option.click(); - await expect(option).not.toBeVisible(); - }).toPass(); - - await poHomeChannel.tabs.channels.btnAdd.click(); - await poHomeChannel.content.waitForChannel(); + await poHomeTeam.headerToolbar.openTeamChannels(); + await poHomeTeam.tabs.channels.addExistingChannel(targetChannel); - await expect(poHomeChannel.sidepanel.getItemByName(targetChannel)).toBeVisible(); + await expect(poHomeTeam.sidepanel.getItemByName(targetChannel)).toBeVisible(); }); test('should keep the main room on the top even if child has unread messages', async ({ page, browser }) => { @@ -166,30 +158,22 @@ test.describe.serial('feature preview', () => { await page.goto(`/group/${sidepanelTeam}`); - await poHomeChannel.roomToolbar.openTeamChannels(); - await poHomeChannel.tabs.channels.btnAddExisting.click(); - // flaky: workarround for when AutoComplete does not close the list box before trying to click `Add` - await expect(async () => { - await poHomeChannel.tabs.channels.inputChannels.fill(targetChannel); - const option = poHomeChannel.tabs.channels.getListboxOption(targetChannel); - await option.click(); - await expect(option).not.toBeVisible(); - }).toPass(); - await poHomeChannel.tabs.channels.btnAdd.click(); + await poHomeTeam.headerToolbar.openTeamChannels(); + await poHomeTeam.tabs.channels.addExistingChannel(targetChannel); - const sidepanelTeamItem = poHomeChannel.sidepanel.getTeamItemByName(sidepanelTeam); - const targetChannelItem = poHomeChannel.sidepanel.getTeamItemByName(targetChannel); + const sidepanelTeamItem = poHomeTeam.sidepanel.getTeamItemByName(sidepanelTeam); + const targetChannelItem = poHomeTeam.sidepanel.getTeamItemByName(targetChannel); await targetChannelItem.click(); expect(page.url()).toContain(`/channel/${targetChannel}`); - await poHomeChannel.content.sendMessage('hello channel'); + await poHomeTeam.content.sendMessage('hello channel'); await expect(async () => { await sidepanelTeamItem.focus(); await sidepanelTeamItem.click(); expect(page.url()).toContain(`/group/${sidepanelTeam}`); }).toPass(); - await poHomeChannel.content.sendMessage('hello team'); + await poHomeTeam.content.sendMessage('hello team'); await user1Page.goto(`/channel/${targetChannel}`); await user1Channel.content.waitForChannel(); @@ -197,7 +181,7 @@ test.describe.serial('feature preview', () => { await user1Channel.content.toggleAlsoSendThreadToChannel(false); await user1Channel.content.sendMessageInThread('hello thread'); - const item = poHomeChannel.sidepanel.getTeamItemByName(targetChannel); + const item = poHomeTeam.sidepanel.getTeamItemByName(targetChannel); await expect(item.locator('..')).toHaveAttribute('data-item-index', '1'); await user1Page.close(); @@ -254,6 +238,7 @@ test.describe.serial('feature preview', () => { }); test('should show discussion in discussions and all sidepanel filter, should remove after deleting discussion', async ({ page }) => { + const poHomeDiscussion = new HomeDiscussion(page); await page.goto(`/group/${sidepanelTeam}`); await poHomeChannel.content.waitForChannel(); @@ -265,22 +250,20 @@ test.describe.serial('feature preview', () => { await poHomeChannel.content.btnCreateDiscussionModal.click(); await expect(page.getByRole('heading', { name: discussionName })).toBeVisible(); - await poHomeChannel.sidebar.discussionsTeamCollabFilter.click(); - await expect(poHomeChannel.sidepanel.getItemByName(discussionName)).toBeVisible(); + await poHomeDiscussion.sidebar.discussionsTeamCollabFilter.click(); + await expect(poHomeDiscussion.sidepanel.getItemByName(discussionName)).toBeVisible(); - await poHomeChannel.sidebar.allTeamCollabFilter.click(); - await expect(poHomeChannel.sidepanel.getItemByName(discussionName)).toBeVisible(); + await poHomeDiscussion.sidebar.allTeamCollabFilter.click(); + await expect(poHomeDiscussion.sidepanel.getItemByName(discussionName)).toBeVisible(); - await poHomeChannel.roomToolbar.openRoomInfo(); - await poHomeChannel.tabs.room.btnMore.click(); - await poHomeChannel.tabs.room.getMoreOption('Delete').click(); - await poHomeChannel.tabs.room.confirmDeleteDiscussion(); + await poHomeDiscussion.roomToolbar.openRoomInfo(); + await poHomeDiscussion.tabs.room.deleteRoom(); - await poHomeChannel.sidebar.discussionsTeamCollabFilter.click(); - await expect(poHomeChannel.sidepanel.getItemByName(discussionName)).not.toBeVisible(); + await poHomeDiscussion.sidebar.discussionsTeamCollabFilter.click(); + await expect(poHomeDiscussion.sidepanel.getItemByName(discussionName)).not.toBeVisible(); - await poHomeChannel.sidebar.allTeamCollabFilter.click(); - await expect(poHomeChannel.sidepanel.getItemByName(discussionName)).not.toBeVisible(); + await poHomeDiscussion.sidebar.allTeamCollabFilter.click(); + await expect(poHomeDiscussion.sidepanel.getItemByName(discussionName)).not.toBeVisible(); }); test('should persist sidepanel state after page reload', async ({ page }) => { diff --git a/apps/meteor/tests/e2e/message-actions.spec.ts b/apps/meteor/tests/e2e/message-actions.spec.ts index 3a1e71733ca02..e80adaff127c9 100644 --- a/apps/meteor/tests/e2e/message-actions.spec.ts +++ b/apps/meteor/tests/e2e/message-actions.spec.ts @@ -1,7 +1,7 @@ import { ADMIN_CREDENTIALS } from './config/constants'; import { Users } from './fixtures/userStates'; -import { HomeChannel, HomeDiscussion } from './page-objects'; -import { HomeFlextab } from './page-objects/fragments'; +import { HomeChannel } from './page-objects'; +import { CreateNewDiscussionModal } from './page-objects/fragments'; import { createTargetChannel, createTargetTeam } from './utils'; import { setUserPreferences } from './utils/setUserPreferences'; import { expect, test } from './utils/test'; @@ -9,7 +9,6 @@ import { expect, test } from './utils/test'; test.use({ storageState: Users.admin.state }); test.describe.serial('message-actions', () => { let poHomeChannel: HomeChannel; - let poHomeDiscussion: HomeDiscussion; let targetChannel: string; let forwardChannel: string; let forwardTeam: string; @@ -20,7 +19,6 @@ test.describe.serial('message-actions', () => { }); test.beforeEach(async ({ page }) => { poHomeChannel = new HomeChannel(page); - poHomeDiscussion = new HomeDiscussion(page); await page.goto('/home'); await poHomeChannel.navbar.openChat(targetChannel); }); @@ -129,10 +127,11 @@ test.describe.serial('message-actions', () => { await poHomeChannel.content.sendMessage(message); await poHomeChannel.content.openLastMessageMenu(); await page.locator('role=menuitem[name="Start a Discussion"]').click(); - const createButton = poHomeDiscussion.btnCreate; + const createDiscussionModal = new CreateNewDiscussionModal(page); + const createButton = createDiscussionModal.btnCreate; // Name should be prefilled thus making the create button enabled await expect(createButton).not.toBeDisabled(); - await poHomeDiscussion.inputName.fill(discussionName); + await createDiscussionModal.inputName.fill(discussionName); await createButton.click(); await expect(page.locator('header h1')).toHaveText(discussionName); await poHomeChannel.navbar.openChat(targetChannel); @@ -141,13 +140,12 @@ test.describe.serial('message-actions', () => { }); test('expect star the message', async ({ page }) => { - const flextab = new HomeFlextab(page); await poHomeChannel.content.sendMessage('Message to star'); await poHomeChannel.content.openLastMessageMenu(); await page.locator('role=menuitem[name="Star"]').click(); await poHomeChannel.toastMessage.dismissToast(); - await flextab.kebab.click(); - await page.locator('[data-key="starred-messages"]').click(); + await poHomeChannel.roomToolbar.openMoreOptions(); + await poHomeChannel.roomToolbar.menuItemStarredMessages.click(); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('Message to star'); }); diff --git a/apps/meteor/tests/e2e/page-objects/admin-device-management.ts b/apps/meteor/tests/e2e/page-objects/admin-device-management.ts index 60976c8e2ab89..42c927322db53 100644 --- a/apps/meteor/tests/e2e/page-objects/admin-device-management.ts +++ b/apps/meteor/tests/e2e/page-objects/admin-device-management.ts @@ -2,7 +2,7 @@ import type { Locator, Page } from '@playwright/test'; import { Admin } from './admin'; import { MenuOptions, DevicesTable } from './fragments'; -import { DeviceInfoFlexTab } from './fragments/device-info-flextab'; +import { DeviceInfoFlexTab } from './fragments/flextabs'; import { ConfirmLogoutModal } from './fragments/modals'; export class AdminDeviceManagement extends Admin { diff --git a/apps/meteor/tests/e2e/page-objects/admin-emojis.ts b/apps/meteor/tests/e2e/page-objects/admin-emojis.ts index 71717404e50d0..432cc619766db 100644 --- a/apps/meteor/tests/e2e/page-objects/admin-emojis.ts +++ b/apps/meteor/tests/e2e/page-objects/admin-emojis.ts @@ -1,7 +1,7 @@ import type { Locator, Page } from '@playwright/test'; import { Admin } from './admin'; -import { AddEmojiFlexTab, EditEmojiFlexTab } from './fragments/admin-flextab-emoji'; +import { AddEmojiFlexTab, EditEmojiFlexTab } from './fragments/flextabs'; export class AdminEmoji extends Admin { readonly addEmojiFlexTab: AddEmojiFlexTab; diff --git a/apps/meteor/tests/e2e/page-objects/admin-rooms.ts b/apps/meteor/tests/e2e/page-objects/admin-rooms.ts index eda0a45707606..40104eeeddb7b 100644 --- a/apps/meteor/tests/e2e/page-objects/admin-rooms.ts +++ b/apps/meteor/tests/e2e/page-objects/admin-rooms.ts @@ -1,14 +1,14 @@ import type { Locator, Page } from '@playwright/test'; import { Admin } from './admin'; -import { EditRoomFlexTab } from './fragments/edit-room-flextab'; +import { EditAdminRoomFlexTab } from './fragments/flextabs'; export class AdminRooms extends Admin { - readonly editRoom: EditRoomFlexTab; + readonly editRoom: EditAdminRoomFlexTab; constructor(page: Page) { super(page); - this.editRoom = new EditRoomFlexTab(page.getByRole('dialog', { name: 'Room Information' })); + this.editRoom = new EditAdminRoomFlexTab(page.getByRole('dialog', { name: 'Room Information' })); } get adminPageContent(): Locator { diff --git a/apps/meteor/tests/e2e/page-objects/encrypted-room.ts b/apps/meteor/tests/e2e/page-objects/encrypted-room.ts index e54f92906043c..cd3be947f9f16 100644 --- a/apps/meteor/tests/e2e/page-objects/encrypted-room.ts +++ b/apps/meteor/tests/e2e/page-objects/encrypted-room.ts @@ -1,8 +1,17 @@ -import { HomeContent, HomeFlextab } from './fragments'; +import type { Page } from '@playwright/test'; + +import { EncryptedRoomToolbar, HomeContent } from './fragments'; import { Message } from './fragments/message'; import { DisableRoomEncryptionModal, EnableRoomEncryptionModal } from './fragments/modals'; export class EncryptedRoomPage extends HomeContent { + readonly toolbar: EncryptedRoomToolbar; + + constructor(page: Page) { + super(page); + this.toolbar = new EncryptedRoomToolbar(page); + } + get encryptedTitle() { return this.page.getByRole('button', { name: '- encrypted' }); } @@ -20,28 +29,23 @@ export class EncryptedRoomPage extends HomeContent { } async enableEncryption() { - const tabs = new HomeFlextab(this.page); - const enableRoomEncryptionModal = new EnableRoomEncryptionModal(this.page); - await tabs.kebab.click(); - await tabs.btnEnableE2E.click(); + await this.toolbar.openMoreOptions(); + await this.toolbar.menuItemEnableE2EEncryption.click(); await enableRoomEncryptionModal.enable(); } async disableEncryption() { - const tabs = new HomeFlextab(this.page); const disableRoomEncryptionModal = new DisableRoomEncryptionModal(this.page); - await tabs.kebab.click(); - await tabs.btnDisableE2E.click(); + await this.toolbar.openMoreOptions(); + await this.toolbar.menuItemDisableE2EEncryption.click(); await disableRoomEncryptionModal.disable(); } async showExportMessagesTab() { - const tabs = new HomeFlextab(this.page); - - await tabs.kebab.click(); - await tabs.btnExportMessages.click(); + await this.toolbar.openMoreOptions(); + await this.toolbar.menuItemExportMessages.click(); } } diff --git a/apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts deleted file mode 100644 index 8fa085c271e89..0000000000000 --- a/apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts +++ /dev/null @@ -1,91 +0,0 @@ -import type { Locator, Page } from '@playwright/test'; - -import { FlexTab } from './flextab'; -import { Listbox } from './listbox'; - -export class EditRoomFlexTab extends FlexTab { - constructor(locator: Locator) { - super(locator); - } - - get roomNameInput(): Locator { - return this.root.locator('input[name="roomName"]'); - } - - get privateLabel(): Locator { - return this.root.locator(`label >> text=Private`); - } - - get privateInput(): Locator { - return this.root.locator('input[name="roomType"]'); - } - - get roomOwnerInput(): Locator { - return this.root.locator('input[name="roomOwner"]'); - } - - get archivedLabel(): Locator { - return this.root.locator('label >> text=Archived'); - } - - get archivedInput(): Locator { - return this.root.locator('input[name="archived"]'); - } - - get favoriteLabel(): Locator { - return this.root.locator('label >> text=Favorite'); - } - - get favoriteInput(): Locator { - return this.root.locator('input[name="favorite"]'); - } - - get defaultLabel(): Locator { - return this.root.locator('label >> text=Default'); - } - - get defaultInput(): Locator { - return this.root.locator('input[name="isDefault"]'); - } -} - -export class OmnichannelEditRoomFlexTab extends EditRoomFlexTab { - private readonly tagsListbox: Listbox; - - private readonly slaListbox: Listbox; - - constructor(page: Page) { - super(page.getByRole('dialog', { name: 'Edit Room' })); - this.tagsListbox = new Listbox(page); - this.slaListbox = new Listbox(page, 'SLA Policy'); - } - - get inputTopic(): Locator { - return this.root.getByRole('textbox', { name: 'Topic', exact: true }); - } - - get inputSLAPolicy(): Locator { - return this.root.getByRole('button', { name: 'SLA Policy', exact: true }); - } - - optionTag(name: string): Locator { - return this.tagsListbox.getOption(name); - } - - async selectTag(name: string) { - await this.tagsListbox.selectOption(name); - } - - async selectSLA(name: string) { - await this.inputSLAPolicy.click(); - await this.slaListbox.selectOption(name, true); - } - - get inputTags(): Locator { - return this.root.getByRole('textbox', { name: 'Select an option' }); - } - - getRoomCustomField(label: string): Locator { - return this.root.getByRole('group', { name: 'Custom Fields' }).getByLabel(label); - } -} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/flextabs/admin-edit-room-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/admin-edit-room-flextab.ts new file mode 100644 index 0000000000000..fe0d5206af00c --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/admin-edit-room-flextab.ts @@ -0,0 +1,49 @@ +import type { Locator } from '@playwright/test'; + +import { FlexTab } from './flextab'; + +export class EditAdminRoomFlexTab extends FlexTab { + constructor(locator: Locator) { + super(locator); + } + + get roomNameInput(): Locator { + return this.root.locator('input[name="roomName"]'); + } + + get privateLabel(): Locator { + return this.root.locator(`label >> text=Private`); + } + + get privateInput(): Locator { + return this.root.locator('input[name="roomType"]'); + } + + get roomOwnerInput(): Locator { + return this.root.locator('input[name="roomOwner"]'); + } + + get archivedLabel(): Locator { + return this.root.locator('label >> text=Archived'); + } + + get archivedInput(): Locator { + return this.root.locator('input[name="archived"]'); + } + + get favoriteLabel(): Locator { + return this.root.locator('label >> text=Favorite'); + } + + get favoriteInput(): Locator { + return this.root.locator('input[name="favorite"]'); + } + + get defaultLabel(): Locator { + return this.root.locator('label >> text=Default'); + } + + get defaultInput(): Locator { + return this.root.locator('input[name="isDefault"]'); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/admin-flextab-emoji.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/admin-flextab-emoji.ts similarity index 100% rename from apps/meteor/tests/e2e/page-objects/fragments/admin-flextab-emoji.ts rename to apps/meteor/tests/e2e/page-objects/fragments/flextabs/admin-flextab-emoji.ts diff --git a/apps/meteor/tests/e2e/page-objects/fragments/flextabs/channels-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/channels-flextab.ts new file mode 100644 index 0000000000000..d40cecdd489ea --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/channels-flextab.ts @@ -0,0 +1,83 @@ +import type { Locator, Page } from '@playwright/test'; + +import { FlexTab } from './flextab'; +import { Listbox } from '../listbox'; +import { ConfirmDeleteRoomModal, ConfirmRemoveModal } from '../modals'; +import { Modal } from '../modals/modal'; + +class AddExistingChannelModal extends Modal { + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Add Existing Channels' })); + } + + get inputChannels(): Locator { + return this.root.getByRole('textbox'); + } + + get btnAdd(): Locator { + return this.root.getByRole('button', { name: 'Add' }); + } + + async confirmAdd() { + await this.btnAdd.click(); + await this.waitForDismissal(); + } +} + +export class ChannelsFlexTab extends FlexTab { + readonly confirmRemoveModal: ConfirmRemoveModal; + + readonly confirmDeleteModal: ConfirmDeleteRoomModal; + + readonly addExistingChannelModal: AddExistingChannelModal; + + readonly listbox: Listbox; + + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Team Channels' })); + this.confirmRemoveModal = new ConfirmRemoveModal(page.getByRole('dialog', { name: 'Are you sure?' })); + this.confirmDeleteModal = new ConfirmDeleteRoomModal(page); + this.addExistingChannelModal = new AddExistingChannelModal(page); + this.listbox = new Listbox(page); + } + + get btnAddExisting(): Locator { + return this.root.getByRole('button', { name: 'Add Existing' }); + } + + get btnCreateNew(): Locator { + return this.root.getByRole('button', { name: 'Create new' }); + } + + get channelsList(): Locator { + return this.root.getByRole('list'); + } + + getListboxOption(name: string): Locator { + return this.listbox.getOption(name); + } + + channelOption(name: string) { + return this.root.locator('li', { hasText: name }); + } + + async openChannelOptionMoreActions(name: string) { + await this.channelOption(name).hover(); + await this.channelOption(name).getByRole('button', { name: 'More' }).click(); + } + + async confirmRemoveChannel() { + return this.confirmRemoveModal.confirmRemove(); + } + + async confirmDeleteRoom() { + return this.confirmDeleteModal.confirmDelete(); + } + + async addExistingChannel(name: string) { + await this.btnAddExisting.click(); + await this.addExistingChannelModal.inputChannels.fill(name); + await this.listbox.selectOption(name); + await this.addExistingChannelModal.confirmAdd(); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/device-info-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/device-info-flextab.ts similarity index 100% rename from apps/meteor/tests/e2e/page-objects/fragments/device-info-flextab.ts rename to apps/meteor/tests/e2e/page-objects/fragments/flextabs/device-info-flextab.ts diff --git a/apps/meteor/tests/e2e/page-objects/fragments/edit-contact-flaxtab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/edit-contact-flextab.ts similarity index 100% rename from apps/meteor/tests/e2e/page-objects/fragments/edit-contact-flaxtab.ts rename to apps/meteor/tests/e2e/page-objects/fragments/flextabs/edit-contact-flextab.ts diff --git a/apps/meteor/tests/e2e/page-objects/fragments/flextabs/edit-room-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/edit-room-flextab.ts new file mode 100644 index 0000000000000..5dd6fe70fdea3 --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/edit-room-flextab.ts @@ -0,0 +1,114 @@ +import type { Locator, Page } from '@playwright/test'; + +import { FlexTab } from './flextab'; +import { Listbox } from '../listbox'; + +export class EditRoomFlexTab extends FlexTab { + constructor(locator: Locator) { + super(locator); + } + + get inputTopic(): Locator { + return this.root.getByRole('textbox', { name: 'Topic' }); + } + + get inputAnnouncement(): Locator { + return this.root.getByRole('textbox', { name: 'Announcement' }); + } + + get inputDescription(): Locator { + return this.root.getByRole('textbox', { name: 'Description' }); + } + + get checkboxReadOnly(): Locator { + return this.root.locator('label', { hasText: 'Read-only' }); + } + + get calloutRetentionPolicy(): Locator { + return this.root.getByRole('alert', { name: 'Retention policy warning callout' }); + } + + get advancedSettingsAccordion(): Locator { + return this.root.getByRole('button', { name: 'Advanced settings' }); + } + + get pruneAccordion(): Locator { + return this.root.getByRole('button', { name: 'Prune', exact: true }); + } + + getMaxAgeLabel(maxAge = '30') { + return this.root.getByText(`Maximum message age in days (default: ${maxAge})`); + } + + get inputRetentionMaxAge(): Locator { + return this.root.locator('input[name="retentionMaxAge"]'); + } + + get checkboxPruneMessages(): Locator { + return this.root.locator('label', { hasText: 'Automatically prune old messages' }); + } + + get checkboxOverrideGlobalRetention(): Locator { + return this.root.locator('label', { hasText: 'Override global retention policy' }); + } + + get checkboxIgnoreThreads(): Locator { + return this.root.locator('label', { hasText: 'Do not prune Threads' }); + } + + get checkboxChannels(): Locator { + return this.root.locator('label', { hasText: 'Channels' }); + } + + get checkboxDiscussions(): Locator { + return this.root.locator('label', { hasText: 'Discussions' }); + } + + async toggleSidepanelItems() { + await this.checkboxChannels.click(); + await this.checkboxDiscussions.click(); + } +} + +export class EditTeamFlexTab extends EditRoomFlexTab { + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Edit team' })); + } +} + +export class OmnichannelEditRoomFlexTab extends EditRoomFlexTab { + private readonly tagsListbox: Listbox; + + private readonly slaListbox: Listbox; + + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Edit Room' })); + this.tagsListbox = new Listbox(page); + this.slaListbox = new Listbox(page, 'SLA Policy'); + } + + get inputSLAPolicy(): Locator { + return this.root.getByRole('button', { name: 'SLA Policy', exact: true }); + } + + optionTag(name: string): Locator { + return this.tagsListbox.getOption(name); + } + + async selectTag(name: string) { + await this.tagsListbox.selectOption(name); + } + + async selectSLA(name: string) { + await this.inputSLAPolicy.click(); + await this.slaListbox.selectOption(name, true); + } + + get inputTags(): Locator { + return this.root.getByRole('textbox', { name: 'Select an option' }); + } + + getRoomCustomField(label: string): Locator { + return this.root.getByRole('group', { name: 'Custom Fields' }).getByLabel(label); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/edit-user-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/edit-user-flextab.ts similarity index 100% rename from apps/meteor/tests/e2e/page-objects/fragments/edit-user-flextab.ts rename to apps/meteor/tests/e2e/page-objects/fragments/flextabs/edit-user-flextab.ts diff --git a/apps/meteor/tests/e2e/page-objects/fragments/export-messages-tab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/export-messages-flextab.ts similarity index 97% rename from apps/meteor/tests/e2e/page-objects/fragments/export-messages-tab.ts rename to apps/meteor/tests/e2e/page-objects/fragments/flextabs/export-messages-flextab.ts index edceaebf6878a..0915b86a007b7 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/export-messages-tab.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/export-messages-flextab.ts @@ -2,7 +2,7 @@ import type { Locator, Page } from '@playwright/test'; import { FlexTab } from './flextab'; -export class ExportMessagesTab extends FlexTab { +export class ExportMessagesFlexTab extends FlexTab { constructor(page: Page) { super(page.getByRole('dialog', { name: 'Export Messages' })); } diff --git a/apps/meteor/tests/e2e/page-objects/fragments/files-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/files-flextab.ts similarity index 90% rename from apps/meteor/tests/e2e/page-objects/fragments/files-flextab.ts rename to apps/meteor/tests/e2e/page-objects/fragments/flextabs/files-flextab.ts index 5ee044d6d5e5e..95f2d79be25ff 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/files-flextab.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/files-flextab.ts @@ -1,8 +1,8 @@ import type { Page } from '@playwright/test'; import { FlexTab } from './flextab'; -import { MenuMore } from './menu'; -import { ConfirmDeleteModal } from './modals'; +import { MenuMore } from '../menu'; +import { ConfirmDeleteModal } from '../modals'; export class FilesFlexTab extends FlexTab { readonly menu: MenuMore; diff --git a/apps/meteor/tests/e2e/page-objects/fragments/flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/flextab.ts similarity index 82% rename from apps/meteor/tests/e2e/page-objects/fragments/flextab.ts rename to apps/meteor/tests/e2e/page-objects/fragments/flextabs/flextab.ts index e406a0decb43a..3c5257aef4ceb 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/flextab.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/flextab.ts @@ -1,8 +1,11 @@ import type { Locator } from '@playwright/test'; -import { expect } from '../../utils/test'; +import { expect } from '../../../utils/test'; export abstract class FlexTab { + /** + * @param root should be protected, but for now there are a lot of tests relying on accessing it directly, * so we need to keep it public until we can refactor those tests + */ constructor(public root: Locator) {} waitForDisplay() { diff --git a/apps/meteor/tests/e2e/page-objects/fragments/flextabs/index.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/index.ts new file mode 100644 index 0000000000000..7faeca128d584 --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/index.ts @@ -0,0 +1,16 @@ +export * from './admin-flextab-emoji'; +export * from './admin-edit-room-flextab'; +export * from './channels-flextab'; +export * from './device-info-flextab'; +export * from './edit-room-flextab'; +export * from './edit-user-flextab'; +export * from './edit-contact-flextab'; +export * from './export-messages-flextab'; +export * from './files-flextab'; +export * from './members-flextab'; +export * from './notification-preferences-flextab'; +export * from './prune-messages-flextab'; +export * from './room-info-flextab'; +export * from './threads-flextab'; +export * from './search-messages-flextab'; +export * from './user-info-flextab'; diff --git a/apps/meteor/tests/e2e/page-objects/fragments/flextabs/members-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/members-flextab.ts new file mode 100644 index 0000000000000..720d0090059a9 --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/members-flextab.ts @@ -0,0 +1,145 @@ +import type { Page } from '@playwright/test'; + +import { FlexTab } from './flextab'; +import { Listbox } from '../listbox'; +import { MenuMore } from '../menu'; +import { ConfirmRemoveModal } from '../modals'; +import { UserInfoFlexTab } from './user-info-flextab'; +import { Modal } from '../modals/modal'; + +export class ConfirmMuteModal extends Modal { + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Are you sure' })); + } + + private get btnMute() { + return this.root.getByRole('button', { name: 'Yes, mute user!' }); + } + + async confirmMute() { + await this.btnMute.click(); + await this.waitForDismissal(); + } +} + +class AddUsersFlexTab extends FlexTab { + readonly listbox: Listbox; + + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Add users' })); + this.listbox = new Listbox(page); + } + + private btnAddUsers() { + return this.root.getByRole('button', { name: 'Add users' }); + } + + async addUser(username: string) { + await this.root.getByRole('textbox', { name: 'Choose users' }).pressSequentially(username); + await this.listbox.selectOption(username); + await this.btnAddUsers().click(); + await this.waitForDismissal(); + } +} + +export class MembersFlexTab extends FlexTab { + readonly listbox: Listbox; + + readonly removeModal: ConfirmRemoveModal; + + readonly menu: MenuMore; + + readonly confirmMuteModal: ConfirmMuteModal; + + readonly addUsersFlexTab: AddUsersFlexTab; + + readonly userInfo: UserInfoFlexTab; + + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Members' })); + this.removeModal = new ConfirmRemoveModal(page.getByRole('dialog', { name: 'Confirmation', exact: true })); + this.listbox = new Listbox(page); + this.menu = new MenuMore(page); + this.confirmMuteModal = new ConfirmMuteModal(page); + this.addUsersFlexTab = new AddUsersFlexTab(page); + this.userInfo = new UserInfoFlexTab(page); + } + + memberOption(username: string) { + return this.root.locator('li', { hasText: username }); + } + + getMenuItemAction(action: string) { + return this.menu.getMenuItem(action); + } + + async openMemberInfo(username: string) { + await this.memberOption(username).click(); + } + + async openMoreActions() { + await this.root.getByRole('button', { name: 'More' }).click(); + } + + async openMemberOptionMoreActions(username: string) { + await this.memberOption(username).hover(); + await this.memberOption(username).getByRole('button', { name: 'More' }).click(); + } + + async addUser(username: string) { + await this.root.getByRole('button', { name: 'Add' }).click(); + await this.addUsersFlexTab.addUser(username); + } + + private get btnInviteLink() { + return this.root.getByRole('button', { name: 'Invite Link' }); + } + + async inviteUser() { + await this.btnInviteLink.click(); + } + + async muteUser(username: string) { + await this.openMemberOptionMoreActions(username); + await this.menu.selectMenuItem('Mute user'); + await this.confirmMuteModal.confirmMute(); + } + + async unmuteUser(username: string) { + await this.openMemberOptionMoreActions(username); + await this.menu.selectMenuItem('Unmute user'); + } + + async setUserAsModerator(username: string) { + await this.openMemberOptionMoreActions(username); + await this.menu.selectMenuItem('Set as moderator'); + } + + async setUserAsOwner(username: string) { + await this.openMemberOptionMoreActions(username); + await this.menu.selectMenuItem('Set as owner'); + } + + async showAllUsers() { + await this.root.getByRole('button', { name: 'Online' }).click(); + await this.listbox.selectOption('All'); + } + + private async ignoreUserAction(action: string, username: string) { + await this.openMemberInfo(username); + await this.userInfo.openMoreActions(); + await this.userInfo.menu.selectMenuItem(action); + } + + async ignoreUser(username: string) { + await this.ignoreUserAction('Ignore', username); + } + + async unignoreUser(username: string) { + await this.ignoreUserAction('Unignore', username); + } + + async confirmRemoveUser() { + return this.removeModal.confirmRemove(); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-notificationPreferences.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/notification-preferences-flextab.ts similarity index 53% rename from apps/meteor/tests/e2e/page-objects/fragments/home-flextab-notificationPreferences.ts rename to apps/meteor/tests/e2e/page-objects/fragments/flextabs/notification-preferences-flextab.ts index 9a38571b32898..30d9f6516b18f 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-notificationPreferences.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/notification-preferences-flextab.ts @@ -1,34 +1,30 @@ import type { Locator, Page } from '@playwright/test'; -export class HomeFlextabNotificationPreferences { - private readonly page: Page; +import { FlexTab } from './flextab'; +import { Listbox } from '../listbox'; - constructor(page: Page) { - this.page = page; - } +export class NotificationPreferencesFlexTab extends FlexTab { + readonly listbox: Listbox; - get btnSave(): Locator { - return this.page.locator('role=button[name="Save"]'); - } - - get dialogNotificationPreferences(): Locator { - return this.page.getByRole('dialog', { name: 'Notifications Preferences' }); + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Notifications Preferences' })); + this.listbox = new Listbox(page); } getPreferenceByDevice(device: string): Locator { - return this.page.locator(`//div[@id="${device}Alert"]`); + return this.root.locator(`//div[@id="${device}Alert"]`); } async selectDropdownById(text: string): Promise { - await this.dialogNotificationPreferences.locator(`//div[@id="${text}"]`).click(); + await this.root.locator(`//div[@id="${text}"]`).click(); } async selectOptionByLabel(text: string): Promise { - await this.page.getByRole('listbox').getByRole('option', { name: text }).click(); + await this.listbox.selectOption(text); } async selectDevice(text: string): Promise { - await this.dialogNotificationPreferences.getByRole('button', { name: text }).click(); + await this.root.getByRole('button', { name: text }).click(); } async updateDevicePreference(device: string): Promise { diff --git a/apps/meteor/tests/e2e/page-objects/fragments/flextabs/prune-messages-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/prune-messages-flextab.ts new file mode 100644 index 0000000000000..33e1d23a667ab --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/prune-messages-flextab.ts @@ -0,0 +1,37 @@ +import type { Locator, Page } from '@playwright/test'; + +import { FlexTab } from './flextab'; +import { Modal } from '../modals/modal'; + +class ConfirmPruneMessageModal extends Modal { + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Are you sure?' })); + } + + async pruneConfirm(): Promise { + await this.root.getByRole('button', { name: 'Yes, prune them!' }).click(); + await this.waitForDismissal(); + } +} + +export class PruneMessagesFlexTab extends FlexTab { + readonly confirmPruneModal: ConfirmPruneMessageModal; + + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Prune Messages' })); + this.confirmPruneModal = new ConfirmPruneMessageModal(page); + } + + get labelDoNotPrunePinned(): Locator { + return this.root.locator('label', { hasText: 'Do not prune pinned messages' }); + } + + get labelFilesOnly(): Locator { + return this.root.locator('label', { hasText: 'Only remove the attached files, keep messages' }); + } + + async prune(): Promise { + await this.root.getByRole('button', { name: 'Prune' }).click(); + await this.confirmPruneModal.pruneConfirm(); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/flextabs/room-info-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/room-info-flextab.ts new file mode 100644 index 0000000000000..9148bff93a95d --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/room-info-flextab.ts @@ -0,0 +1,124 @@ +import type { Locator, Page } from '@playwright/test'; + +import { FlexTab } from './flextab'; +import { MenuMore } from '../menu'; +import { ConfirmDeleteTeamModal, ConfirmDeleteRoomModal } from '../modals'; +import { Modal } from '../modals/modal'; + +class ConfirmLeaveRoomModal extends Modal { + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Confirmation', exact: true })); + } + + private get btnLeave() { + return this.root.getByRole('button', { name: 'Leave', exact: true }); + } + + async confirmLeave() { + await this.btnLeave.click(); + await this.waitForDismissal(); + } +} + +export class RoomInfoFlexTab extends FlexTab { + readonly menu: MenuMore; + + readonly confirmLeaveModal: ConfirmLeaveRoomModal; + + readonly confirmDeleteModal: ConfirmDeleteRoomModal; + + constructor(root: Locator) { + super(root); + this.menu = new MenuMore(root.page()); + this.confirmLeaveModal = new ConfirmLeaveRoomModal(root.page()); + this.confirmDeleteModal = new ConfirmDeleteRoomModal(root.page()); + } + + get btnEdit(): Locator { + return this.root.getByRole('button', { name: 'Edit' }); + } + + get btnLeave(): Locator { + return this.root.getByRole('button', { name: 'Leave' }); + } + + get btnMore(): Locator { + return this.root.getByRole('button', { name: 'More' }); + } + + get optionDelete(): Locator { + return this.menu.getMenuItem('Delete'); + } + + async leaveRoom() { + await this.btnLeave.click(); + await this.confirmLeaveModal.confirmLeave(); + } + + async deleteRoom() { + await this.btnMore.click(); + await this.menu.selectMenuItem('Delete'); + await this.confirmDeleteModal.confirmDelete(); + } +} + +class ConfirmConvertIntoChannelModal extends Modal { + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Confirmation', exact: true })); + } + + private get btnConvert() { + return this.root.getByRole('button', { name: 'Convert', exact: true }); + } + + async confirmConvert() { + await this.btnConvert.click(); + await this.waitForDismissal(); + } +} + +export class TeamInfoFlexTab extends RoomInfoFlexTab { + readonly confirmDeleteTeamModal: ConfirmDeleteTeamModal; + + readonly confirmConvertIntoChannelModal: ConfirmConvertIntoChannelModal; + + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Team info' })); + this.confirmDeleteTeamModal = new ConfirmDeleteTeamModal(page); + this.confirmConvertIntoChannelModal = new ConfirmConvertIntoChannelModal(page); + } + + async deleteTeam() { + await this.btnMore.click(); + await this.menu.selectMenuItem('Delete'); + return this.confirmDeleteTeamModal.confirmDelete(); + } + + async convertIntoChannel() { + await this.btnMore.click(); + await this.menu.selectMenuItem('Convert to Channel'); + await this.confirmConvertIntoChannelModal.confirmConvert(); + } +} + +export class OmnichannelRoomInfoFlexTab extends RoomInfoFlexTab { + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Room Information' })); + } + + getInfo(value: string): Locator { + return this.root.locator(`span >> text="${value}"`); + } + + getLabel(label: string): Locator { + return this.root.locator(`div >> text="${label}"`); + } + + getInfoByLabel(label: string): Locator { + return this.root.getByLabel(label); + } + + getTagInfoByLabel(label: string): Locator { + return this.root.getByRole('list', { name: 'Tags' }).getByText(label, { exact: true }); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/searchMessages-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/search-messages-flextab.ts similarity index 100% rename from apps/meteor/tests/e2e/page-objects/fragments/searchMessages-flextab.ts rename to apps/meteor/tests/e2e/page-objects/fragments/flextabs/search-messages-flextab.ts diff --git a/apps/meteor/tests/e2e/page-objects/fragments/flextabs/threads-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/threads-flextab.ts new file mode 100644 index 0000000000000..a1f3e3d5a71cd --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/threads-flextab.ts @@ -0,0 +1,17 @@ +import type { Locator, Page } from '@playwright/test'; + +import { FlexTab } from './flextab'; + +export class ThreadsFlexTab extends FlexTab { + constructor(page: Page) { + super(page.getByRole('dialog')); + } + + private get listThreadMessages(): Locator { + return this.root.getByRole('list', { name: 'Thread message list' }); + } + + get lastThreadMessage(): Locator { + return this.listThreadMessages.locator('[data-qa-type="message"]').last().locator('[data-qa-type="message-body"]'); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/user-info-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/user-info-flextab.ts similarity index 76% rename from apps/meteor/tests/e2e/page-objects/fragments/user-info-flextab.ts rename to apps/meteor/tests/e2e/page-objects/fragments/flextabs/user-info-flextab.ts index 249fb15c35eae..f66ac4bc0069c 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/user-info-flextab.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/user-info-flextab.ts @@ -1,7 +1,7 @@ import type { Locator, Page } from '@playwright/test'; import { FlexTab } from './flextab'; -import { MenuMore } from './menu'; +import { MenuMore } from '../menu'; export class UserInfoFlexTab extends FlexTab { readonly menu: MenuMore; @@ -22,4 +22,12 @@ export class UserInfoFlexTab extends FlexTab { get menuItemDeleteUser(): Locator { return this.menu.root.getByRole('menuitem', { name: 'Delete' }); } + + get username(): Locator { + return this.root.getByLabel('Username'); + } + + async openMoreActions() { + await this.btnMoreActions.click(); + } } diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts index d05b356dd5b0e..27efd1a1521aa 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts @@ -317,14 +317,6 @@ export class HomeContent { return this.primaryRoomActionsToolbar.getByRole('button', { name: 'Voice call' }); } - get userCard(): Locator { - return this.page.getByRole('dialog', { name: 'User card', exact: true }); - } - - get linkUserCard(): Locator { - return this.userCard.locator('a'); - } - get btnContactInformation(): Locator { return this.page.getByRole('button', { name: 'User Info' }); } diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-channels.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-channels.ts deleted file mode 100644 index 7b95c17d14c49..0000000000000 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-channels.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { Locator, Page } from '@playwright/test'; - -export class HomeFlextabChannels { - private readonly page: Page; - - constructor(page: Page) { - this.page = page; - } - - get channelsTab(): Locator { - return this.page.getByRole('dialog', { exact: true }); - } - - get btnAddExisting(): Locator { - return this.page.locator('button >> text="Add Existing"'); - } - - get btnCreateNew(): Locator { - return this.page.locator('button >> text="Create new"'); - } - - get inputChannels(): Locator { - return this.page.locator('#modal-root').getByRole('dialog').getByRole('textbox'); - } - - get btnAdd(): Locator { - return this.page.locator('role=dialog >> role=group >> role=button[name=Add]'); - } - - get channelsList(): Locator { - return this.channelsTab.getByRole('list'); - } - - getListboxOption(name: string): Locator { - return this.page.getByRole('listbox').getByRole('option', { name }); - } - - channelOption(name: string) { - return this.channelsTab.locator('li', { hasText: name }); - } - - async openChannelOptionMoreActions(name: string) { - await this.channelOption(name).hover(); - await this.channelOption(name).locator('role=button[name="More"]').click(); - } - - async confirmRemoveChannel() { - return this.page - .getByRole('dialog', { name: 'Are you sure?', exact: true }) - .getByRole('button', { name: 'Remove', exact: true }) - .click(); - } - - async confirmDeleteRoom() { - return this.page.getByRole('button', { name: 'Yes, delete', exact: true }).click(); - } -} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-members.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-members.ts deleted file mode 100644 index d23622e7d70f5..0000000000000 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-members.ts +++ /dev/null @@ -1,91 +0,0 @@ -import type { Page } from '@playwright/test'; - -export class HomeFlextabMembers { - private readonly page: Page; - - constructor(page: Page) { - this.page = page; - } - - memberOption(username: string) { - return this.page.getByRole('dialog').locator('li', { hasText: username }); - } - - async openMemberInfo(username: string) { - await this.memberOption(username).click(); - } - - getMenuItemAction(action: string) { - return this.page.locator(`role=menuitem[name="${action}"]`); - } - - async openMoreActions() { - await this.page.locator('role=button[name="More"]').click(); - } - - async openMemberOptionMoreActions(username: string) { - await this.memberOption(username).hover(); - await this.memberOption(username).locator('role=button[name="More"]').click(); - } - - async addUser(username: string) { - await this.page.locator('role=button[name="Add"]').click(); - await this.page.getByRole('textbox', { name: 'Choose users' }).pressSequentially(username); - await this.page.getByRole('option', { name: username }).click(); - await this.page.locator('role=button[name="Add users"]').click(); - } - - async inviteUser() { - await this.page.locator('role=button[name="Invite Link"]').click(); - } - - async muteUser(username: string) { - await this.openMemberOptionMoreActions(username); - await this.getMenuItemAction('Mute user').click(); - await this.page.locator('.rcx-modal .rcx-button--danger').click(); - await this.page.getByRole('dialog').getByRole('button').first().click(); - } - - async unmuteUser(username: string) { - await this.openMemberOptionMoreActions(username); - await this.getMenuItemAction('Unmute user').click(); - } - - async setUserAsModerator(username: string) { - await this.openMemberOptionMoreActions(username); - await this.getMenuItemAction('Set as moderator').click(); - } - - async setUserAsOwner(username: string) { - await this.openMemberOptionMoreActions(username); - await this.getMenuItemAction('Set as owner').click(); - } - - async showAllUsers() { - const selectInput = this.page.getByRole('button', { name: 'Online' }); - await selectInput.click(); - await this.page.getByRole('listbox').getByRole('option', { name: 'All' }).click(); - } - - private async ignoreUserAction(action: string, username: string) { - await this.openMemberInfo(username); - await this.openMoreActions(); - await this.getMenuItemAction(action).click(); - } - - async ignoreUser(username: string) { - await this.ignoreUserAction('Ignore', username); - } - - async unignoreUser(username: string) { - await this.ignoreUserAction('Unignore', username); - } - - get confirmRemoveUserModal() { - return this.page.getByRole('dialog', { name: 'Confirmation', exact: true }); - } - - async confirmRemoveUser() { - return this.confirmRemoveUserModal.getByRole('button', { name: 'Remove', exact: true }).click(); - } -} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-pruneMessages.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-pruneMessages.ts deleted file mode 100644 index 7d5f933be8203..0000000000000 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-pruneMessages.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { Locator, Page } from '@playwright/test'; - -export class HomeFlextabPruneMessages { - private readonly page: Page; - - constructor(page: Page) { - this.page = page; - } - - private get form(): Locator { - return this.page.getByRole('dialog', { name: 'Prune Messages' }); - } - - get doNotPrunePinned(): Locator { - return this.form.locator('label', { hasText: 'Do not prune pinned messages' }); - } - - get filesOnly(): Locator { - return this.form.locator('label', { hasText: 'Only remove the attached files, keep messages' }); - } - - async prune(): Promise { - await this.form.getByRole('button', { name: 'Prune' }).click(); - return this.page - .getByRole('dialog', { name: 'Are you sure?', exact: true }) - .getByRole('button', { name: 'Yes, prune them!', exact: true }) - .click(); - } -} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts deleted file mode 100644 index cbc6a9184b051..0000000000000 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts +++ /dev/null @@ -1,138 +0,0 @@ -import type { Locator, Page } from '@playwright/test'; - -export class HomeFlextabRoom { - private readonly page: Page; - - constructor(page: Page) { - this.page = page; - } - - get btnEdit(): Locator { - return this.page.locator('role=button[name="Edit"]'); - } - - get btnLeave(): Locator { - return this.page.locator('role=button[name="Leave"]'); - } - - get btnMore(): Locator { - return this.page.locator('role=button[name="More"]'); - } - - getMoreOption(option: string) { - return this.page.locator(`role=menuitem[name="${option}"]`); - } - - get confirmLeaveModal(): Locator { - return this.page.getByRole('dialog', { name: 'Confirmation', exact: true }); - } - - async confirmLeave() { - return this.confirmLeaveModal.getByRole('button', { name: 'Leave', exact: true }).click(); - } - - get confirmDeleteTeamModal(): Locator { - return this.page.getByRole('dialog', { name: 'Delete team', exact: true }); - } - - get confirmDeleteDiscussionModal(): Locator { - return this.page.getByRole('dialog', { name: 'Delete discussion', exact: true }); - } - - async confirmDeleteTeam() { - return this.confirmDeleteTeamModal.getByRole('button', { name: 'Yes, delete', exact: true }).click(); - } - - async confirmDeleteDiscussion() { - return this.confirmDeleteDiscussionModal.getByRole('button', { name: 'Yes, delete', exact: true }).click(); - } - - get confirmConvertModal(): Locator { - return this.page.getByRole('dialog', { name: 'Confirmation', exact: true }); - } - - async confirmConvert() { - return this.confirmConvertModal.getByRole('button', { name: 'Convert', exact: true }).click(); - } - - get optionDelete(): Locator { - return this.page.locator('label[data-key="delete"]'); - } - - get inputName(): Locator { - return this.page.getByRole('dialog').getByRole('textbox', { name: 'Name' }); - } - - get inputTopic(): Locator { - return this.page.getByRole('dialog').getByRole('textbox', { name: 'Topic' }); - } - - get inputAnnouncement(): Locator { - return this.page.getByRole('dialog').getByRole('textbox', { name: 'Announcement' }); - } - - get inputDescription(): Locator { - return this.page.getByRole('dialog').getByRole('textbox', { name: 'Description' }); - } - - get checkboxReadOnly(): Locator { - return this.page.locator('label', { has: this.page.getByRole('checkbox', { name: 'Read-only' }) }); - } - - get btnSave(): Locator { - return this.page.locator('role=button[name="Save"]'); - } - - get calloutRetentionPolicy(): Locator { - return this.page.getByRole('dialog').getByRole('alert', { name: 'Retention policy warning callout' }); - } - - get advancedSettingsAccordion(): Locator { - return this.page.getByRole('dialog').getByRole('button', { name: 'Advanced settings' }); - } - - get pruneAccordion(): Locator { - return this.page.getByRole('dialog').getByRole('button', { name: 'Prune', exact: true }); - } - - getMaxAgeLabel(maxAge = '30') { - return this.page.getByRole('dialog').getByText(`Maximum message age in days (default: ${maxAge})`); - } - - get inputRetentionMaxAge(): Locator { - return this.page.getByRole('dialog').locator('input[name="retentionMaxAge"]'); - } - - get checkboxPruneMessages(): Locator { - return this.page - .getByRole('dialog') - .locator('label', { has: this.page.getByRole('checkbox', { name: 'Automatically prune old messages' }) }); - } - - get checkboxOverrideGlobalRetention(): Locator { - return this.page - .getByRole('dialog') - .locator('label', { has: this.page.getByRole('checkbox', { name: 'Override global retention policy' }) }); - } - - get checkboxIgnoreThreads(): Locator { - return this.page.getByRole('dialog').locator('label', { has: this.page.getByRole('checkbox', { name: 'Do not prune Threads' }) }); - } - - get checkboxChannels(): Locator { - return this.page.getByRole('dialog').locator('label', { has: this.page.getByRole('checkbox', { name: 'Channels' }) }); - } - - get checkboxDiscussions(): Locator { - return this.page.getByRole('dialog').locator('label', { has: this.page.getByRole('checkbox', { name: 'Discussions' }) }); - } - - async toggleSidepanelItems() { - await this.checkboxChannels.click(); - await this.checkboxDiscussions.click(); - } - - get panelChannelInfo(): Locator { - return this.page.getByRole('dialog', { name: 'Channel info' }); - } -} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-flextab.ts deleted file mode 100644 index af808345e597b..0000000000000 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab.ts +++ /dev/null @@ -1,86 +0,0 @@ -import type { Locator, Page } from '@playwright/test'; - -import { ExportMessagesTab } from './export-messages-tab'; -import { FilesFlexTab } from './files-flextab'; -import { HomeFlextabChannels } from './home-flextab-channels'; -import { HomeFlextabMembers } from './home-flextab-members'; -import { HomeFlextabNotificationPreferences } from './home-flextab-notificationPreferences'; -import { HomeFlextabPruneMessages } from './home-flextab-pruneMessages'; -import { HomeFlextabRoom } from './home-flextab-room'; -import { SearchMessagesFlexTab } from './searchMessages-flextab'; - -export class HomeFlextab { - private readonly page: Page; - - readonly members: HomeFlextabMembers; - - readonly room: HomeFlextabRoom; - - readonly channels: HomeFlextabChannels; - - readonly notificationPreferences: HomeFlextabNotificationPreferences; - - readonly exportMessages: ExportMessagesTab; - - readonly pruneMessages: HomeFlextabPruneMessages; - - readonly searchMessages: SearchMessagesFlexTab; - - readonly files: FilesFlexTab; - - constructor(page: Page) { - this.page = page; - this.members = new HomeFlextabMembers(page); - this.room = new HomeFlextabRoom(page); - this.channels = new HomeFlextabChannels(page); - this.notificationPreferences = new HomeFlextabNotificationPreferences(page); - this.exportMessages = new ExportMessagesTab(page); - this.pruneMessages = new HomeFlextabPruneMessages(page); - this.searchMessages = new SearchMessagesFlexTab(page); - this.files = new FilesFlexTab(page); - } - - get toolbarPrimaryActions(): Locator { - return this.page.getByRole('toolbar', { name: 'Primary Room actions' }); - } - - get btnTeamMembers(): Locator { - return this.page.locator('role=menuitem[name="Teams Members"]'); - } - - get kebab(): Locator { - return this.toolbarPrimaryActions.locator('role=button[name="Options"]'); - } - - get btnNotificationPreferences(): Locator { - return this.page.locator('role=menuitem[name="Notifications Preferences"]'); - } - - get btnExportMessages(): Locator { - return this.page.locator('role=menuitem[name="Export messages"]'); - } - - get btnPruneMessages(): Locator { - return this.page.getByRole('menuitem', { name: 'Prune Messages' }); - } - - get btnDisableE2E(): Locator { - return this.page.locator('role=menuitem[name="Disable E2E encryption"]'); - } - - get btnEnableE2E(): Locator { - return this.page.locator('role=menuitem[name="Enable E2E encryption"]'); - } - - get userInfoUsername(): Locator { - return this.page.locator('[data-qa="UserInfoUserName"]'); - } - - get btnPinnedMessagesList(): Locator { - return this.page.locator('[data-key="pinned-messages"]'); - } - - get btnStarredMessageList(): Locator { - return this.page.locator('[data-key="starred-messages"]'); - } -} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/index.ts b/apps/meteor/tests/e2e/page-objects/fragments/index.ts index f9e422678697b..61b1944e5cfe9 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/index.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/index.ts @@ -1,15 +1,12 @@ -export * from './edit-user-flextab'; -export * from './user-info-flextab'; export * from './home-content'; export * from './home-omnichannel-content'; -export * from './home-flextab'; export * from './navbar'; export * from './sidebar'; export * from './sidepanel'; export * from './modals'; export * from './toast-messages'; -export * from './export-messages-tab'; export * from './menu'; export * from './table'; export * from './toolbar'; export * from './composer'; +export * from './flextabs'; diff --git a/apps/meteor/tests/e2e/page-objects/fragments/modals/confirm-delete-modal.ts b/apps/meteor/tests/e2e/page-objects/fragments/modals/confirm-delete-modal.ts index 64967bbdf19ca..5fea3747648d3 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/modals/confirm-delete-modal.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/modals/confirm-delete-modal.ts @@ -17,6 +17,21 @@ export class ConfirmDeleteModal extends Modal { } } +export class ConfirmDeleteRoomModal extends Modal { + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Delete' })); + } + + get btnDelete() { + return this.root.getByRole('button', { name: 'Yes, delete', exact: true }); + } + + async confirmDelete() { + await this.btnDelete.click(); + await this.waitForDismissal(); + } +} + export class ConfirmDeleteDepartmentModal extends ConfirmDeleteModal { constructor(page: Page) { super(page.getByRole('dialog', { name: 'Delete Department?' })); @@ -31,3 +46,18 @@ export class ConfirmDeleteDepartmentModal extends ConfirmDeleteModal { await this.confirmDelete(); } } + +export class ConfirmDeleteTeamModal extends Modal { + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Delete team', exact: true })); + } + + private get btnDelete() { + return this.root.getByRole('button', { name: 'Yes, delete', exact: true }); + } + + async confirmDelete() { + await this.btnDelete.click(); + await this.waitForDismissal(); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/modals/confirm-remove-modal.ts b/apps/meteor/tests/e2e/page-objects/fragments/modals/confirm-remove-modal.ts new file mode 100644 index 0000000000000..d1bfd0f01084f --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/modals/confirm-remove-modal.ts @@ -0,0 +1,18 @@ +import type { Locator } from '@playwright/test'; + +import { Modal } from './modal'; + +export class ConfirmRemoveModal extends Modal { + constructor(root: Locator) { + super(root); + } + + get btnRemove() { + return this.root.getByRole('button', { name: 'Remove' }); + } + + async confirmRemove() { + await this.btnRemove.click(); + await this.waitForDismissal(); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/modals/index.ts b/apps/meteor/tests/e2e/page-objects/fragments/modals/index.ts index 1f52d90447f9a..c48e32f7ef549 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/modals/index.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/modals/index.ts @@ -1,6 +1,7 @@ export * from './apps-modal'; export * from './confirm-delete-modal'; export * from './confirm-logout-modal'; +export * from './confirm-remove-modal'; export * from './create-new-modal'; export * from './delete-account-modal'; export * from './disable-room-encryption-modal'; diff --git a/apps/meteor/tests/e2e/page-objects/fragments/room-info-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/room-info-flextab.ts deleted file mode 100644 index 1983f8c6c57b7..0000000000000 --- a/apps/meteor/tests/e2e/page-objects/fragments/room-info-flextab.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { Locator, Page } from '@playwright/test'; - -import { FlexTab } from './flextab'; - -export class RoomInfoFlexTab extends FlexTab { - constructor(page: Page) { - super(page.getByRole('dialog', { name: 'Room Information' })); - } - - get btnEdit(): Locator { - return this.root.getByRole('button', { name: 'Edit' }); - } -} - -export class OmnichannelRoomInfoFlexTab extends RoomInfoFlexTab { - getInfo(value: string): Locator { - return this.root.locator(`span >> text="${value}"`); - } - - getLabel(label: string): Locator { - return this.root.locator(`div >> text="${label}"`); - } - - getInfoByLabel(label: string): Locator { - return this.root.getByLabel(label); - } - - getTagInfoByLabel(label: string): Locator { - return this.root.getByRole('list', { name: 'Tags' }).getByText(label, { exact: true }); - } -} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/toolbar.ts b/apps/meteor/tests/e2e/page-objects/fragments/toolbar.ts index 782c4516038cb..5548626412a4e 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/toolbar.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/toolbar.ts @@ -23,10 +23,6 @@ export class RoomToolbar extends Toolbar { return this.root.getByRole('button', { name: 'Room Information' }); } - private get btnTeamInfo() { - return this.root.getByRole('button', { name: 'Team info' }); - } - get btnMembers() { return this.root.getByRole('button', { name: 'Members' }); } @@ -47,10 +43,6 @@ export class RoomToolbar extends Toolbar { return this.root.getByRole('button', { name: 'Discussions' }); } - private get btnTeamChannels(): Locator { - return this.root.getByRole('button', { name: 'Team Channels' }); - } - get btnThreads(): Locator { return this.root.getByRole('button', { name: 'Threads' }); } @@ -71,20 +63,36 @@ export class RoomToolbar extends Toolbar { return this.root.getByRole('button', { name: 'Disable E2E encryption' }); } + get menuItemExportMessages(): Locator { + return this.menu.getMenuItem('Export messages'); + } + get menuItemMentions(): Locator { - return this.root.getByRole('menuitem', { name: 'Mentions' }); + return this.menu.getMenuItem('Mentions'); } get menuItemStarredMessages(): Locator { - return this.root.getByRole('menuitem', { name: 'Starred Messages' }); + return this.menu.getMenuItem('Starred Messages'); } get menuItemPinnedMessages(): Locator { - return this.root.getByRole('menuitem', { name: 'Pinned Messages' }); + return this.menu.getMenuItem('Pinned Messages'); } get menuItemPruneMessages(): Locator { - return this.root.getByRole('menuitem', { name: 'Prune Messages' }); + return this.menu.getMenuItem('Prune Messages'); + } + + get menuItemNotificationsPreferences(): Locator { + return this.menu.getMenuItem('Notifications Preferences'); + } + + get menuItemDisableE2EEncryption(): Locator { + return this.menu.getMenuItem('Disable E2E encryption'); + } + + get menuItemEnableE2EEncryption(): Locator { + return this.menu.getMenuItem('Enable E2E encryption'); } get menuItemFiles(): Locator { @@ -95,10 +103,6 @@ export class RoomToolbar extends Toolbar { await this.btnRoomInfo.click(); } - async openTeamInfo() { - await this.btnTeamInfo.click(); - } - async openMembersTab() { await this.btnMembers.click(); } @@ -107,15 +111,39 @@ export class RoomToolbar extends Toolbar { await this.btnUserInfo.click(); } + async openMoreOptions() { + await this.btnMoreOptions.click(); + } + + private get btnTeamChannels(): Locator { + return this.root.getByRole('button', { name: 'Team Channels' }); + } + async openTeamChannels() { await this.btnTeamChannels.click(); } +} - async openMoreOptions() { - await this.btnMoreOptions.click(); +export class TeamToolbar extends RoomToolbar { + private get menuItemTeamMembers() { + return this.menu.getMenuItem('Teams Members'); + } + + private get btnTeamInfo() { + return this.root.getByRole('button', { name: 'Team info' }); + } + + async openTeamMembers() { + await this.menuItemTeamMembers.click(); + } + + async openTeamInfo() { + await this.btnTeamInfo.click(); } } +export class EncryptedRoomToolbar extends RoomToolbar {} + export class OmnichannelRoomToolbar extends RoomToolbar { private get btnContactInfo(): Locator { return this.root.getByRole('button', { name: 'Contact Information' }); diff --git a/apps/meteor/tests/e2e/page-objects/fragments/user-card.ts b/apps/meteor/tests/e2e/page-objects/fragments/user-card.ts new file mode 100644 index 0000000000000..32c7ae4c96182 --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/user-card.ts @@ -0,0 +1,31 @@ +import type { Locator, Page } from '@playwright/test'; + +import { expect } from '../../utils/test'; + +export class UserCard { + readonly root: Locator; + + constructor(protected page: Page) { + this.root = page.getByRole('dialog', { name: 'User card', exact: true }); + } + + waitForDisplay() { + return expect(this.root).toBeVisible(); + } + + waitForDismissal() { + return expect(this.root).not.toBeVisible(); + } + + get btnSeeFullProfile(): Locator { + return this.root.getByRole('button', { name: 'See full profile', exact: true }); + } + + get imgUserCard(): Locator { + return this.root.locator('img'); + } + + async openUserInfo() { + await this.btnSeeFullProfile.click(); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/home-channel.ts b/apps/meteor/tests/e2e/page-objects/home-channel.ts index 5c953ff072acf..523b7e0996899 100644 --- a/apps/meteor/tests/e2e/page-objects/home-channel.ts +++ b/apps/meteor/tests/e2e/page-objects/home-channel.ts @@ -1,7 +1,27 @@ import type { Locator, Page } from '@playwright/test'; -import { HomeContent, HomeFlextab, Navbar, Sidepanel, RoomSidebar, ToastMessages, RoomComposer, ThreadComposer } from './fragments'; +import { + HomeContent, + Navbar, + Sidepanel, + RoomSidebar, + ToastMessages, + RoomComposer, + ThreadComposer, + MembersFlexTab, + ChannelsFlexTab, + NotificationPreferencesFlexTab, + ExportMessagesFlexTab, + PruneMessagesFlexTab, + SearchMessagesFlexTab, + RoomInfoFlexTab, + ThreadsFlexTab, + EditRoomFlexTab, + UserInfoFlexTab, + FilesFlexTab, +} from './fragments'; import { RoomToolbar } from './fragments/toolbar'; +import { UserCard } from './fragments/user-card'; import { VoiceCalls } from './fragments/voice-calls'; export class HomeChannel { @@ -15,7 +35,21 @@ export class HomeChannel { readonly navbar: Navbar; - readonly tabs: HomeFlextab; + readonly userCard: UserCard; + + private _tabs: { + members: MembersFlexTab; + userInfo: UserInfoFlexTab; + room: RoomInfoFlexTab; + editRoom: EditRoomFlexTab; + channels: ChannelsFlexTab; + notificationPreferences: NotificationPreferencesFlexTab; + exportMessages: ExportMessagesFlexTab; + pruneMessages: PruneMessagesFlexTab; + searchMessages: SearchMessagesFlexTab; + threads: ThreadsFlexTab; + files: FilesFlexTab; + }; readonly roomToolbar: RoomToolbar; @@ -33,7 +67,20 @@ export class HomeChannel { this.sidebar = new RoomSidebar(page); this.sidepanel = new Sidepanel(page); this.navbar = new Navbar(page); - this.tabs = new HomeFlextab(page); + this.userCard = new UserCard(page); + this._tabs = { + members: new MembersFlexTab(page), + userInfo: new UserInfoFlexTab(page), + room: new RoomInfoFlexTab(page.getByRole('dialog', { name: 'Channel info' })), + editRoom: new EditRoomFlexTab(page.getByRole('dialog', { name: 'Edit channel' })), + channels: new ChannelsFlexTab(page), + notificationPreferences: new NotificationPreferencesFlexTab(page), + exportMessages: new ExportMessagesFlexTab(page), + pruneMessages: new PruneMessagesFlexTab(page), + searchMessages: new SearchMessagesFlexTab(page), + threads: new ThreadsFlexTab(page), + files: new FilesFlexTab(page), + }; this.roomToolbar = new RoomToolbar(page); this.voiceCalls = new VoiceCalls(page); this.toastMessage = new ToastMessages(page); @@ -41,6 +88,10 @@ export class HomeChannel { this.threadComposer = new ThreadComposer(page); } + get tabs() { + return this._tabs; + } + goto() { return this.page.goto('/home'); } diff --git a/apps/meteor/tests/e2e/page-objects/home-discussion.ts b/apps/meteor/tests/e2e/page-objects/home-discussion.ts index 1088007bd9152..7764fad5c4784 100644 --- a/apps/meteor/tests/e2e/page-objects/home-discussion.ts +++ b/apps/meteor/tests/e2e/page-objects/home-discussion.ts @@ -1,36 +1,11 @@ -import type { Locator, Page } from '@playwright/test'; +import type { Page } from '@playwright/test'; -import { HomeContent, HomeFlextab, Navbar } from './fragments'; - -export class HomeDiscussion { - private readonly page: Page; - - readonly content: HomeContent; - - readonly navbar: Navbar; - - readonly tabs: HomeFlextab; +import { RoomInfoFlexTab } from './fragments'; +import { HomeChannel } from './home-channel'; +export class HomeDiscussion extends HomeChannel { constructor(page: Page) { - this.page = page; - this.content = new HomeContent(page); - this.navbar = new Navbar(page); - this.tabs = new HomeFlextab(page); - } - - get inputChannelName(): Locator { - return this.page.locator('role=textbox[name="Parent channel or team"]'); - } - - get inputName(): Locator { - return this.page.locator('role=textbox[name="Name"]'); - } - - get inputMessage(): Locator { - return this.page.locator('role=textbox[name="Message"]'); - } - - get btnCreate(): Locator { - return this.page.locator('role=dialog >> role=group >> role=button[name="Create"]'); + super(page); + this.tabs.room = new RoomInfoFlexTab(page.getByRole('dialog', { name: 'Discussion Info' })); } } diff --git a/apps/meteor/tests/e2e/page-objects/home-omnichannel.ts b/apps/meteor/tests/e2e/page-objects/home-omnichannel.ts index ea7695d398bf5..62bb9244e413f 100644 --- a/apps/meteor/tests/e2e/page-objects/home-omnichannel.ts +++ b/apps/meteor/tests/e2e/page-objects/home-omnichannel.ts @@ -1,8 +1,8 @@ import type { Locator, Page } from '@playwright/test'; import { HomeOmnichannelContent, OmnichannelQuickActionsRoomToolbar, OmnichannelRoomToolbar, OmnichannelSidebar } from './fragments'; -import { OmnichannelEditRoomFlexTab } from './fragments/edit-room-flextab'; -import { OmnichannelRoomInfoFlexTab } from './fragments/room-info-flextab'; +import { OmnichannelEditRoomFlexTab } from './fragments/flextabs'; +import { OmnichannelRoomInfoFlexTab } from './fragments/flextabs/room-info-flextab'; import { HomeChannel } from './home-channel'; import { OmnichannelCannedResponses, diff --git a/apps/meteor/tests/e2e/page-objects/home-team.ts b/apps/meteor/tests/e2e/page-objects/home-team.ts index 350daa7036de1..3fc7d1cea0062 100644 --- a/apps/meteor/tests/e2e/page-objects/home-team.ts +++ b/apps/meteor/tests/e2e/page-objects/home-team.ts @@ -1,28 +1,21 @@ -import type { Locator, Page } from '@playwright/test'; +import type { Page } from '@playwright/test'; +import { EditTeamFlexTab, TeamInfoFlexTab, TeamToolbar } from './fragments'; import { HomeChannel } from './home-channel'; -/** - * TODO: HomeTeam shouldn't exist since the rooms are the same - */ export class HomeTeam extends HomeChannel { + readonly headerToolbar: TeamToolbar; + constructor(page: Page) { super(page); + this.headerToolbar = new TeamToolbar(page); } - get inputTeamName(): Locator { - return this.page.locator('role=textbox[name="Name"]'); - } - - get btnTeamCreate(): Locator { - return this.page.locator('role=dialog >> role=group >> role=button[name=Create]'); - } - - get textPrivate(): Locator { - return this.page.locator('label', { has: this.page.getByRole('checkbox', { name: 'Private' }) }); - } - - get textReadOnly(): Locator { - return this.page.locator('label', { has: this.page.getByRole('checkbox', { name: 'Read-only' }) }); + override get tabs() { + return { + ...super.tabs, + room: new TeamInfoFlexTab(this.page), + editRoom: new EditTeamFlexTab(this.page), + }; } } diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-agents.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-agents.ts index b40141802759c..cbbd40ba92912 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-agents.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-agents.ts @@ -1,7 +1,7 @@ import type { Locator, Page } from '@playwright/test'; import { OmnichannelAdmin } from './omnichannel-admin'; -import { FlexTab } from '../fragments/flextab'; +import { FlexTab } from '../fragments/flextabs/flextab'; import { Listbox } from '../fragments/listbox'; import { Table } from '../fragments/table'; diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-contact-center/omnichannel-contact-center-chats.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-contact-center/omnichannel-contact-center-chats.ts index 3831bb49fb877..8168032b60cfb 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-contact-center/omnichannel-contact-center-chats.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-contact-center/omnichannel-contact-center-chats.ts @@ -1,7 +1,7 @@ import type { Locator, Page } from '@playwright/test'; import { OmnichannelContactCenter } from './omnichannel-contact-center'; -import { FlexTab } from '../../fragments/flextab'; +import { FlexTab } from '../../fragments/flextabs/flextab'; import { Listbox } from '../../fragments/listbox'; import { OmnichannelConfirmRemoveChat } from '../../fragments/modals'; import { Table } from '../../fragments/table'; diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-contact-center/omnichannel-contact-center-contacts.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-contact-center/omnichannel-contact-center-contacts.ts index 00989c8510325..5f10e0dc0c1c0 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-contact-center/omnichannel-contact-center-contacts.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-contact-center/omnichannel-contact-center-contacts.ts @@ -3,7 +3,7 @@ import type { Locator, Page } from '@playwright/test'; import { OmnichannelContactInfo } from '../omnichannel-info'; import { OmnichannelContactCenter } from './omnichannel-contact-center'; import { MenuMoreActions } from '../../fragments'; -import { OmnichannelEditContactFlexTab } from '../../fragments/edit-contact-flaxtab'; +import { OmnichannelEditContactFlexTab } from '../../fragments/flextabs'; import { OmnichannelDeleteContactModal } from '../../fragments/modals'; import { Table } from '../../fragments/table'; diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-custom-fields.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-custom-fields.ts index ca9fcf7ad26d0..25d10540d2590 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-custom-fields.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-custom-fields.ts @@ -1,7 +1,7 @@ import type { Locator, Page } from '@playwright/test'; import { OmnichannelAdmin } from './omnichannel-admin'; -import { FlexTab } from '../fragments/flextab'; +import { FlexTab } from '../fragments/flextabs/flextab'; import { Table } from '../fragments/table'; class OmnichannelManageCustomFieldsFlexTab extends FlexTab { diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts index 5d6a877e71022..5da1a0357d1c5 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts @@ -1,6 +1,6 @@ import type { Locator, Page } from '@playwright/test'; -import { FlexTab } from '../fragments/flextab'; +import { FlexTab } from '../fragments/flextabs/flextab'; import { OmnichannelContactReviewModal } from '../fragments/modals'; export class OmnichannelContactInfo extends FlexTab { diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-priorities.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-priorities.ts index d458c9f4f3970..1b28c02c1fe44 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-priorities.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-priorities.ts @@ -2,7 +2,7 @@ import type { Page } from '@playwright/test'; import { OmnichannelAdmin } from './omnichannel-admin'; import { ToastMessages } from '../fragments'; -import { FlexTab } from '../fragments/flextab'; +import { FlexTab } from '../fragments/flextabs/flextab'; import { OmnichannelResetPrioritiesModal } from '../fragments/modals'; import { Table } from '../fragments/table'; diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-sla-policies.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-sla-policies.ts index 277e5cbb97b4b..01b322a1d3fee 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-sla-policies.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-sla-policies.ts @@ -1,7 +1,7 @@ import type { Locator, Page } from '@playwright/test'; import { OmnichannelAdmin } from './omnichannel-admin'; -import { FlexTab } from '../fragments/flextab'; +import { FlexTab } from '../fragments/flextabs/flextab'; import { Table } from '../fragments/table'; class OmnichannelManageSlaPolicyFlexTab extends FlexTab { diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-tags.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-tags.ts index 4bf0212e25aad..a718a29e03e1c 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-tags.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-tags.ts @@ -1,7 +1,7 @@ import type { Locator, Page } from '@playwright/test'; import { OmnichannelAdmin } from './omnichannel-admin'; -import { FlexTab } from '../fragments/flextab'; +import { FlexTab } from '../fragments/flextabs/flextab'; import { Listbox } from '../fragments/listbox'; import { Table } from '../fragments/table'; diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-triggers.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-triggers.ts index 9619671a2c140..16e3def384c8e 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-triggers.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-triggers.ts @@ -1,7 +1,7 @@ import type { Locator, Page } from '@playwright/test'; import { OmnichannelAdmin } from './omnichannel-admin'; -import { FlexTab } from '../fragments/flextab'; +import { FlexTab } from '../fragments/flextabs/flextab'; import { Listbox } from '../fragments/listbox'; import { Table } from '../fragments/table'; diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-units.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-units.ts index 1ee38399ee639..32f5c03df6e10 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-units.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-units.ts @@ -1,7 +1,7 @@ import type { Locator, Page } from '@playwright/test'; import { OmnichannelAdmin } from './omnichannel-admin'; -import { FlexTab } from '../fragments/flextab'; +import { FlexTab } from '../fragments/flextabs/flextab'; import { Listbox } from '../fragments/listbox'; import { Table } from '../fragments/table'; diff --git a/apps/meteor/tests/e2e/prune-messages.spec.ts b/apps/meteor/tests/e2e/prune-messages.spec.ts index ea668588453a9..d3ce4d08b6b1a 100644 --- a/apps/meteor/tests/e2e/prune-messages.spec.ts +++ b/apps/meteor/tests/e2e/prune-messages.spec.ts @@ -56,35 +56,34 @@ test.describe('prune-messages', () => { }); await test.step('prune files only not pinned', async () => { - await pruneMessages.doNotPrunePinned.check({ force: true }); - await pruneMessages.filesOnly.check({ force: true }); + await pruneMessages.labelDoNotPrunePinned.click(); + await pruneMessages.labelFilesOnly.click(); await pruneMessages.prune(); await toastMessage.waitForDisplay({ type: 'success', message: '1 file pruned' }); await toastMessage.dismissToast(); - await expect(pruneMessages.filesOnly, 'Checkbox is reset after success').not.toBeChecked(); - await expect(pruneMessages.doNotPrunePinned, 'Checkbox is reset after success').not.toBeChecked(); + await expect(pruneMessages.labelFilesOnly, 'Checkbox is reset after success').not.toBeChecked(); + await expect(pruneMessages.labelDoNotPrunePinned, 'Checkbox is reset after success').not.toBeChecked(); }); await test.step('prune files only again', async () => { - await pruneMessages.doNotPrunePinned.check({ force: true }); - await pruneMessages.filesOnly.check({ force: true }); + await pruneMessages.labelDoNotPrunePinned.click(); + await pruneMessages.labelFilesOnly.click(); await pruneMessages.prune(); await toastMessage.waitForDisplay({ type: 'error', message: 'No files found to prune' }); await toastMessage.dismissToast('error'); - await expect(pruneMessages.filesOnly, 'Checkbox retains value after error').toBeChecked(); - await expect(pruneMessages.doNotPrunePinned, 'Checkbox retains value after error').toBeChecked(); + await expect(pruneMessages.labelFilesOnly, 'Checkbox retains value after error').toBeChecked(); + await expect(pruneMessages.labelDoNotPrunePinned, 'Checkbox retains value after error').toBeChecked(); }); await test.step('uncheck files only', async () => { - await pruneMessages.filesOnly.uncheck({ force: true }); + await pruneMessages.labelFilesOnly.click(); await pruneMessages.prune(); await toastMessage.waitForDisplay({ type: 'success', message: '2 messages pruned' }); await toastMessage.dismissToast(); - await expect(pruneMessages.filesOnly, 'Checkbox is reset after success').not.toBeChecked(); + await expect(pruneMessages.labelFilesOnly, 'Checkbox is reset after success').not.toBeChecked(); }); - await test.step('uncheck do not prune pinned', async () => { - await pruneMessages.doNotPrunePinned.uncheck({ force: true }); + await test.step('prune remained pinned message', async () => { await pruneMessages.prune(); await toastMessage.waitForDisplay({ type: 'success', message: '1 message pruned' }); await toastMessage.dismissToast(); @@ -114,12 +113,12 @@ test.describe('prune-messages', () => { await expect(content.getLastMessageByFileName('any_file.txt')).toBeVisible(); await test.step('prune files only', async () => { - await pruneMessages.filesOnly.check({ force: true }); + await pruneMessages.labelFilesOnly.click(); await pruneMessages.prune(); await toastMessage.waitForDisplay({ type: 'success', message: '1 file pruned' }); await toastMessage.dismissToast(); - await expect(pruneMessages.filesOnly, 'Checkbox is reset after success').not.toBeChecked(); - await expect(pruneMessages.doNotPrunePinned, 'Checkbox is reset after success').not.toBeChecked(); + await expect(pruneMessages.labelFilesOnly, 'Checkbox is reset after success').not.toBeChecked(); + await expect(pruneMessages.labelDoNotPrunePinned, 'Checkbox is reset after success').not.toBeChecked(); }); await test.step('check message list for prune message-attachment', async () => { diff --git a/apps/meteor/tests/e2e/retention-policy.spec.ts b/apps/meteor/tests/e2e/retention-policy.spec.ts index 35ab3b60b7678..f989f18b05147 100644 --- a/apps/meteor/tests/e2e/retention-policy.spec.ts +++ b/apps/meteor/tests/e2e/retention-policy.spec.ts @@ -3,7 +3,7 @@ import type { Page } from '@playwright/test'; import { createAuxContext } from './fixtures/createAuxContext'; import { Users } from './fixtures/userStates'; -import { HomeChannel } from './page-objects'; +import { HomeChannel, HomeTeam } from './page-objects'; import { createTargetTeam, createTargetPrivateChannel, getSettingValueById, setSettingValueById } from './utils'; import { test, expect } from './utils/test'; import { timeUnitToMs, TIMEUNIT } from '../../client/lib/convertTimeUnit'; @@ -53,7 +53,7 @@ test.describe.serial('retention-policy', () => { await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await expect(poHomeChannel.tabs.room.pruneAccordion).not.toBeVisible(); + await expect(poHomeChannel.tabs.editRoom.pruneAccordion).not.toBeVisible(); }); }); @@ -88,7 +88,7 @@ test.describe.serial('retention-policy', () => { await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await expect(poHomeChannel.tabs.room.pruneAccordion).toBeVisible(); + await expect(poHomeChannel.tabs.editRoom.pruneAccordion).toBeVisible(); }); test.describe('edit-room-retention-policy permission', async () => { @@ -104,13 +104,13 @@ test.describe.serial('retention-policy', () => { await auxContext.page.close(); }); test('should not show prune section in edit channel for users without permission', async () => { - await expect(poHomeChannel.tabs.room.pruneAccordion).not.toBeVisible(); + await expect(poHomeChannel.tabs.editRoom.pruneAccordion).not.toBeVisible(); }); test('users without permission should be able to edit the channel', async () => { - await auxContext.poHomeChannel.tabs.room.advancedSettingsAccordion.click(); - await auxContext.poHomeChannel.tabs.room.checkboxReadOnly.check(); - await auxContext.poHomeChannel.tabs.room.btnSave.click(); + await auxContext.poHomeChannel.tabs.editRoom.advancedSettingsAccordion.click(); + await auxContext.poHomeChannel.tabs.editRoom.checkboxReadOnly.check(); + await auxContext.poHomeChannel.tabs.editRoom.btnSave.click(); await expect(auxContext.poHomeChannel.content.getSystemMessageByText('set room to read only')).toBeVisible(); }); @@ -129,18 +129,19 @@ test.describe.serial('retention-policy', () => { await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await poHomeChannel.tabs.room.pruneAccordion.click(); - await expect(poHomeChannel.tabs.room.checkboxPruneMessages).toBeChecked(); + await poHomeChannel.tabs.editRoom.pruneAccordion.click(); + await expect(poHomeChannel.tabs.editRoom.checkboxPruneMessages).toBeChecked(); }); - test('should prune old messages checkbox enabled by default in team and show retention policy banner', async () => { - await poHomeChannel.navbar.openChat(targetTeam); - await expect(poHomeChannel.content.channelRetentionPolicyWarning).toBeVisible(); + test('should prune old messages checkbox enabled by default in team and show retention policy banner', async ({ page }) => { + const poHomeTeam = new HomeTeam(page); + await poHomeTeam.navbar.openChat(targetTeam); + await expect(poHomeTeam.content.channelRetentionPolicyWarning).toBeVisible(); - await poHomeChannel.roomToolbar.openTeamInfo(); - await poHomeChannel.tabs.room.btnEdit.click(); - await poHomeChannel.tabs.room.pruneAccordion.click(); - await expect(poHomeChannel.tabs.room.checkboxPruneMessages).toBeChecked(); + await poHomeTeam.headerToolbar.openTeamInfo(); + await poHomeTeam.tabs.room.btnEdit.click(); + await poHomeTeam.tabs.editRoom.pruneAccordion.click(); + await expect(poHomeTeam.tabs.editRoom.checkboxPruneMessages).toBeChecked(); }); test('should prune old messages checkbox enabled by default in group and show retention policy banner', async () => { @@ -149,8 +150,8 @@ test.describe.serial('retention-policy', () => { await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await poHomeChannel.tabs.room.pruneAccordion.click(); - await expect(poHomeChannel.tabs.room.checkboxPruneMessages).toBeChecked(); + await poHomeChannel.tabs.editRoom.pruneAccordion.click(); + await expect(poHomeChannel.tabs.editRoom.checkboxPruneMessages).toBeChecked(); }); test('should show retention policy banner in DMs', async () => { @@ -171,43 +172,43 @@ test.describe.serial('retention-policy', () => { await poHomeChannel.navbar.openChat(targetChannel); await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await poHomeChannel.tabs.room.pruneAccordion.click(); + await poHomeChannel.tabs.editRoom.pruneAccordion.click(); }); test('should display the default max age in edit channel', async () => { - await poHomeChannel.tabs.room.checkboxOverrideGlobalRetention.click(); + await poHomeChannel.tabs.editRoom.checkboxOverrideGlobalRetention.click(); - await expect(poHomeChannel.tabs.room.getMaxAgeLabel('15')).toBeVisible(); + await expect(poHomeChannel.tabs.editRoom.getMaxAgeLabel('15')).toBeVisible(); }); test('should display overridden retention max age value', async () => { - await poHomeChannel.tabs.room.checkboxOverrideGlobalRetention.click(); - await poHomeChannel.tabs.room.inputRetentionMaxAge.fill('365'); - await poHomeChannel.tabs.room.btnSave.click(); + await poHomeChannel.tabs.editRoom.checkboxOverrideGlobalRetention.click(); + await poHomeChannel.tabs.editRoom.inputRetentionMaxAge.fill('365'); + await poHomeChannel.tabs.editRoom.btnSave.click(); await poHomeChannel.toastMessage.dismissToast(); await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await poHomeChannel.tabs.room.pruneAccordion.click(); + await poHomeChannel.tabs.editRoom.pruneAccordion.click(); - await expect(poHomeChannel.tabs.room.getMaxAgeLabel('15')).toBeVisible(); - await expect(poHomeChannel.tabs.room.inputRetentionMaxAge).toHaveValue('365'); + await expect(poHomeChannel.tabs.editRoom.getMaxAgeLabel('15')).toBeVisible(); + await expect(poHomeChannel.tabs.editRoom.inputRetentionMaxAge).toHaveValue('365'); }); test('should ignore threads be checked accordingly with the global default value', async () => { - await expect(poHomeChannel.tabs.room.checkboxIgnoreThreads).toBeChecked({ checked: ignoreThreadsSetting }); + await expect(poHomeChannel.tabs.editRoom.checkboxIgnoreThreads).toBeChecked({ checked: ignoreThreadsSetting }); }); test('should override ignore threads default value', async () => { - await poHomeChannel.tabs.room.checkboxIgnoreThreads.click(); - await poHomeChannel.tabs.room.btnSave.click(); + await poHomeChannel.tabs.editRoom.checkboxIgnoreThreads.click(); + await poHomeChannel.tabs.editRoom.btnSave.click(); await poHomeChannel.toastMessage.dismissToast(); await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.tabs.room.btnEdit.click(); - await poHomeChannel.tabs.room.pruneAccordion.click(); + await poHomeChannel.tabs.editRoom.pruneAccordion.click(); - await expect(poHomeChannel.tabs.room.checkboxIgnoreThreads).toBeChecked({ checked: !ignoreThreadsSetting }); + await expect(poHomeChannel.tabs.editRoom.checkboxIgnoreThreads).toBeChecked({ checked: !ignoreThreadsSetting }); }); }); }); diff --git a/apps/meteor/tests/e2e/team-management.spec.ts b/apps/meteor/tests/e2e/team-management.spec.ts index 161506d47a36b..e1745212c6ea7 100644 --- a/apps/meteor/tests/e2e/team-management.spec.ts +++ b/apps/meteor/tests/e2e/team-management.spec.ts @@ -10,9 +10,11 @@ test.use({ storageState: Users.admin.state }); test.describe('teams-management-permissions', () => { let poHomeTeam: HomeTeam; + let newTeamModal: CreateNewTeamModal; test.beforeEach(async ({ page }) => { poHomeTeam = new HomeTeam(page); + newTeamModal = new CreateNewTeamModal(page); await page.goto('/home'); }); @@ -37,8 +39,8 @@ test.describe('teams-management-permissions', () => { await poHomeTeam.navbar.openCreate('Team'); - await expect(poHomeTeam.textPrivate).toBeDisabled(); - await expect(poHomeTeam.textPrivate).toBeChecked(); + await expect(newTeamModal.checkboxPrivate).toBeDisabled(); + await expect(newTeamModal.checkboxPrivate).toBeChecked(); }); test('should not allow to create private team if user does not have the create-p permission', async ({ api }) => { @@ -52,8 +54,8 @@ test.describe('teams-management-permissions', () => { await poHomeTeam.navbar.openCreate('Team'); - await expect(poHomeTeam.textPrivate).toBeDisabled(); - await expect(poHomeTeam.textPrivate).not.toBeChecked(); + await expect(newTeamModal.checkboxPrivate).toBeDisabled(); + await expect(newTeamModal.checkboxPrivate).not.toBeChecked(); }); test('should not allow to create team if user does not have both create-p and create-c permissions', async ({ api }) => { @@ -154,11 +156,11 @@ test.describe.serial('teams-management', () => { test('should set targetTeam as readonly', async () => { await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamInfo(); + await poHomeTeam.headerToolbar.openTeamInfo(); await poHomeTeam.tabs.room.btnEdit.click(); - await poHomeTeam.tabs.room.advancedSettingsAccordion.click(); - await poHomeTeam.tabs.room.checkboxReadOnly.click(); - await poHomeTeam.tabs.room.btnSave.click(); + await poHomeTeam.tabs.editRoom.advancedSettingsAccordion.click(); + await poHomeTeam.tabs.editRoom.checkboxReadOnly.click(); + await poHomeTeam.tabs.editRoom.btnSave.click(); await expect(poHomeTeam.content.getSystemMessageByText('set room to read only')).toBeVisible(); }); @@ -169,7 +171,7 @@ test.describe.serial('teams-management', () => { ); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await expect(poHomeTeam.tabs.channels.btnAddExisting).not.toBeVisible(); }); @@ -188,7 +190,7 @@ test.describe.serial('teams-management', () => { ).toBe(200); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await expect(poHomeTeam.tabs.channels.btnCreateNew).not.toBeVisible(); }); @@ -207,7 +209,7 @@ test.describe.serial('teams-management', () => { ).toBe(200); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await expect(poHomeTeam.tabs.channels.btnCreateNew).toBeVisible(); await poHomeTeam.tabs.channels.btnCreateNew.click(); @@ -234,7 +236,7 @@ test.describe.serial('teams-management', () => { ).toBe(200); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await expect(poHomeTeam.tabs.channels.btnCreateNew).toBeVisible(); await poHomeTeam.tabs.channels.btnCreateNew.click(); @@ -247,15 +249,12 @@ test.describe.serial('teams-management', () => { await expect(poHomeTeam.tabs.channels.channelsList).toContainText(targetGroupNameInTeam); }); - test('should move targetChannel to targetTeam', async ({ page, api }) => { + test('should move targetChannel to targetTeam', async ({ api }) => { expect((await api.post('/permissions.update', { permissions: [{ _id: 'move-room-to-team', roles: ['owner'] }] })).status()).toBe(200); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); - await poHomeTeam.tabs.channels.btnAddExisting.click(); - await poHomeTeam.tabs.channels.inputChannels.fill(targetChannel); - await page.locator(`.rcx-option__content:has-text("${targetChannel}")`).click(); - await poHomeTeam.tabs.channels.btnAdd.click(); + await poHomeTeam.headerToolbar.openTeamChannels(); + await poHomeTeam.tabs.channels.addExistingChannel(targetChannel); await expect(poHomeTeam.tabs.channels.channelsList).toContainText(targetChannel); }); @@ -278,7 +277,7 @@ test.describe.serial('teams-management', () => { ); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await poHomeTeam.tabs.channels.openChannelOptionMoreActions(targetGroupNameInTeam); await expect(page.getByRole('menu', { exact: true }).getByRole('menuitem', { name: 'Remove from team' })).not.toBeVisible(); }); @@ -287,7 +286,7 @@ test.describe.serial('teams-management', () => { expect((await api.post('/permissions.update', { permissions: [{ _id: 'remove-team-channel', roles: ['owner'] }] })).status()).toBe(200); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await poHomeTeam.tabs.channels.openChannelOptionMoreActions(targetGroupNameInTeam); await expect(page.getByRole('menu', { exact: true }).getByRole('menuitem', { name: 'Remove from team' })).toBeVisible(); await page.getByRole('menu', { exact: true }).getByRole('menuitem', { name: 'Remove from team' }).click(); @@ -313,11 +312,8 @@ test.describe.serial('teams-management', () => { // re-add channel to team await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); - await poHomeTeam.tabs.channels.btnAddExisting.click(); - await poHomeTeam.tabs.channels.inputChannels.fill(targetGroupNameInTeam); - await page.locator(`.rcx-option__content:has-text("${targetGroupNameInTeam}")`).click(); - await poHomeTeam.tabs.channels.btnAdd.click(); + await poHomeTeam.headerToolbar.openTeamChannels(); + await poHomeTeam.tabs.channels.addExistingChannel(targetGroupNameInTeam); await expect(poHomeTeam.tabs.channels.channelsList).toContainText(targetGroupNameInTeam); // try to delete group in team @@ -332,14 +328,14 @@ test.describe.serial('teams-management', () => { expect((await api.post('/permissions.update', { permissions: [{ _id: 'delete-team-group', roles: ['owner'] }] })).status()).toBe(200); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await poHomeTeam.tabs.channels.openChannelOptionMoreActions(targetGroupNameInTeam); await expect(page.getByRole('menu', { exact: true }).getByRole('menuitem', { name: 'Delete' })).toBeVisible(); await page.getByRole('menu', { exact: true }).getByRole('menuitem', { name: 'Delete' }).click(); await poHomeTeam.tabs.channels.confirmDeleteRoom(); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await expect(poHomeTeam.tabs.channels.channelsList).not.toContainText(targetGroupNameInTeam); }); @@ -352,7 +348,7 @@ test.describe.serial('teams-management', () => { ); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await poHomeTeam.tabs.channels.openChannelOptionMoreActions(targetChannelNameInTeam); await expect(page.getByRole('menu', { exact: true }).getByRole('menuitem', { name: 'Remove from team' })).not.toBeVisible(); }); @@ -361,7 +357,7 @@ test.describe.serial('teams-management', () => { expect((await api.post('/permissions.update', { permissions: [{ _id: 'remove-team-channel', roles: ['owner'] }] })).status()).toBe(200); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await poHomeTeam.tabs.channels.openChannelOptionMoreActions(targetChannelNameInTeam); await expect(page.getByRole('menu', { exact: true }).getByRole('menuitem', { name: 'Remove from team' })).toBeVisible(); await page.getByRole('menu', { exact: true }).getByRole('menuitem', { name: 'Remove from team' }).click(); @@ -387,11 +383,8 @@ test.describe.serial('teams-management', () => { // re-add channel to team await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); - await poHomeTeam.tabs.channels.btnAddExisting.click(); - await poHomeTeam.tabs.channels.inputChannels.fill(targetChannelNameInTeam); - await page.locator(`.rcx-option__content:has-text("${targetChannelNameInTeam}")`).click(); - await poHomeTeam.tabs.channels.btnAdd.click(); + await poHomeTeam.headerToolbar.openTeamChannels(); + await poHomeTeam.tabs.channels.addExistingChannel(targetChannelNameInTeam); await expect(poHomeTeam.tabs.channels.channelsList).toContainText(targetChannelNameInTeam); // try to delete channel in team @@ -406,14 +399,14 @@ test.describe.serial('teams-management', () => { expect((await api.post('/permissions.update', { permissions: [{ _id: 'delete-team-channel', roles: ['owner'] }] })).status()).toBe(200); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await poHomeTeam.tabs.channels.openChannelOptionMoreActions(targetChannelNameInTeam); await expect(page.getByRole('menu', { exact: true }).getByRole('menuitem', { name: 'Delete' })).toBeVisible(); await page.getByRole('menu', { exact: true }).getByRole('menuitem', { name: 'Delete' }).click(); await poHomeTeam.tabs.channels.confirmDeleteRoom(); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await expect(poHomeTeam.tabs.channels.channelsList).not.toContainText(targetChannelNameInTeam); }); @@ -421,7 +414,7 @@ test.describe.serial('teams-management', () => { expect((await api.post('/permissions.update', { permissions: [{ _id: 'remove-team-channel', roles: ['owner'] }] })).status()).toBe(200); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamChannels(); + await poHomeTeam.headerToolbar.openTeamChannels(); await poHomeTeam.tabs.channels.openChannelOptionMoreActions(targetChannel); await page.getByRole('menu', { exact: true }).getByRole('menuitem', { name: 'Remove from team' }).click(); await poHomeTeam.tabs.channels.confirmRemoveChannel(); @@ -431,25 +424,20 @@ test.describe.serial('teams-management', () => { test('should remove user1 from targetTeamNonPrivate', async () => { await poHomeTeam.navbar.openChat(targetTeamNonPrivate); - await poHomeTeam.tabs.kebab.click({ force: true }); - await poHomeTeam.tabs.btnTeamMembers.click(); + await poHomeTeam.headerToolbar.openMoreOptions(); + await poHomeTeam.headerToolbar.openTeamMembers(); await poHomeTeam.tabs.members.showAllUsers(); await poHomeTeam.tabs.members.openMemberOptionMoreActions('user1'); await poHomeTeam.tabs.members.getMenuItemAction('Remove from team').click(); - await expect(poHomeTeam.tabs.members.confirmRemoveUserModal).toBeVisible(); - await poHomeTeam.tabs.members.confirmRemoveUser(); await expect(poHomeTeam.tabs.members.memberOption('user1')).not.toBeVisible(); }); test('should delete targetTeamNonPrivate', async () => { await poHomeTeam.navbar.openChat(targetTeamNonPrivate); - await poHomeTeam.roomToolbar.openTeamInfo(); - await poHomeTeam.tabs.room.btnMore.click(); - await poHomeTeam.tabs.room.getMoreOption('Delete').click(); - await expect(poHomeTeam.tabs.room.confirmDeleteTeamModal).toBeVisible(); + await poHomeTeam.headerToolbar.openTeamInfo(); + await poHomeTeam.tabs.room.deleteTeam(); - await poHomeTeam.tabs.room.confirmDeleteTeam(); await poHomeTeam.navbar.typeSearch(targetTeamNonPrivate); await expect(poHomeTeam.navbar.getSearchRoomByName(targetTeamNonPrivate)).not.toBeVisible(); }); @@ -460,28 +448,21 @@ test.describe.serial('teams-management', () => { await user1Page.goto(`/group/${targetTeam}`); await user1Channel.content.waitForChannel(); - await user1Channel.roomToolbar.openTeamInfo(); - await user1Channel.tabs.room.btnLeave.click(); - await expect(user1Channel.tabs.room.confirmLeaveModal).toBeVisible(); - - await user1Channel.tabs.room.confirmLeave(); + await user1Channel.headerToolbar.openTeamInfo(); + await user1Channel.tabs.room.leaveRoom(); await user1Page.close(); await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.tabs.kebab.click({ force: true }); - await poHomeTeam.tabs.btnTeamMembers.click(); + await poHomeTeam.headerToolbar.openMoreOptions(); + await poHomeTeam.headerToolbar.openTeamMembers(); await poHomeTeam.tabs.members.showAllUsers(); await expect(poHomeTeam.tabs.members.memberOption('user1')).not.toBeVisible(); }); test('should convert team into a channel', async () => { await poHomeTeam.navbar.openChat(targetTeam); - await poHomeTeam.roomToolbar.openTeamInfo(); - await poHomeTeam.tabs.room.btnMore.click(); - await poHomeTeam.tabs.room.getMoreOption('Convert to Channel').click(); - await expect(poHomeTeam.tabs.room.confirmConvertModal).toBeVisible(); - - await poHomeTeam.tabs.room.confirmConvert(); + await poHomeTeam.headerToolbar.openTeamInfo(); + await poHomeTeam.tabs.room.convertIntoChannel(); // TODO: improve this locator and check the action reactivity await expect(poHomeTeam.content.getSystemMessageByText(`converted #${targetTeam} to channel`)).toBeVisible(); diff --git a/packages/ui-client/src/components/InfoPanel/InfoPanelField.tsx b/packages/ui-client/src/components/InfoPanel/InfoPanelField.tsx index 20bdbda9cb842..99bc88a6df0cc 100644 --- a/packages/ui-client/src/components/InfoPanel/InfoPanelField.tsx +++ b/packages/ui-client/src/components/InfoPanel/InfoPanelField.tsx @@ -1,10 +1,8 @@ import { Box } from '@rocket.chat/fuselage'; -import type { ReactNode } from 'react'; +import type { ComponentPropsWithoutRef } from 'react'; -type InfoPanelFieldProps = { - children?: ReactNode; -}; +type InfoPanelFieldProps = ComponentPropsWithoutRef; -const InfoPanelField = ({ children }: InfoPanelFieldProps) => {children}; +const InfoPanelField = (props: InfoPanelFieldProps) => ; export default InfoPanelField; From 58fc21c785f9200c2a27399c1abc47fdcd874e83 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 7 Apr 2026 16:53:18 -0300 Subject: [PATCH 24/51] ci: upgrade actions/cache to v5 (#40064) --- .github/actions/meteor-build/action.yml | 8 ++++---- .github/actions/setup-node/action.yml | 2 +- .github/actions/setup-playwright/action.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/meteor-build/action.yml b/.github/actions/meteor-build/action.yml index 9466a172cebf7..75ce286b6ae53 100644 --- a/.github/actions/meteor-build/action.yml +++ b/.github/actions/meteor-build/action.yml @@ -30,7 +30,7 @@ runs: steps: - name: Cache build - uses: actions/cache@v4 + uses: actions/cache@v5 id: cache-build with: path: /tmp/Rocket.Chat.tar.gz @@ -69,7 +69,7 @@ runs: # df -h - name: Cache vite - uses: actions/cache@v3 + uses: actions/cache@v5 if: steps.cache-build.outputs.cache-hit != 'true' with: path: ./node_modules/.vite @@ -78,7 +78,7 @@ runs: vite-local-cache-${{ runner.arch }}-${{ runner.os }}- - name: Cache meteor local - uses: actions/cache@v3 + uses: actions/cache@v5 if: steps.cache-build.outputs.cache-hit != 'true' with: path: ./apps/meteor/.meteor/local @@ -87,7 +87,7 @@ runs: meteor-local-cache-${{ runner.arch }}-${{ runner.os }}-${{ inputs.type }}- - name: Cache meteor - uses: actions/cache@v3 + uses: actions/cache@v5 if: steps.cache-build.outputs.cache-hit != 'true' with: path: ~/.meteor diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml index 16eb1317327e5..86d7a8e926eb9 100644 --- a/.github/actions/setup-node/action.yml +++ b/.github/actions/setup-node/action.yml @@ -41,7 +41,7 @@ runs: - name: Cache Node Modules & Deno if: inputs.cache-modules id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v5 with: # We need to cache node_modules for all workspaces with "hoistingLimits" defined path: | diff --git a/.github/actions/setup-playwright/action.yml b/.github/actions/setup-playwright/action.yml index 1d71e06e2c473..609a8e925878d 100644 --- a/.github/actions/setup-playwright/action.yml +++ b/.github/actions/setup-playwright/action.yml @@ -5,7 +5,7 @@ runs: steps: - name: Cache Playwright binaries - uses: actions/cache@v4 + uses: actions/cache@v5 id: cache-playwright with: path: | From a23c43b99bbf49f6ba9ada3110636b80e66dd9f7 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 7 Apr 2026 18:42:31 -0300 Subject: [PATCH 25/51] fix: delete all users subscriptions on re-join after being banned (#40061) --- .changeset/many-avocados-battle.md | 5 + .../app/lib/server/functions/addUserToRoom.ts | 8 +- apps/meteor/tests/end-to-end/api/rooms.ts | 126 ++++++++++++++++++ 3 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 .changeset/many-avocados-battle.md diff --git a/.changeset/many-avocados-battle.md b/.changeset/many-avocados-battle.md new file mode 100644 index 0000000000000..e059961f0eee8 --- /dev/null +++ b/.changeset/many-avocados-battle.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes a bug that could remove all of a user's subscriptions when the user was re-added to a room while still banned. diff --git a/apps/meteor/app/lib/server/functions/addUserToRoom.ts b/apps/meteor/app/lib/server/functions/addUserToRoom.ts index dc4f83654f1c8..7b871e2d37a9d 100644 --- a/apps/meteor/app/lib/server/functions/addUserToRoom.ts +++ b/apps/meteor/app/lib/server/functions/addUserToRoom.ts @@ -11,7 +11,7 @@ import { beforeAddUserToRoom } from '../../../../server/lib/callbacks/beforeAddU import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator'; import { settings } from '../../../settings/server'; import { beforeAddUserToRoom as beforeAddUserToRoomPatch } from '../lib/beforeAddUserToRoom'; -import { notifyOnRoomChangedById } from '../lib/notifyListener'; +import { notifyOnRoomChangedById, notifyOnSubscriptionChanged } from '../lib/notifyListener'; /** * This function adds user to the given room. @@ -97,10 +97,12 @@ export const addUserToRoom = async ( if (!isBannedSubscription(subscription)) { return true; } - const deleteCount = await Subscriptions.removeByUserId(userToBeAdded._id); - if (!deleteCount) { + + const deletedSub = await Subscriptions.removeByRoomIdAndUserId(rid, userToBeAdded._id); + if (!deletedSub) { return true; } + void notifyOnSubscriptionChanged(deletedSub, 'removed'); if (!skipSystemMessage && inviter) { await Message.saveSystemMessage('user-unbanned', rid, userToBeAdded.username!, inviter, { ts: now }); diff --git a/apps/meteor/tests/end-to-end/api/rooms.ts b/apps/meteor/tests/end-to-end/api/rooms.ts index fada0b0287546..2d22484773b38 100644 --- a/apps/meteor/tests/end-to-end/api/rooms.ts +++ b/apps/meteor/tests/end-to-end/api/rooms.ts @@ -4587,4 +4587,130 @@ describe('[Rooms]', () => { }); }); }); + + describe('Re-inviting a banned user should preserve other subscriptions', () => { + let privateChannel: IRoom; + let otherChannel1: IRoom; + let otherChannel2: IRoom; + let userB: TestUser; + let userBCredentials: Credentials; + + before(async () => { + userB = await createUser(); + userBCredentials = await login(userB.username, password); + + // Create the private channel (owned by admin / User A) + const result = await createRoom({ type: 'p', name: `ban-reinvite-test-${Date.now()}` }); + privateChannel = result.body.group; + + // Create two additional channels that User B will be a member of + const ch1 = await createRoom({ type: 'c', name: `other-ch1-${Date.now()}` }); + otherChannel1 = ch1.body.channel; + + const ch2 = await createRoom({ type: 'c', name: `other-ch2-${Date.now()}` }); + otherChannel2 = ch2.body.channel; + + // Add User B to all three channels + await request.post(api('groups.invite')).set(credentials).send({ roomId: privateChannel._id, userId: userB._id }).expect(200); + await request.post(api('channels.invite')).set(credentials).send({ roomId: otherChannel1._id, userId: userB._id }).expect(200); + await request.post(api('channels.invite')).set(credentials).send({ roomId: otherChannel2._id, userId: userB._id }).expect(200); + }); + + after(async () => { + await deleteRoom({ type: 'p', roomId: privateChannel._id }); + await deleteRoom({ type: 'c', roomId: otherChannel1._id }); + await deleteRoom({ type: 'c', roomId: otherChannel2._id }); + await deleteUser(userB); + }); + + it('should confirm User B is a member of all three channels', async () => { + const res = await request.get(api('subscriptions.get')).set(userBCredentials).expect(200); + expect(res.body).to.have.property('success', true); + + const roomIds = res.body.update.map((sub: { rid: string }) => sub.rid); + expect(roomIds).to.include(privateChannel._id); + expect(roomIds).to.include(otherChannel1._id); + expect(roomIds).to.include(otherChannel2._id); + }); + + it('should ban User B from the private channel', async () => { + await request + .post(api('rooms.banUser')) + .set(credentials) + .send({ + roomId: privateChannel._id, + userId: userB._id, + }) + .expect('Content-Type', 'application/json') + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + }); + }); + + it('should still have User B subscribed to the other channels after being banned', async () => { + const res = await request.get(api('subscriptions.get')).set(userBCredentials).expect(200); + expect(res.body).to.have.property('success', true); + + const roomIds = res.body.update.map((sub: { rid: string }) => sub.rid); + expect(roomIds).to.include(otherChannel1._id); + expect(roomIds).to.include(otherChannel2._id); + expect(roomIds).to.not.include(privateChannel._id); + }); + + it('should re-invite banned User B back to the private channel', async () => { + await request + .post(api('groups.invite')) + .set(credentials) + .send({ + roomId: privateChannel._id, + userId: userB._id, + }) + .expect('Content-Type', 'application/json') + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + }); + }); + + it('should list User B as a member of the private channel again', async () => { + const res = await request + .get(api('groups.members')) + .set(credentials) + .query({ + roomId: privateChannel._id, + }) + .expect('Content-Type', 'application/json') + .expect(200); + + expect(res.body).to.have.property('success', true); + const usernames = res.body.members.map((m: IUser) => m.username); + expect(usernames).to.include(userB.username); + }); + + it('should no longer list User B as banned', async () => { + const res = await request + .get(api('rooms.bannedUsers')) + .set(credentials) + .query({ + roomId: privateChannel._id, + }) + .expect('Content-Type', 'application/json') + .expect(200); + + expect(res.body).to.have.property('success', true); + const userIds = res.body.bannedUsers.map((u: IUser) => u._id); + expect(userIds).to.not.include(userB._id); + }); + + it('should preserve all other channel subscriptions after re-invite', async () => { + const res = await request.get(api('subscriptions.get')).set(userBCredentials).expect(200); + expect(res.body).to.have.property('success', true); + + const roomIds = res.body.update.map((sub: { rid: string }) => sub.rid); + expect(roomIds).to.include(privateChannel._id, 'User B should be re-subscribed to the private channel'); + expect(roomIds).to.include(otherChannel1._id, 'User B should still be subscribed to otherChannel1'); + expect(roomIds).to.include(otherChannel2._id, 'User B should still be subscribed to otherChannel2'); + }); + }); }); From dd55029450e461a7d6873a0a034bf128fcdde831 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 7 Apr 2026 19:44:22 -0300 Subject: [PATCH 26/51] test(federation): reorganize display name change tests for clarity and consistency (#40079) --- .../tests/end-to-end/dms.spec.ts | 175 ++++++++++-------- 1 file changed, 93 insertions(+), 82 deletions(-) diff --git a/ee/packages/federation-matrix/tests/end-to-end/dms.spec.ts b/ee/packages/federation-matrix/tests/end-to-end/dms.spec.ts index 64bed6b14ebf4..688655ee5be69 100644 --- a/ee/packages/federation-matrix/tests/end-to-end/dms.spec.ts +++ b/ee/packages/federation-matrix/tests/end-to-end/dms.spec.ts @@ -186,88 +186,6 @@ const waitForRoomEvent = async ( }); }); - describe('Display name changes', () => { - let rcUser: TestUser; - let rcUserConfig: IRequestConfig; - let hs1Room: Room; - let rcRoom: IRoom; - - const userDm = `dm-federation-displayname-user-${Date.now()}`; - const userDmId = `@${userDm}:${federationConfig.rc1.domain}`; - const initialDisplayName = `DM User ${Date.now()}`; - const updatedDisplayName = `Updated Display Name ${Date.now()}`; - - beforeAll(async () => { - rcUser = await createUser( - { - username: userDm, - password: 'random', - email: `${userDm}@rocket.chat`, - name: initialDisplayName, - }, - rc1AdminRequestConfig, - ); - - rcUserConfig = await getRequestConfig(federationConfig.rc1.url, rcUser.username, 'random'); - - hs1Room = (await hs1AdminApp.createDM([userDmId])) as Room; - - await retry('waiting for the room to be created in RC', async () => { - const roomsResponse = await rcUserConfig.request.get(api('rooms.get')).set(rcUserConfig.credentials).expect(200); - - rcRoom = roomsResponse.body.update.find((room: IRoomNativeFederated) => room.federation.mrid === hs1Room.roomId); - - expect(rcRoom).toHaveProperty('_id'); - }); - }); - - afterAll(async () => { - await deleteUser(rcUser, {}, rc1AdminRequestConfig); - - // Reset display name back to original - await hs1AdminApp.matrixClient.setDisplayName(federationConfig.hs1.adminUser); - - // wait until the name change is reflected in RC before finishing the test - await retry( - 'waiting for Synapse user displayname to propagate to RC', - async () => { - const response = await rc1AdminRequestConfig.request - .get(api('users.info')) - .set(rc1AdminRequestConfig.credentials) - .query({ username: federationConfig.hs1.adminMatrixUserId }) - .expect(200); - - expect(response.body.user).toHaveProperty('name', federationConfig.hs1.adminUser); - }, - { retries: 15, delayMs: 1000 }, - ); - }); - - it('should accept the DM invitation from RC', async () => { - const response = await acceptRoomInvite(rcRoom._id, rcUserConfig); - expect(response.success).toBe(true); - }); - - it('should update DM room name after Synapse user changes their display name', async () => { - // Verify initial state: room name should be the Synapse admin initial display name - const initialSub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); - expect(initialSub).toHaveProperty('fname', federationConfig.hs1.adminUser); - - // Action: update the Synapse user's displayname - await hs1AdminApp.matrixClient.setDisplayName(updatedDisplayName); - - // Verify: the DM room name should be updated after the debounced name update completes - await retry( - 'waiting for DM room name to be updated after display name change', - async () => { - const updatedSub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); - expect(updatedSub).toHaveProperty('fname', updatedDisplayName); - }, - { delayMs: 1000 }, - ); - }); - }); - describe('Permission validations', () => { let rcUser: TestUser; let rcUserConfig: IRequestConfig; @@ -368,6 +286,99 @@ const waitForRoomEvent = async ( await leaveEventPromise; }); }); + + describe('Display name changes', () => { + let rcUser: TestUser; + let rcUserConfig: IRequestConfig; + let hs1Room: Room; + let rcRoom: IRoom; + + const userDm = `dm-federation-displayname-user-${Date.now()}`; + const userDmId = `@${userDm}:${federationConfig.rc1.domain}`; + const initialDisplayName = `DM User ${Date.now()}`; + const updatedDisplayName = `Updated Display Name ${Date.now()}`; + + beforeAll(async () => { + rcUser = await createUser( + { + username: userDm, + password: 'random', + email: `${userDm}@rocket.chat`, + name: initialDisplayName, + }, + rc1AdminRequestConfig, + ); + + rcUserConfig = await getRequestConfig(federationConfig.rc1.url, rcUser.username, 'random'); + + hs1Room = (await hs1AdminApp.createDM([userDmId])) as Room; + + await retry('waiting for the room to be created in RC', async () => { + const roomsResponse = await rcUserConfig.request.get(api('rooms.get')).set(rcUserConfig.credentials).expect(200); + + rcRoom = roomsResponse.body.update.find((room: IRoomNativeFederated) => room.federation.mrid === hs1Room.roomId); + + expect(rcRoom).toHaveProperty('_id'); + }); + }); + + afterAll(async () => { + // Reset display name back to original before deleting the user + await hs1AdminApp.matrixClient.setDisplayName(federationConfig.hs1.adminUser); + + // wait until the name change is reflected in RC before finishing the test + await retry( + 'waiting for Synapse user displayname to propagate to RC', + async () => { + const response = await rc1AdminRequestConfig.request + .get(api('users.info')) + .set(rc1AdminRequestConfig.credentials) + .query({ username: federationConfig.hs1.adminMatrixUserId }) + .expect(200); + + expect(response.body.user).toHaveProperty('name', federationConfig.hs1.adminUser); + }, + { retries: 15, delayMs: 1000 }, + ); + + // Also wait for the DM subscription fname to be updated, since this propagates + // asynchronously after the user name change via debounced Room.updateDirectMessageRoomName + await retry( + 'waiting for subscription fname to reflect reset display name', + async () => { + const sub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); + expect(sub).toHaveProperty('fname', federationConfig.hs1.adminUser); + }, + { retries: 10, delayMs: 1000 }, + ); + + await deleteUser(rcUser, {}, rc1AdminRequestConfig); + }); + + it('should accept the DM invitation from RC', async () => { + const response = await acceptRoomInvite(rcRoom._id, rcUserConfig); + expect(response.success).toBe(true); + }); + + it('should update DM room name after Synapse user changes their display name', async () => { + // Verify initial state: room name should be the Synapse admin initial display name + const initialSub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); + expect(initialSub).toHaveProperty('fname', federationConfig.hs1.adminUser); + + // Action: update the Synapse user's displayname + await hs1AdminApp.matrixClient.setDisplayName(updatedDisplayName); + + // Verify: the DM room name should be updated after the debounced name update completes + await retry( + 'waiting for DM room name to be updated after display name change', + async () => { + const updatedSub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); + expect(updatedSub).toHaveProperty('fname', updatedDisplayName); + }, + { delayMs: 1000 }, + ); + }); + }); }); describe('Rocket.Chat as the resident server', () => { From b0f026b40317a59090318eae275a4805901344f3 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 7 Apr 2026 19:47:25 -0300 Subject: [PATCH 27/51] ci: improve cache keys, observability, and node_modules caching strategy (#39709) --- .github/actions/meteor-build/action.yml | 2 +- .github/actions/setup-node/action.yml | 36 +++++++++--------- .github/workflows/ci-code-check.yml | 49 +++++++++++++++++++------ .github/workflows/ci.yml | 29 +++++++++++++-- 4 files changed, 82 insertions(+), 34 deletions(-) diff --git a/.github/actions/meteor-build/action.yml b/.github/actions/meteor-build/action.yml index 75ce286b6ae53..8f0a033433f78 100644 --- a/.github/actions/meteor-build/action.yml +++ b/.github/actions/meteor-build/action.yml @@ -22,7 +22,7 @@ inputs: type: string source-hash: required: true - description: 'Source code hash' + description: 'RC cache id (e.g. packages-build-cache-key + meteor apps/meteor archive hash from CI)' type: string runs: diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml index 86d7a8e926eb9..7163afb1a13d1 100644 --- a/.github/actions/setup-node/action.yml +++ b/.github/actions/setup-node/action.yml @@ -33,46 +33,48 @@ outputs: node-version: description: 'Node version' value: ${{ steps.node-version.outputs.node-version }} + cache-deno-hit: + description: 'Exact key hit for Deno cache' + value: ${{ steps.cache-deno.outputs.cache-hit }} runs: using: composite steps: - - name: Cache Node Modules & Deno + # Turbo local cache: use rharkor/caching-for-turbo in workflows — not stored here to avoid huge redundant keys. + - name: Cache Deno (apps-engine) if: inputs.cache-modules - id: cache-node-modules + id: cache-deno uses: actions/cache@v5 with: - # We need to cache node_modules for all workspaces with "hoistingLimits" defined - path: | - .turbo/cache - node_modules - apps/meteor/node_modules - apps/meteor/ee/server/services/node_modules - packages/apps-engine/node_modules - packages/apps-engine/.deno-cache - key: node-modules-${{ inputs.type }}-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('package.json') }}-${{ hashFiles('yarn.lock') }}-${{ hashFiles('.yarnrc.yml') }}-deno-v${{ inputs.deno-version }}-${{ hashFiles('packages/apps-engine/deno-runtime/deno.lock') }}-v5 - # key: node-modules-${{ inputs.type }}-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('package.json') }}-${{ hashFiles('yarn.lock') }}-${{ hashFiles('.yarnrc.yml') }}-deno-v${{ inputs.deno-version }}-${{ hashFiles('packages/apps-engine/deno-runtime/deno.lock') }}-v${{ github.run_id }} - # - # Could use this command to list all paths to save: - # find . -name 'node_modules' -prune | grep -v "/\.meteor/" | grep -v "/meteor/packages/" + path: packages/apps-engine/.deno-cache + key: deno-${{ runner.os }}-${{ runner.arch }}-v${{ inputs.deno-version }}-${{ hashFiles('packages/apps-engine/deno-runtime/deno.lock') }} + restore-keys: | + deno-${{ runner.os }}-${{ runner.arch }}-v${{ inputs.deno-version }}- - name: Use Node.js ${{ inputs.node-version }} id: node-version uses: actions/setup-node@v6.0.0 with: node-version: ${{ inputs.node-version }} - cache: 'yarn' + cache: ${{ inputs.cache-modules && 'yarn' || '' }} - name: Use Deno ${{ inputs.deno-version }} uses: denoland/setup-deno@v1 with: deno-version: ${{ inputs.deno-version }} + - name: Cache mongodb-memory-server binary + if: inputs.cache-modules + uses: actions/cache@v5 + with: + path: ${{ runner.temp }}/mongodb-memory-server + key: mongoms-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} + - name: Configure mongodb-memory-server cache shell: bash run: | - CACHE_DIR="${GITHUB_WORKSPACE}/node_modules/.cache/mongodb-memory-server" + CACHE_DIR="${{ runner.temp }}/mongodb-memory-server" mkdir -p "$CACHE_DIR" echo "MONGOMS_DOWNLOAD_DIR=$CACHE_DIR" >> $GITHUB_ENV echo "MONGOMS_PREFER_GLOBAL_PATH=false" >> $GITHUB_ENV diff --git a/.github/workflows/ci-code-check.yml b/.github/workflows/ci-code-check.yml index a2eecd5603f3e..45e02e88228bd 100644 --- a/.github/workflows/ci-code-check.yml +++ b/.github/workflows/ci-code-check.yml @@ -45,15 +45,21 @@ jobs: - uses: ./.github/actions/restore-packages - - name: Cache TypeCheck - uses: actions/cache@v5 + - name: Restore TypeScript incremental cache + id: restore-typecheck + if: matrix.check == 'ts' + uses: actions/cache/restore@v5 with: path: ./apps/meteor/tsconfig.typecheck.tsbuildinfo - key: typecheck-cache-${{ runner.OS }}-${{ hashFiles('yarn.lock') }}-${{ github.event.issue.number }} + key: typecheck-cache-${{ runner.os }}-${{ hashFiles('yarn.lock') }} restore-keys: | - typecheck-cache-${{ runner.OS }}-${{ hashFiles('yarn.lock') }} - typecheck-cache-${{ runner.OS }} - typecheck-cache + typecheck-cache-${{ runner.os }}- + + - name: Cache observability (typecheck) + if: matrix.check == 'ts' + run: | + echo "### TypeScript incremental cache" >> $GITHUB_STEP_SUMMARY + echo "- **exact hit**: \`${{ steps.restore-typecheck.outputs.cache-hit }}\`" >> $GITHUB_STEP_SUMMARY - name: Install Meteor shell: bash @@ -79,17 +85,36 @@ jobs: if: matrix.check == 'ts' run: yarn turbo run typecheck --concurrency=5 - - name: Cache eslint - uses: actions/cache@v5 + - name: Save TypeScript incremental cache + if: matrix.check == 'ts' && github.ref == 'refs/heads/develop' && github.event_name == 'push' + uses: actions/cache/save@v5 + with: + path: ./apps/meteor/tsconfig.typecheck.tsbuildinfo + key: typecheck-cache-${{ runner.os }}-${{ hashFiles('yarn.lock') }} + + - name: Restore ESLint cache + id: restore-eslint if: matrix.check == 'lint' + uses: actions/cache/restore@v5 with: path: ./apps/meteor/.eslintcache - key: eslintcache-cache-${{ runner.OS }}-${{ hashFiles('yarn.lock') }}-${{ github.event.issue.number }} + key: eslintcache-${{ runner.os }}-${{ hashFiles('yarn.lock') }} restore-keys: | - eslintcache-cache-${{ runner.OS }}-${{ hashFiles('yarn.lock') }} - eslintcache-cache-${{ runner.OS }} - eslintcache-cache + eslintcache-${{ runner.os }}- + + - name: Cache observability (eslint) + if: matrix.check == 'lint' + run: | + echo "### ESLint cache" >> $GITHUB_STEP_SUMMARY + echo "- **exact hit**: \`${{ steps.restore-eslint.outputs.cache-hit }}\`" >> $GITHUB_STEP_SUMMARY - name: Lint if: matrix.check == 'lint' run: yarn lint + + - name: Save ESLint cache + if: matrix.check == 'lint' && github.ref == 'refs/heads/develop' && github.event_name == 'push' + uses: actions/cache/save@v5 + with: + path: ./apps/meteor/.eslintcache + key: eslintcache-${{ runner.os }}-${{ hashFiles('yarn.lock') }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d590223204a86..ba45c8438fca7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,8 @@ jobs: node-version: ${{ steps.var.outputs.node-version }} deno-version: ${{ steps.var.outputs.deno-version }} source-hash: ${{ steps.source.outputs.hash }} + packages-build-cache-key: ${{ steps.ci-cache-keys.outputs.packages-build-cache-key }} + meteor-rc-cache-key: ${{ steps.ci-cache-keys.outputs.meteor-rc-cache-key }} # this is 100% intentional, secrets are not available for forks, so ee-tests will always fail # to avoid this, we are using a dummy license, expiring at 2026-07-01 enterprise-license: Uo7Jcr6WW0XYA8ydHd+Sk6pZ9/0V6dIASnyTwvUrNym/zJg2Ma3eYNKkC8osXLCc72y1ahohnWY7/+7IYkvono3GYXQR+IGvYbbrVgNR6OjMahd9P/odHZL1GFTm2qHrEL5Hh/XEOG+YluFeRdWPzCizQlp4zGGOi0+PkQo096TR9NVCLrsErVl2MW1WM6ZM1W5EUJG9pKly4BQnaOTUAlor1im6i8qPTDCKrISZfLiZEWuQKaPW/GE3mRKjQNjDh0CabX1N2S880pRRGoozBYAnp2NmFfrQW0+5ihKisBTIeMbMZ7K5NE5PkYU1nhQDcc+rpDHtwG9Ceg5X0J+oea3UfrPTmDON2aSI0iO22kvL6G7QI3fyrEIvJrMbxcNKxAFeQYgnjisw/b06+chWSG4jG686Fx58XrVS87dFhWL9WoGltsk1dJCntUQvI1sX6zOfpvyg1iWRnHfYDOrwoWlX57XMm29fWineEoqnOOTOVnA/uP+DKEhercQ9Xuo7Cr6zJxpQpwd03e7ODVjiEbTDqlkZE687rmxRCD4Wmu8L86WIl2xSEIajKLX301Ww5mz/FdLqk+Mg32lkW66W3azQKvJ1440NBrYxhpJ+dl9vSFMb3s1+xnz1cYUbjUcq9mARvORcgy5mLwKulmqT6Sq0Uvbv10YCO0TW0beXYW8= @@ -91,6 +93,14 @@ jobs: echo "DENO_VERSION: ${DENO_VERSION}" echo "deno-version=${DENO_VERSION}" >> $GITHUB_OUTPUT + - id: ci-cache-keys + run: | + set -euo pipefail + PACKAGES_HASH=$(cat yarn.lock .yarnrc.yml package.json turbo.json | sha256sum | awk '{print $1}') + echo "packages-build-cache-key=${PACKAGES_HASH}" >> "$GITHUB_OUTPUT" + METEOR_HASH=$(git archive HEAD apps/meteor | sha256sum | awk '{print $1}') + echo "meteor-rc-cache-key=${METEOR_HASH}" >> "$GITHUB_OUTPUT" + - id: by-tag run: | if echo "$GITHUB_REF_NAME" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' ; then @@ -175,10 +185,13 @@ jobs: with: path: | /tmp/RocketChat-packages-build.tar.gz - key: ${{ runner.arch }}-${{ runner.os }}-packages-build-${{ needs.release-versions.outputs.source-hash }} + key: ${{ runner.arch }}-${{ runner.os }}-packages-build-${{ needs.release-versions.outputs.packages-build-cache-key }} - - name: Debug cache-hit - run: echo "cache-hit=${{ steps.packages-cache-build.outputs.cache-hit }}" + - name: Cache observability (packages-build) + run: | + echo "### 📦 packages-build cache" >> $GITHUB_STEP_SUMMARY + echo "- **hit**: \`${{ steps.packages-cache-build.outputs.cache-hit }}\`" >> $GITHUB_STEP_SUMMARY + echo "- **key**: \`${{ needs.release-versions.outputs.packages-build-cache-key }}\`" >> $GITHUB_STEP_SUMMARY - name: Set Swap Space uses: pierotofy/set-swap-space@master @@ -190,6 +203,7 @@ jobs: if: steps.packages-cache-build.outputs.cache-hit != 'true' - name: Setup NodeJS + id: setup-node-packages uses: ./.github/actions/setup-node if: steps.packages-cache-build.outputs.cache-hit != 'true' with: @@ -200,6 +214,13 @@ jobs: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} HARDENED_MODE: '1' + - name: Cache observability (node_modules) + if: steps.packages-cache-build.outputs.cache-hit != 'true' + run: | + echo "### 🟢 node_modules cache" >> $GITHUB_STEP_SUMMARY + echo "- **deno cache hit**: \`${{ steps.setup-node-packages.outputs.cache-deno-hit }}\`" >> $GITHUB_STEP_SUMMARY + echo "- **node_modules size**: \`$(du -sh node_modules 2>/dev/null | cut -f1 || echo 'n/a')\`" >> $GITHUB_STEP_SUMMARY + - name: Cache vite uses: actions/cache@v5 if: steps.packages-cache-build.outputs.cache-hit != 'true' @@ -259,7 +280,7 @@ jobs: with: node-version: ${{ needs.release-versions.outputs.node-version }} deno-version: ${{ needs.release-versions.outputs.deno-version }} - source-hash: ${{ needs.release-versions.outputs.source-hash }} + source-hash: ${{ needs.release-versions.outputs.packages-build-cache-key }}-${{ needs.release-versions.outputs.meteor-rc-cache-key }} type: ${{ matrix.type }} build-gh-docker: From bb97a680df8c2c4e257046bbdca511709765f4ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 19:56:03 -0300 Subject: [PATCH 28/51] chore(deps): bump actions/setup-node from 6.2.0 to 6.3.0 (#39319) --- .github/workflows/ci.yml | 2 +- .github/workflows/update-version-durability.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba45c8438fca7..de9ce193193a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -735,7 +735,7 @@ jobs: - uses: actions/checkout@v6 - name: Use Node.js - uses: actions/setup-node@v6.2.0 + uses: actions/setup-node@v6.3.0 with: node-version: ${{ needs.release-versions.outputs.node-version }} diff --git a/.github/workflows/update-version-durability.yml b/.github/workflows/update-version-durability.yml index 46f9fbb0c3b0e..c2e0d93cc85db 100644 --- a/.github/workflows/update-version-durability.yml +++ b/.github/workflows/update-version-durability.yml @@ -21,7 +21,7 @@ jobs: - uses: actions/checkout@v6 - name: Use Node.js - uses: actions/setup-node@v6.2.0 + uses: actions/setup-node@v6.3.0 with: node-version: 22.16.0 From df43b7957a69d850f3665615d105480b526c2476 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 19:56:29 -0300 Subject: [PATCH 29/51] chore(deps): bump docker/login-action from 3 to 4 (#39355) --- .github/workflows/ci-test-e2e.yml | 2 +- .github/workflows/ci.yml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-test-e2e.yml b/.github/workflows/ci-test-e2e.yml index 99395082a9fbc..23ddeef27dd12 100644 --- a/.github/workflows/ci-test-e2e.yml +++ b/.github/workflows/ci-test-e2e.yml @@ -106,7 +106,7 @@ jobs: - name: Login to GitHub Container Registry if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') && github.actor != 'dependabot[bot]' - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ secrets.CR_USER }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de9ce193193a7..cd9905e87084a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -400,7 +400,7 @@ jobs: - name: Login to GitHub Container Registry if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ secrets.CR_USER }} @@ -661,7 +661,7 @@ jobs: - name: Login to GitHub Container Registry if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') && github.actor != 'dependabot[bot]' - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ secrets.CR_USER }} @@ -896,13 +896,13 @@ jobs: ref: ${{ github.ref }} - name: Login to DockerHub - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASS }} - name: Login to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ secrets.CR_USER }} From 25e988b2e339c3757184c2e2c37d1de8a948b2f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 23:02:59 -0300 Subject: [PATCH 30/51] chore(deps): bump codecov/codecov-action from 5 to 6 (#39895) --- .github/workflows/ci-test-storybook.yml | 2 +- .github/workflows/ci-test-unit.yml | 2 +- .github/workflows/ci.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-test-storybook.yml b/.github/workflows/ci-test-storybook.yml index c1adfc760e170..3f0ab5b9e1255 100644 --- a/.github/workflows/ci-test-storybook.yml +++ b/.github/workflows/ci-test-storybook.yml @@ -46,7 +46,7 @@ jobs: env: STORYBOOK_DISABLE_TELEMETRY: 1 - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@v6 with: flags: unit verbose: true diff --git a/.github/workflows/ci-test-unit.yml b/.github/workflows/ci-test-unit.yml index 56184ff08aff2..61323ecd4546d 100644 --- a/.github/workflows/ci-test-unit.yml +++ b/.github/workflows/ci-test-unit.yml @@ -46,7 +46,7 @@ jobs: - name: Unit Test run: yarn testunit --concurrency=1 - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@v6 with: flags: unit verbose: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd9905e87084a..1dcde726f5941 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -761,7 +761,7 @@ jobs: include-hidden-files: true - name: Report API coverage - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: files: /tmp/coverage_report/api/lcov.info working-directory: . @@ -770,7 +770,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} - name: Report UI coverage - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: files: /tmp/coverage_report/ui/lcov.info working-directory: . From 2cebe41eab04bb5edc87b2669c543ed4fc33921b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 23:13:35 -0300 Subject: [PATCH 31/51] chore(deps): bump @xmldom/xmldom from 0.8.10 to 0.8.12 in /.github/actions/update-version-durability (#40016) --- .github/actions/update-version-durability/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/update-version-durability/package-lock.json b/.github/actions/update-version-durability/package-lock.json index 5ac99a59a922a..258b8fb97217b 100644 --- a/.github/actions/update-version-durability/package-lock.json +++ b/.github/actions/update-version-durability/package-lock.json @@ -194,9 +194,9 @@ } }, "node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.12.tgz", + "integrity": "sha512-9k/gHF6n/pAi/9tqr3m3aqkuiNosYTurLLUtc7xQ9sxB/wm7WPygCv8GYa6mS0fLJEHhqMC1ATYhz++U/lRHqg==", "license": "MIT", "engines": { "node": ">=10.0.0" From f21ed3a749a6e69560dbf6990e2e3da768a84a17 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Wed, 8 Apr 2026 15:25:32 -0300 Subject: [PATCH 32/51] fix: require unban before using inviting link (#40087) --- .../server/functions/useInviteToken.ts | 11 +- apps/meteor/tests/end-to-end/api/invites.ts | 67 +++++++++- apps/meteor/tests/end-to-end/api/rooms.ts | 126 ------------------ docs/features/ban-user.md | 39 +++++- 4 files changed, 105 insertions(+), 138 deletions(-) diff --git a/apps/meteor/app/invites/server/functions/useInviteToken.ts b/apps/meteor/app/invites/server/functions/useInviteToken.ts index f514736da590c..10ccd147d5b98 100644 --- a/apps/meteor/app/invites/server/functions/useInviteToken.ts +++ b/apps/meteor/app/invites/server/functions/useInviteToken.ts @@ -1,3 +1,4 @@ +import { isBannedSubscription } from '@rocket.chat/core-typings'; import { Invites, Subscriptions, Users } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; @@ -37,11 +38,15 @@ export const useInviteToken = async (userId: string, token: string) => { field: 'userId', }); } + const subscription = await Subscriptions.findOneByRoomIdAndUserId(room._id, user._id); + if (subscription && isBannedSubscription(subscription)) { + throw new Meteor.Error('error-user-is-banned', 'User is banned from this room', { + method: 'useInviteToken', + }); + } + await Users.updateInviteToken(user._id, token); - const subscription = await Subscriptions.findOneByRoomIdAndUserId(room._id, user._id, { - projection: { _id: 1 }, - }); if (!subscription) { await Invites.increaseUsageById(inviteData._id, 1); } diff --git a/apps/meteor/tests/end-to-end/api/invites.ts b/apps/meteor/tests/end-to-end/api/invites.ts index 85f0771f67d13..9ae8163134e8e 100644 --- a/apps/meteor/tests/end-to-end/api/invites.ts +++ b/apps/meteor/tests/end-to-end/api/invites.ts @@ -1,8 +1,13 @@ -import type { IInvite } from '@rocket.chat/core-typings'; +import type { Credentials } from '@rocket.chat/api-client'; +import type { IInvite, IRoom, IUser } from '@rocket.chat/core-typings'; import { expect } from 'chai'; -import { before, describe, it } from 'mocha'; +import { after, before, describe, it } from 'mocha'; import { getCredentials, api, request, credentials } from '../../data/api-data'; +import { createRoom, deleteRoom } from '../../data/rooms.helper'; +import { password } from '../../data/user'; +import type { TestUser } from '../../data/users.helper'; +import { createUser, deleteUser, login } from '../../data/users.helper'; describe('Invites', () => { let testInviteID: IInvite['_id']; @@ -195,6 +200,64 @@ describe('Invites', () => { }); }); + describe('POST [/useInviteToken] - banned user', () => { + let room: IRoom; + let bannedUser: TestUser; + let bannedUserCredentials: Credentials; + let inviteId: IInvite['_id']; + + before(async () => { + bannedUser = await createUser(); + bannedUserCredentials = await login(bannedUser.username, password); + + const result = await createRoom({ type: 'p', name: `invite-ban-test-${Date.now()}` }); + room = result.body.group; + + // Add user then ban them + await request.post(api('groups.invite')).set(credentials).send({ roomId: room._id, userId: bannedUser._id }).expect(200); + await request.post(api('rooms.banUser')).set(credentials).send({ roomId: room._id, userId: bannedUser._id }).expect(200); + + // Create invite link for the room + const invite = await request + .post(api('findOrCreateInvite')) + .set(credentials) + .send({ rid: room._id, days: 1, maxUses: 10 }) + .expect(200); + inviteId = invite.body._id; + }); + + after(async () => { + await deleteRoom({ type: 'p', roomId: room._id }); + await deleteUser(bannedUser); + }); + + it('should fail if user is banned from the room', async () => { + await request + .post(api('useInviteToken')) + .set(bannedUserCredentials) + .send({ token: inviteId }) + .expect(400) + .expect((res) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('errorType', 'error-user-is-banned'); + }); + }); + + it('should succeed after the user is unbanned', async () => { + await request.post(api('rooms.unbanUser')).set(credentials).send({ roomId: room._id, userId: bannedUser._id }).expect(200); + + await request + .post(api('useInviteToken')) + .set(bannedUserCredentials) + .send({ token: inviteId }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('room').and.to.have.property('rid', room._id); + }); + }); + }); + describe('DELETE [/removeInvite]', () => { it('should fail if not logged in', (done) => { void request diff --git a/apps/meteor/tests/end-to-end/api/rooms.ts b/apps/meteor/tests/end-to-end/api/rooms.ts index 0b8ca498a6a8f..96d9385569030 100644 --- a/apps/meteor/tests/end-to-end/api/rooms.ts +++ b/apps/meteor/tests/end-to-end/api/rooms.ts @@ -4628,130 +4628,4 @@ describe('[Rooms]', () => { }); }); }); - - describe('Re-inviting a banned user should preserve other subscriptions', () => { - let privateChannel: IRoom; - let otherChannel1: IRoom; - let otherChannel2: IRoom; - let userB: TestUser; - let userBCredentials: Credentials; - - before(async () => { - userB = await createUser(); - userBCredentials = await login(userB.username, password); - - // Create the private channel (owned by admin / User A) - const result = await createRoom({ type: 'p', name: `ban-reinvite-test-${Date.now()}` }); - privateChannel = result.body.group; - - // Create two additional channels that User B will be a member of - const ch1 = await createRoom({ type: 'c', name: `other-ch1-${Date.now()}` }); - otherChannel1 = ch1.body.channel; - - const ch2 = await createRoom({ type: 'c', name: `other-ch2-${Date.now()}` }); - otherChannel2 = ch2.body.channel; - - // Add User B to all three channels - await request.post(api('groups.invite')).set(credentials).send({ roomId: privateChannel._id, userId: userB._id }).expect(200); - await request.post(api('channels.invite')).set(credentials).send({ roomId: otherChannel1._id, userId: userB._id }).expect(200); - await request.post(api('channels.invite')).set(credentials).send({ roomId: otherChannel2._id, userId: userB._id }).expect(200); - }); - - after(async () => { - await deleteRoom({ type: 'p', roomId: privateChannel._id }); - await deleteRoom({ type: 'c', roomId: otherChannel1._id }); - await deleteRoom({ type: 'c', roomId: otherChannel2._id }); - await deleteUser(userB); - }); - - it('should confirm User B is a member of all three channels', async () => { - const res = await request.get(api('subscriptions.get')).set(userBCredentials).expect(200); - expect(res.body).to.have.property('success', true); - - const roomIds = res.body.update.map((sub: { rid: string }) => sub.rid); - expect(roomIds).to.include(privateChannel._id); - expect(roomIds).to.include(otherChannel1._id); - expect(roomIds).to.include(otherChannel2._id); - }); - - it('should ban User B from the private channel', async () => { - await request - .post(api('rooms.banUser')) - .set(credentials) - .send({ - roomId: privateChannel._id, - userId: userB._id, - }) - .expect('Content-Type', 'application/json') - .expect(200) - .expect((res) => { - expect(res.body).to.have.property('success', true); - }); - }); - - it('should still have User B subscribed to the other channels after being banned', async () => { - const res = await request.get(api('subscriptions.get')).set(userBCredentials).expect(200); - expect(res.body).to.have.property('success', true); - - const roomIds = res.body.update.map((sub: { rid: string }) => sub.rid); - expect(roomIds).to.include(otherChannel1._id); - expect(roomIds).to.include(otherChannel2._id); - expect(roomIds).to.not.include(privateChannel._id); - }); - - it('should re-invite banned User B back to the private channel', async () => { - await request - .post(api('groups.invite')) - .set(credentials) - .send({ - roomId: privateChannel._id, - userId: userB._id, - }) - .expect('Content-Type', 'application/json') - .expect(200) - .expect((res) => { - expect(res.body).to.have.property('success', true); - }); - }); - - it('should list User B as a member of the private channel again', async () => { - const res = await request - .get(api('groups.members')) - .set(credentials) - .query({ - roomId: privateChannel._id, - }) - .expect('Content-Type', 'application/json') - .expect(200); - - expect(res.body).to.have.property('success', true); - const usernames = res.body.members.map((m: IUser) => m.username); - expect(usernames).to.include(userB.username); - }); - - it('should no longer list User B as banned', async () => { - const res = await request - .get(api('rooms.bannedUsers')) - .set(credentials) - .query({ - roomId: privateChannel._id, - }) - .expect('Content-Type', 'application/json') - .expect(200); - - expect(res.body).to.have.property('success', true); - const userIds = res.body.bannedUsers.map((u: IUser) => u._id); - expect(userIds).to.not.include(userB._id); - }); - - it('should preserve all other channel subscriptions after re-invite', async () => { - const res = await request.get(api('subscriptions.get')).set(userBCredentials).expect(200); - expect(res.body).to.have.property('success', true); - - const roomIds = res.body.update.map((sub: { rid: string }) => sub.rid); - expect(roomIds).to.include(privateChannel._id, 'User B should be re-subscribed to the private channel'); - expect(roomIds).to.include(otherChannel1._id, 'User B should still be subscribed to otherChannel1'); - expect(roomIds).to.include(otherChannel2._id, 'User B should still be subscribed to otherChannel2'); - }); - }); }); diff --git a/docs/features/ban-user.md b/docs/features/ban-user.md index 10e5037b01f54..1515b489dd696 100644 --- a/docs/features/ban-user.md +++ b/docs/features/ban-user.md @@ -34,14 +34,39 @@ Banning prevents a user from participating in a specific room. Unlike kicking (w **Important:** after unban the user **does not become a member** of the room again. The banned subscription is deleted. The user must be invited or join again. -## Re-entry After Unban +## Join / Invite / Re-entry Behavior -In `addUserToRoom`, if the user being added has a subscription with `status: 'BANNED'`: -- Removes the banned subscription. -- Saves a `user-unbanned` system message. -- Creates a new subscription normally. +A banned user **cannot** re-enter the room through any path. The ban must be explicitly lifted first. Below is how each entry point enforces this for both normal and federated rooms. -This means inviting/adding a banned user automatically unbans them. +### Invite via API / UI (`groups.invite`, `channels.invite`, "Add Users") + +`addUsersToRoom` checks for a `BANNED` subscription before calling `addUserToRoom`: +- Returns `error-user-is-banned` — the invite is rejected. +- The UI shows a warning modal asking the admin to unban first. +- Applies equally to normal and federated rooms (the check is in the method layer, before the room-type branch). + +### Invite link (`useInviteToken`) + +`useInviteToken` checks for a `BANNED` subscription before saving the invite token or calling `addUserToRoom`: +- Returns `error-user-is-banned` — the token is not consumed. +- Because the check runs before `Users.updateInviteToken`, the secondary path through `setUsername` (for users who register via invite link) is also blocked. + +### Direct join (`channels.join`, `joinRoom`) + +`Room.join` calls `canAccessRoom` before `addUserToRoom`: +- For **public rooms** and **public rooms inside teams**, the `canAccessRoom` validators explicitly check `findOneBannedSubscription` and deny access. +- For **private rooms**, `countByRoomIdAndUserId` excludes `BANNED` subscriptions (`status: { $exists: false }`), so the "already joined" validator returns false and access is denied. + +### Federation invite events + +When a Matrix homeserver sends an invite for a user who is banned locally: +- `handleInvite` in `federation-matrix/src/events/member.ts` finds the existing (banned) subscription and returns early without creating a new one. +- The user never receives an `INVITED` subscription, so `handleJoin` is never reached. + +### Expected flow + +1. **Unban** the user via `POST /v1/rooms.unbanUser`, `/unban @username`, or the "Banned Users" contextual bar. This deletes the banned subscription. +2. **Invite or join** — the user can now be invited (API, UI, invite link) or join (public rooms) normally. ## Access Control @@ -49,7 +74,7 @@ The `canAccessRoom` validators check for bans in two public room scenarios: - **Public rooms inside teams** — if banned, access is denied. - **Regular public rooms** — if banned, access is denied. -For private rooms, access is already controlled by the subscription (which is marked as `BANNED`). +For private rooms, access is controlled by the subscription: `countByRoomIdAndUserId` excludes `BANNED` subscriptions, so a banned user has no valid subscription and cannot access the room. ## UI From 46faa43d5ed17e08e0302756fd344d555f6e26e6 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Wed, 8 Apr 2026 17:03:18 -0300 Subject: [PATCH 33/51] chore: update Meteor and package versions to latest stable releases 3.4 (#38614) Co-authored-by: Kevin Aleman --- .github/actions/build-docker/action.yml | 2 -- apps/meteor/.meteor/packages | 19 ++++++------- apps/meteor/.meteor/release | 2 +- apps/meteor/.meteor/versions | 28 +++++++++---------- .../server/lib/validateOutgoingIntegration.ts | 9 ++++-- .../incoming/addIncomingIntegration.ts | 14 +++++++--- .../incoming/updateIncomingIntegration.ts | 15 ++++++---- apps/meteor/package.json | 5 ++-- yarn.lock | 8 ++++++ 9 files changed, 61 insertions(+), 41 deletions(-) diff --git a/.github/actions/build-docker/action.yml b/.github/actions/build-docker/action.yml index 1bc8542e20464..a11733027bae5 100644 --- a/.github/actions/build-docker/action.yml +++ b/.github/actions/build-docker/action.yml @@ -82,8 +82,6 @@ runs: swc_arch='arm64' fi - find /tmp/build/bundle/programs/server/npm/node_modules/meteor/babel-compiler/node_modules/@meteorjs/swc-core/.swc/node_modules/@swc -type d -name 'core-*' -not -name "*linux-${swc_arch}-gnu*" -exec rm -rf {} + - find /tmp/build/bundle/programs/server/npm/node_modules/@img -type d -name 'sharp-*' -not -name "*-linuxmusl-${swc_arch}" -exec rm -rf {} + find /tmp/build/bundle/programs/server/npm/node_modules/@napi-rs -type d -name 'pinyin-linux-*' -not -name "*-linux-${swc_arch}-*" -exec rm -rf {} + diff --git a/apps/meteor/.meteor/packages b/apps/meteor/.meteor/packages index 0b6c97b193712..757831b7a1bea 100644 --- a/apps/meteor/.meteor/packages +++ b/apps/meteor/.meteor/packages @@ -7,33 +7,33 @@ rocketchat:mongo-config rocketchat:livechat rocketchat:version -accounts-base@3.1.2 +accounts-base@3.2.0 accounts-facebook@1.3.4 accounts-google@1.4.1 accounts-meteor-developer@1.5.1 accounts-oauth@1.4.6 -accounts-password@3.2.1 +accounts-password@3.2.2 accounts-twitter@1.5.2 google-oauth@1.4.5 oauth@3.0.2 oauth2@1.3.3 -check@1.4.4 +check@1.5.0 ddp-rate-limiter@1.2.2 rate-limit@1.1.2 email@3.1.2 meteor-base@1.5.2 ddp-common@1.4.4 -webapp@2.0.7 +webapp@2.1.0 -mongo@2.1.4 +mongo@2.2.0 reload@1.3.2 service-configuration@1.3.5 session@1.2.2 -shell-server@0.6.2 +shell-server@0.7.0 dispatch:run-as-user ostrio:cookies @@ -50,11 +50,10 @@ tracker@1.3.4 reactive-dict@1.3.2 reactive-var@1.0.13 -babel-compiler@7.12.2 -standard-minifier-css@1.9.3 +standard-minifier-css@1.10.0 dynamic-import@0.7.4 -ecmascript@0.16.13 -typescript@5.6.6 +ecmascript@0.17.0 +typescript@5.9.3 autoupdate@2.0.1 diff --git a/apps/meteor/.meteor/release b/apps/meteor/.meteor/release index 4876d6ff64c16..703a72252657a 100644 --- a/apps/meteor/.meteor/release +++ b/apps/meteor/.meteor/release @@ -1 +1 @@ -METEOR@3.3.2 +METEOR@3.4 diff --git a/apps/meteor/.meteor/versions b/apps/meteor/.meteor/versions index 91adcc4d4e5f2..d83c4802bcf32 100644 --- a/apps/meteor/.meteor/versions +++ b/apps/meteor/.meteor/versions @@ -1,19 +1,19 @@ -accounts-base@3.1.2 +accounts-base@3.2.0 accounts-facebook@1.3.4 accounts-google@1.4.1 accounts-meteor-developer@1.5.1 accounts-oauth@1.4.6 -accounts-password@3.2.1 +accounts-password@3.2.2 accounts-twitter@1.5.2 allow-deny@2.1.0 autoupdate@2.0.1 -babel-compiler@7.12.2 +babel-compiler@7.13.0 babel-runtime@1.5.2 base64@1.0.13 binary-heap@1.0.12 -boilerplate-generator@2.0.2 +boilerplate-generator@2.1.0 callback-hook@1.6.1 -check@1.4.4 +check@1.5.0 core-runtime@1.0.0 ddp@1.4.2 ddp-client@3.1.1 @@ -23,7 +23,7 @@ ddp-server@3.1.2 diff-sequence@1.1.3 dispatch:run-as-user@1.1.1 dynamic-import@0.7.4 -ecmascript@0.16.13 +ecmascript@0.17.0 ecmascript-runtime@0.8.3 ecmascript-runtime-client@0.12.3 ecmascript-runtime-server@0.11.1 @@ -41,16 +41,16 @@ id-map@1.2.0 inter-process-messaging@0.1.2 localstorage@1.2.1 logging@1.3.6 -meteor@2.1.1 +meteor@2.2.0 meteor-base@1.5.2 meteor-developer-oauth@1.3.3 meteorhacks:inject-initial@1.0.5 minifier-css@2.0.1 -minimongo@2.0.4 +minimongo@2.0.5 modern-browsers@0.2.3 modules@0.20.3 modules-runtime@0.13.2 -mongo@2.1.4 +mongo@2.2.0 mongo-decimal@0.2.0 mongo-dev-server@1.1.1 mongo-id@1.0.9 @@ -63,7 +63,7 @@ ostrio:cookies@2.7.2 promise@1.0.0 random@1.2.2 rate-limit@1.1.2 -react-fast-refresh@0.2.9 +react-fast-refresh@0.3.0 reactive-dict@1.3.2 reactive-var@1.0.13 reload@1.3.2 @@ -75,15 +75,15 @@ routepolicy@1.1.2 service-configuration@1.3.5 session@1.2.2 sha@1.0.10 -shell-server@0.6.2 +shell-server@0.7.0 socket-stream-client@0.6.1 -standard-minifier-css@1.9.3 +standard-minifier-css@1.10.0 tracker@1.3.4 twitter-oauth@1.3.4 -typescript@5.6.6 +typescript@5.9.3 underscore@1.6.4 url@1.3.5 -webapp@2.0.7 +webapp@2.1.0 webapp-hashing@1.1.2 zodern:caching-minifier@0.5.0 zodern:standard-minifier-js@5.3.1 diff --git a/apps/meteor/app/integrations/server/lib/validateOutgoingIntegration.ts b/apps/meteor/app/integrations/server/lib/validateOutgoingIntegration.ts index fabe8cae7688d..d4b1a68af5796 100644 --- a/apps/meteor/app/integrations/server/lib/validateOutgoingIntegration.ts +++ b/apps/meteor/app/integrations/server/lib/validateOutgoingIntegration.ts @@ -1,7 +1,8 @@ +import { transformSync } from '@babel/core'; +import presetEnv from '@babel/preset-env'; import type { IUser, INewOutgoingIntegration, IOutgoingIntegration, IUpdateOutgoingIntegration } from '@rocket.chat/core-typings'; import { Subscriptions, Users, Rooms } from '@rocket.chat/models'; import { pick } from '@rocket.chat/tools'; -import { Babel } from 'meteor/babel-compiler'; import { Match } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -179,13 +180,15 @@ export const validateOutgoingIntegration = async function ( integration.script.trim() !== '' ) { try { - const babelOptions = Object.assign(Babel.getDefaultOptions({ runtime: false }), { + const result = transformSync(integration.script, { + presets: [presetEnv], compact: true, minified: true, comments: false, }); - integrationData.scriptCompiled = Babel.compile(integration.script, babelOptions).code; + // TODO: Webhook Integration Editor should inform the user if the script is compiled successfully + integrationData.scriptCompiled = result?.code ?? undefined; integrationData.scriptError = undefined; } catch (e) { integrationData.scriptCompiled = undefined; diff --git a/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts b/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts index a64e0c40c7afe..3a7a48835a427 100644 --- a/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts +++ b/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts @@ -1,9 +1,10 @@ +import { transformSync } from '@babel/core'; +import presetEnv from '@babel/preset-env'; import type { INewIncomingIntegration, IIncomingIntegration } from '@rocket.chat/core-typings'; import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Integrations, Subscriptions, Users, Rooms } from '@rocket.chat/models'; import { Random } from '@rocket.chat/random'; import { removeEmpty } from '@rocket.chat/tools'; -import { Babel } from 'meteor/babel-compiler'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import _ from 'underscore'; @@ -111,10 +112,15 @@ export const addIncomingIntegration = async (userId: string, integration: INewIn integration.script.trim() !== '' ) { try { - let babelOptions = Babel.getDefaultOptions({ runtime: false }); - babelOptions = _.extend(babelOptions, { compact: true, minified: true, comments: false }); + const result = transformSync(integration.script, { + presets: [presetEnv], + compact: true, + minified: true, + comments: false, + }); - integrationData.scriptCompiled = Babel.compile(integration.script, babelOptions).code; + // TODO: Webhook Integration Editor should inform the user if the script is compiled successfully + integrationData.scriptCompiled = result?.code ?? undefined; delete integrationData.scriptError; } catch (e) { integrationData.scriptCompiled = undefined; diff --git a/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts b/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts index 9e63ce5473b86..5ce2ffd4496aa 100644 --- a/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts +++ b/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts @@ -1,10 +1,10 @@ +import { transformSync } from '@babel/core'; +import presetEnv from '@babel/preset-env'; import type { IIntegration, INewIncomingIntegration, IUpdateIncomingIntegration } from '@rocket.chat/core-typings'; import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Integrations, Subscriptions, Users, Rooms } from '@rocket.chat/models'; import { wrapExceptions } from '@rocket.chat/tools'; -import { Babel } from 'meteor/babel-compiler'; import { Meteor } from 'meteor/meteor'; -import _ from 'underscore'; import { addUserRolesAsync } from '../../../../../server/lib/roles/addUserRoles'; import { hasAllPermissionAsync, hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission'; @@ -90,10 +90,15 @@ export const updateIncomingIntegration = async ( if (integration.scriptEnabled === true && integration.script && integration.script.trim() !== '') { try { - let babelOptions = Babel.getDefaultOptions({ runtime: false }); - babelOptions = _.extend(babelOptions, { compact: true, minified: true, comments: false }); + const result = transformSync(integration.script, { + presets: [presetEnv], + compact: true, + minified: true, + comments: false, + }); - scriptCompiled = Babel.compile(integration.script, babelOptions).code; + // TODO: Webhook Integration Editor should inform the user if the script is compiled successfully + scriptCompiled = result?.code ?? undefined; scriptError = undefined; await Integrations.updateOne( { _id: integrationId }, diff --git a/apps/meteor/package.json b/apps/meteor/package.json index d63d46525d7ca..dd6e41fc9507e 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -69,6 +69,8 @@ "@aws-sdk/client-s3": "^3.862.0", "@aws-sdk/lib-storage": "^3.862.0", "@aws-sdk/s3-request-presigner": "^3.862.0", + "@babel/core": "~7.28.6", + "@babel/preset-env": "~7.28.6", "@babel/runtime": "~7.28.6", "@bugsnag/js": "~7.20.2", "@bugsnag/plugin-react": "~7.19.0", @@ -311,8 +313,6 @@ }, "devDependencies": { "@axe-core/playwright": "^4.10.2", - "@babel/core": "~7.28.6", - "@babel/preset-env": "~7.28.6", "@babel/preset-react": "~7.27.1", "@babel/register": "~7.28.6", "@faker-js/faker": "~8.0.2", @@ -334,6 +334,7 @@ "@testing-library/user-event": "~14.6.1", "@types/adm-zip": "^0.5.7", "@types/archiver": "~6.0.4", + "@types/babel__preset-env": "^7.10.0", "@types/bad-words": "^3.0.3", "@types/bcrypt": "^5.0.2", "@types/body-parser": "^1.19.6", diff --git a/yarn.lock b/yarn.lock index ec5fe2c9f0bca..9b050044d52e7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10071,6 +10071,7 @@ __metadata: "@testing-library/user-event": "npm:~14.6.1" "@types/adm-zip": "npm:^0.5.7" "@types/archiver": "npm:~6.0.4" + "@types/babel__preset-env": "npm:^7.10.0" "@types/bad-words": "npm:^3.0.3" "@types/bcrypt": "npm:^5.0.2" "@types/body-parser": "npm:^1.19.6" @@ -13703,6 +13704,13 @@ __metadata: languageName: node linkType: hard +"@types/babel__preset-env@npm:^7.10.0": + version: 7.10.0 + resolution: "@types/babel__preset-env@npm:7.10.0" + checksum: 10/7d4d12758d89708afe327079d7d7580e8af3292295f087b8a9a48e12ac1d90aadc18ac3bc00f9b0cbc8778f3ce9fe778801d4d49b7691a75e3f13a901b69fd07 + languageName: node + linkType: hard + "@types/babel__template@npm:*": version: 7.4.1 resolution: "@types/babel__template@npm:7.4.1" From c7744b1c3e35a623d7d26be41ae0b3d767afeaef Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:48:06 -0300 Subject: [PATCH 34/51] feat: auto-wrap selected text in composer with matching delimiters (#39393) Co-authored-by: Guilherme Gazzo --- .changeset/warm-cups-dress.md | 5 ++ .../client/messageBox/createComposerAPI.ts | 14 ++++- apps/meteor/client/lib/chats/ChatAPI.ts | 6 +- .../room/composer/messageBox/MessageBox.tsx | 18 +++++- .../room/composer/messageBox/wrapSelection.ts | 58 +++++++++++++++++++ 5 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 .changeset/warm-cups-dress.md create mode 100644 apps/meteor/client/views/room/composer/messageBox/wrapSelection.ts diff --git a/.changeset/warm-cups-dress.md b/.changeset/warm-cups-dress.md new file mode 100644 index 0000000000000..ade4599a2c928 --- /dev/null +++ b/.changeset/warm-cups-dress.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': minor +--- + +Added auto-wrap selected text in composer with matching delimiters diff --git a/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts b/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts index 876a4bea7f0f8..4922bc150d3e6 100644 --- a/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts +++ b/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts @@ -224,7 +224,7 @@ export const createComposerAPI = ( stopFormatterTracker.stop(); }; - const wrapSelection = (pattern: string): void => { + const wrapSelection = (pattern: string): { selectionStart: number; selectionEnd: number; value: string } => { const { selectionEnd = input.value.length, selectionStart = 0 } = input; const initText = input.value.slice(0, selectionStart); const selectedText = input.value.slice(selectionStart, selectionEnd); @@ -254,7 +254,11 @@ export const createComposerAPI = ( triggerEvent(input, 'change'); focus(); - return; + return { + selectionStart: input.selectionStart, + selectionEnd: input.selectionEnd, + value: input.value, + }; } } @@ -268,6 +272,12 @@ export const createComposerAPI = ( triggerEvent(input, 'change'); focus(); + + return { + selectionStart: input.selectionStart, + selectionEnd: input.selectionEnd, + value: input.value, + }; }; const insertNewLine = (): void => insertText('\n'); diff --git a/apps/meteor/client/lib/chats/ChatAPI.ts b/apps/meteor/client/lib/chats/ChatAPI.ts index b7155a71cd3e5..633b819b355ad 100644 --- a/apps/meteor/client/lib/chats/ChatAPI.ts +++ b/apps/meteor/client/lib/chats/ChatAPI.ts @@ -23,7 +23,11 @@ export type ComposerAPI = { | ((previous: { readonly start: number; readonly end: number }) => { readonly start?: number; readonly end?: number }); }, ): void; - wrapSelection(pattern: string): void; + wrapSelection(pattern: string): { + selectionStart: number; + selectionEnd: number; + value: string; + }; insertText(text: string): void; insertNewLine(): void; clear(): void; diff --git a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx index 82ba2a17a6231..c653b0a132e55 100644 --- a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx +++ b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx @@ -21,11 +21,13 @@ import MessageBoxFormattingToolbar from './MessageBoxFormattingToolbar'; import MessageBoxHint from './MessageBoxHint'; import MessageBoxReplies from './MessageBoxReplies'; import MessageComposerFiles from './MessageComposerFiles'; +import { handleSelectionWrapping } from './wrapSelection'; import { createComposerAPI } from '../../../../../app/ui-message/client/messageBox/createComposerAPI'; import type { FormattingButton } from '../../../../../app/ui-message/client/messageBox/messageBoxFormatting'; import { formattingButtons } from '../../../../../app/ui-message/client/messageBox/messageBoxFormatting'; import { getImageExtensionFromMime } from '../../../../../lib/getImageExtensionFromMime'; import { useFormatDateAndTime } from '../../../../hooks/useFormatDateAndTime'; +import { useIsFederationEnabled } from '../../../../hooks/useIsFederationEnabled'; import { useReactiveValue } from '../../../../hooks/useReactiveValue'; import type { ComposerAPI } from '../../../../lib/chats/ChatAPI'; import { roomCoordinator } from '../../../../lib/rooms/roomCoordinator'; @@ -45,7 +47,6 @@ import { useEnablePopupPreview } from '../hooks/useEnablePopupPreview'; import { useMessageComposerMergedRefs } from '../hooks/useMessageComposerMergedRefs'; import { useMessageBoxAutoFocus } from './hooks/useMessageBoxAutoFocus'; import { useMessageBoxPlaceholder } from './hooks/useMessageBoxPlaceholder'; -import { useIsFederationEnabled } from '../../../../hooks/useIsFederationEnabled'; const reducer = (_: unknown, event: FormEvent): boolean => { const target = event.target as HTMLInputElement; @@ -379,6 +380,20 @@ const MessageBox = ({ ), ); + const beforeInputHandlerCallbackRef = useSafeRefCallback( + useCallback( + (node: HTMLTextAreaElement) => { + const eventHandler = (e: Event) => handleSelectionWrapping(e as InputEvent, chat); + node.addEventListener('beforeinput', eventHandler); + + return () => { + node.removeEventListener('beforeinput', eventHandler); + }; + }, + [chat], + ), + ); + const mergedRefs = useMessageComposerMergedRefs( popup.callbackRef, textareaRef, @@ -386,6 +401,7 @@ const MessageBox = ({ callbackRef, autofocusRef, keyDownHandlerCallbackRef, + beforeInputHandlerCallbackRef, ); const shouldPopupPreview = useEnablePopupPreview(popup.filter, popup.option); diff --git a/apps/meteor/client/views/room/composer/messageBox/wrapSelection.ts b/apps/meteor/client/views/room/composer/messageBox/wrapSelection.ts new file mode 100644 index 0000000000000..f888af94ae3f0 --- /dev/null +++ b/apps/meteor/client/views/room/composer/messageBox/wrapSelection.ts @@ -0,0 +1,58 @@ +import type { ChatAPI } from '../../../../lib/chats/ChatAPI'; + +const wrapSelectionPatterns: Record = { + '`': '`{{text}}`', + '"': '"{{text}}"', + "'": "'{{text}}'", + '(': '({{text}})', + '<': '<{{text}}>', + '{': '{{{text}}}', + '[': '[{{text}}]', + '*': '*{{text}}*', + '_': '_{{text}}_', + '~': '~{{text}}~', + '˜': '~{{text}}~', +}; + +const once = (target: EventTarget, eventName: string, callback: (event: Event) => void) => { + const handleEvent = (e: Event) => { + callback(e); + target.removeEventListener(eventName, handleEvent); + }; + target.addEventListener(eventName, handleEvent); +}; + +export const handleSelectionWrapping = (event: InputEvent, chat: ChatAPI): boolean => { + const { composer } = chat; + if (!composer) { + return false; + } + const input = event.target as HTMLTextAreaElement; + const { selectionStart, selectionEnd } = input; + + if (selectionStart === selectionEnd) { + return false; + } + + const key = event.data; + if (!key) { + return false; + } + const pattern = wrapSelectionPatterns[key]; + if (!pattern) { + return false; + } + + const selection = composer.wrapSelection(pattern); + // this is a workaround when we are using MAC + if (event.isComposing) { + once(input, 'input', (event) => { + input.value = selection.value; + input.setSelectionRange(selection.selectionStart, selection.selectionEnd); + event.preventDefault(); + }); + } + + event.preventDefault(); + return true; +}; From a298a270a339a3d902a0321ed2e41d927338788e Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Wed, 8 Apr 2026 18:17:06 -0300 Subject: [PATCH 35/51] chore: Enable Meteor's *Modern Build Stack* (#37614) Co-authored-by: Tasso --- .github/actions/meteor-build/action.yml | 11 +- .../patches/typia-npm-9.7.2-5c5d9c80b4.patch | 17 +++ apps/meteor/.babelrc | 10 +- apps/meteor/.meteor/packages | 2 +- apps/meteor/.meteor/platforms | 3 +- apps/meteor/.meteor/versions | 4 +- apps/meteor/.swcrc | 10 ++ apps/meteor/package.json | 10 +- docs/coverage.md | 125 ++++++++++++++++++ packages/core-typings/package.json | 2 +- packages/ui-kit/package.json | 2 +- yarn.lock | 35 ++++- 12 files changed, 207 insertions(+), 24 deletions(-) create mode 100644 .yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch create mode 100644 apps/meteor/.swcrc create mode 100644 docs/coverage.md diff --git a/.github/actions/meteor-build/action.yml b/.github/actions/meteor-build/action.yml index 8f0a033433f78..8338948a1dc86 100644 --- a/.github/actions/meteor-build/action.yml +++ b/.github/actions/meteor-build/action.yml @@ -157,7 +157,16 @@ runs: # check if BABEL_ENV is set to coverage if [[ $BABEL_ENV == "coverage" ]]; then echo -e "rocketchat:coverage\n" >> ./apps/meteor/.meteor/packages - echo "Coverage enabled" + # Inject swc-plugin-coverage-instrument into .swcrc for istanbul-compatible coverage + node -e " + const fs = require('fs'); + const swcrc = JSON.parse(fs.readFileSync('./apps/meteor/.swcrc', 'utf8')); + swcrc.jsc.experimental = swcrc.jsc.experimental || {}; + swcrc.jsc.experimental.plugins = swcrc.jsc.experimental.plugins || []; + swcrc.jsc.experimental.plugins.push(['swc-plugin-coverage-instrument', {}]); + fs.writeFileSync('./apps/meteor/.swcrc', JSON.stringify(swcrc, null, 2) + '\n'); + " + echo "Coverage enabled (SWC istanbul plugin injected)" fi # Restore original package.json so meteor should not copy devDependencies diff --git a/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch b/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch new file mode 100644 index 0000000000000..b6f291d1a58d7 --- /dev/null +++ b/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch @@ -0,0 +1,17 @@ +diff --git a/lib/index.mjs b/lib/index.mjs +index 35c18fc129e349205d3db64bfb7b9c589c726d35..7fe10a375d6e6d4d46bb1c4a776fdc75f062c3d3 100644 +--- a/lib/index.mjs ++++ b/lib/index.mjs +@@ -1,4 +1,4 @@ +-import * as module from './module.mjs'; ++import * as _module from './module.mjs'; + export { assert, assertEquals, assertGuard, assertGuardEquals, createAssert, createAssertEquals, createAssertGuard, createAssertGuardEquals, createEquals, createIs, createRandom, createValidate, createValidateEquals, equals, is, random, validate, validateEquals } from './module.mjs'; + import * as functional from './functional.mjs'; + export { functional }; +@@ -22,5 +22,5 @@ export { TypeGuardError } from './TypeGuardError.mjs'; + + + +-export { module as default }; ++export { _module as default }; + //# sourceMappingURL=index.mjs.map diff --git a/apps/meteor/.babelrc b/apps/meteor/.babelrc index d57e624148cca..67b35228620e0 100644 --- a/apps/meteor/.babelrc +++ b/apps/meteor/.babelrc @@ -1,7 +1,7 @@ { "presets": [ "@babel/preset-env", - "@babel/preset-react", + ["@babel/preset-react", { "runtime": "automatic" }], [ "@babel/preset-typescript", { @@ -9,14 +9,6 @@ } ] ], - "plugins": [ - [ - "@babel/plugin-transform-react-jsx", - { - "runtime": "automatic" - } - ] - ], "env": { "coverage": { "plugins": [ diff --git a/apps/meteor/.meteor/packages b/apps/meteor/.meteor/packages index 757831b7a1bea..5b78dccdc9eb1 100644 --- a/apps/meteor/.meteor/packages +++ b/apps/meteor/.meteor/packages @@ -60,4 +60,4 @@ autoupdate@2.0.1 # photoswipe zodern:types -zodern:standard-minifier-js +standard-minifier-js diff --git a/apps/meteor/.meteor/platforms b/apps/meteor/.meteor/platforms index 8a3a35f9f6279..62ba921a0c051 100644 --- a/apps/meteor/.meteor/platforms +++ b/apps/meteor/.meteor/platforms @@ -1,2 +1,3 @@ -browser server +browser +modern \ No newline at end of file diff --git a/apps/meteor/.meteor/versions b/apps/meteor/.meteor/versions index d83c4802bcf32..7ea703c812dd1 100644 --- a/apps/meteor/.meteor/versions +++ b/apps/meteor/.meteor/versions @@ -46,6 +46,7 @@ meteor-base@1.5.2 meteor-developer-oauth@1.3.3 meteorhacks:inject-initial@1.0.5 minifier-css@2.0.1 +minifier-js@3.1.0 minimongo@2.0.5 modern-browsers@0.2.3 modules@0.20.3 @@ -85,6 +86,5 @@ underscore@1.6.4 url@1.3.5 webapp@2.1.0 webapp-hashing@1.1.2 -zodern:caching-minifier@0.5.0 -zodern:standard-minifier-js@5.3.1 +standard-minifier-js@3.2.0 zodern:types@1.0.13 diff --git a/apps/meteor/.swcrc b/apps/meteor/.swcrc new file mode 100644 index 0000000000000..003417d6c0619 --- /dev/null +++ b/apps/meteor/.swcrc @@ -0,0 +1,10 @@ +{ + "jsc": { + "target": "es2022", + "transform": { + "react": { + "runtime": "automatic" + } + } + } +} diff --git a/apps/meteor/package.json b/apps/meteor/package.json index dd6e41fc9507e..5c86091690f38 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -62,8 +62,7 @@ "version": "node .scripts/version.js" }, "browserslist": [ - "last 2 versions", - "Firefox ESR" + "defaults" ], "dependencies": { "@aws-sdk/client-s3": "^3.862.0", @@ -291,6 +290,7 @@ "strict-uri-encode": "^2.0.0", "string-strip-html": "^8.5.0", "swagger-ui-express": "^5.0.1", + "swc-plugin-coverage-instrument": "0.0.32", "swiper": "patch:swiper@npm%3A11.1.14#~/.yarn/patches/swiper-npm-11.1.14-8126fa478a.patch", "textarea-caret": "^3.1.0", "tinykeys": "^1.4.0", @@ -298,7 +298,7 @@ "tweetnacl": "^1.0.3", "twilio": "^5.4.2", "twit": "^2.2.11", - "typia": "~9.7.2", + "typia": "patch:typia@npm%3A9.7.2#~/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch", "ua-parser-js": "~1.0.41", "underscore": "^1.13.7", "universal-perf-hooks": "^1.0.1", @@ -459,10 +459,12 @@ "hoistingLimits": "workspaces" }, "meteor": { + "disableLegacyBuild": true, "mainModule": { "client": "client/main.ts", "server": "server/main.ts" - } + }, + "modern": true }, "rocketchat": { "minimumClientVersions": { diff --git a/docs/coverage.md b/docs/coverage.md new file mode 100644 index 0000000000000..532f7077be84b --- /dev/null +++ b/docs/coverage.md @@ -0,0 +1,125 @@ +# Code Coverage + +This document explains how code coverage instrumentation works in Rocket.Chat's build and CI pipeline. + +## Overview + +Coverage is collected during E2E test runs (API, UI, Livechat) to measure how much of the server-side code is exercised by tests. The instrumentation uses [Istanbul](https://istanbul.js.org/)-compatible tooling, which injects counters (`__coverage__`) into the compiled code at build time. + +## Architecture + +The coverage pipeline has three components: + +1. **Build-time instrumentation** - injects coverage counters into the code during Meteor build +2. **Runtime collection** - the `rocketchat:coverage` Meteor package collects `__coverage__` data on process exit +3. **CI reporting** - test workflows merge coverage data and upload reports + +``` +Build (SWC + plugin) --> Run tests --> Process exit triggers report --> Merge & upload +``` + +## Build-time instrumentation + +### Modern build stack (SWC) + +Rocket.Chat uses Meteor's modern build stack with [SWC](https://swc.rs/) as the transpiler. For coverage builds, the [`swc-plugin-coverage-instrument`](https://github.com/kwonoj/swc-plugin-coverage-instrument) plugin is injected into `.swcrc` at build time. + +This is configured in `.github/actions/meteor-build/action.yml`: + +```yaml +env: + BABEL_ENV: ${{ inputs.type }} # "production" or "coverage" +``` + +When `BABEL_ENV=coverage`, the build script: + +1. Adds `rocketchat:coverage` to `.meteor/packages` +2. Injects `swc-plugin-coverage-instrument` into `.swcrc` via a node script: + +```js +const swcrc = JSON.parse(fs.readFileSync('./apps/meteor/.swcrc', 'utf8')); +swcrc.jsc.experimental = swcrc.jsc.experimental || {}; +swcrc.jsc.experimental.plugins = swcrc.jsc.experimental.plugins || []; +swcrc.jsc.experimental.plugins.push(['swc-plugin-coverage-instrument', {}]); +fs.writeFileSync('./apps/meteor/.swcrc', JSON.stringify(swcrc, null, 2) + '\n'); +``` + +This approach ensures the same build pipeline (SWC) is used for both regular and coverage builds, avoiding behavioral differences between build modes. + +### Legacy build stack (Babel) + +Before the modern build stack, coverage was handled via `babel-plugin-istanbul` configured in `.babelrc`: + +```json +{ + "env": { + "coverage": { + "plugins": [ + ["istanbul", { "exclude": ["**/*.spec.js", "**/*.test.js"] }] + ] + } + } +} +``` + +This section is still present in `.babelrc` as a fallback for files that fall back to Babel compilation (e.g., SWC-incompatible code). + +## Runtime collection: `rocketchat:coverage` + +The `rocketchat:coverage` Meteor package (`apps/meteor/packages/rocketchat-coverage/`) is only added to the build during coverage runs. It: + +1. Registers a `process.on('exit')` handler +2. Reads `globalThis['__coverage__']` (populated by the instrumentation) +3. Generates a coverage report using `istanbul-lib-coverage` and `istanbul-reports` + +Configuration via environment variables: + +| Variable | Description | Example | +|---|---|---| +| `COVERAGE_DIR` | Output directory for reports | `/tmp/coverage/api` | +| `COVERAGE_FILE_NAME` | Report filename | `api-1.json` | +| `COVERAGE_REPORTER` | Istanbul reporter format | `json`, `lcov` | + +## CI workflow + +Coverage is collected in the `ci-test-e2e.yml` workflow: + +1. **Build**: `meteor-build` action runs with `type: coverage`, producing a Docker image with instrumented code +2. **Test**: E2E tests run against the instrumented server. On each test shard: + - `COVERAGE_DIR`, `COVERAGE_FILE_NAME`, and `COVERAGE_REPORTER` are set + - When the Rocket.Chat process exits after tests, the coverage plugin writes a JSON report +3. **Merge**: `nyc merge` combines per-shard JSON reports into a single coverage file +4. **Upload**: Coverage data is uploaded to Codecov + +## Local development + +To build with coverage locally: + +```bash +cd apps/meteor + +# Inject the SWC coverage plugin into .swcrc +node -e " + const fs = require('fs'); + const swcrc = JSON.parse(fs.readFileSync('.swcrc', 'utf8')); + swcrc.jsc.experimental = { plugins: [['swc-plugin-coverage-instrument', {}]] }; + fs.writeFileSync('.swcrc', JSON.stringify(swcrc, null, 2)); +" + +# Add the coverage package +echo -e "rocketchat:coverage\n" >> .meteor/packages + +# Set env vars and run +COVERAGE_DIR=/tmp/coverage COVERAGE_FILE_NAME=local.json COVERAGE_REPORTER=lcov yarn dev +``` + +Remember to restore `.swcrc` and `.meteor/packages` after testing. + +## Dependencies + +| Package | Purpose | +|---|---| +| `swc-plugin-coverage-instrument` | SWC plugin for Istanbul-compatible instrumentation | +| `istanbul-lib-coverage` | Coverage map creation (used by `rocketchat:coverage`) | +| `istanbul-lib-report` | Report context creation | +| `istanbul-reports` | Report formatters (json, lcov, etc.) | diff --git a/packages/core-typings/package.json b/packages/core-typings/package.json index 96a46e0d783dd..e3a60325e3fda 100644 --- a/packages/core-typings/package.json +++ b/packages/core-typings/package.json @@ -21,7 +21,7 @@ "@rocket.chat/icons": "~0.47.0", "@rocket.chat/message-parser": "workspace:^", "@rocket.chat/ui-kit": "workspace:~", - "typia": "~9.7.2", + "typia": "patch:typia@npm%3A9.7.2#~/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch", "zod": "~4.3.6" }, "devDependencies": { diff --git a/packages/ui-kit/package.json b/packages/ui-kit/package.json index 94c69c58b407b..f3fcf667c9fda 100644 --- a/packages/ui-kit/package.json +++ b/packages/ui-kit/package.json @@ -31,7 +31,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "typia": "~9.7.2" + "typia": "patch:typia@npm%3A9.7.2#~/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch" }, "devDependencies": { "@rocket.chat/icons": "~0.47.0", diff --git a/yarn.lock b/yarn.lock index 9b050044d52e7..593c43b9c9c68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9173,7 +9173,7 @@ __metadata: rimraf: "npm:^6.0.1" ts-patch: "npm:^3.3.0" typescript: "npm:~5.9.3" - typia: "npm:~9.7.2" + typia: "patch:typia@npm%3A9.7.2#~/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch" zod: "npm:~4.3.6" languageName: unknown linkType: soft @@ -10312,6 +10312,7 @@ __metadata: supertest: "npm:~7.1.4" supports-color: "npm:~7.2.0" swagger-ui-express: "npm:^5.0.1" + swc-plugin-coverage-instrument: "npm:0.0.32" swiper: "patch:swiper@npm%3A11.1.14#~/.yarn/patches/swiper-npm-11.1.14-8126fa478a.patch" template-file: "npm:^6.0.1" textarea-caret: "npm:^3.1.0" @@ -10323,7 +10324,7 @@ __metadata: twilio: "npm:^5.4.2" twit: "npm:^2.2.11" typescript: "npm:~5.9.3" - typia: "npm:~9.7.2" + typia: "patch:typia@npm%3A9.7.2#~/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch" ua-parser-js: "npm:~1.0.41" underscore: "npm:^1.13.7" universal-perf-hooks: "npm:^1.0.1" @@ -11150,7 +11151,7 @@ __metadata: ts-jest: "npm:~29.4.6" ts-patch: "npm:^3.3.0" typescript: "npm:~5.9.3" - typia: "npm:~9.7.2" + typia: "patch:typia@npm%3A9.7.2#~/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch" peerDependencies: "@rocket.chat/icons": "*" languageName: unknown @@ -35680,6 +35681,13 @@ __metadata: languageName: node linkType: hard +"swc-plugin-coverage-instrument@npm:0.0.32": + version: 0.0.32 + resolution: "swc-plugin-coverage-instrument@npm:0.0.32" + checksum: 10/5e5929ca4dc5906d081ddc96be88059f5cbd5c65d40031847902631b2a0911e67435120fc9ba3bd8a2e657e44bd29ad31aa85282a0de4aa1cf106a4bfc579f9b + languageName: node + linkType: hard + "swiper@npm:11.1.14": version: 11.1.14 resolution: "swiper@npm:11.1.14" @@ -36860,7 +36868,7 @@ __metadata: languageName: node linkType: hard -"typia@npm:~9.7.2": +"typia@npm:9.7.2": version: 9.7.2 resolution: "typia@npm:9.7.2" dependencies: @@ -36879,6 +36887,25 @@ __metadata: languageName: node linkType: hard +"typia@patch:typia@npm%3A9.7.2#~/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch": + version: 9.7.2 + resolution: "typia@patch:typia@npm%3A9.7.2#~/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch::version=9.7.2&hash=cc0415" + dependencies: + "@samchon/openapi": "npm:^4.7.1" + "@standard-schema/spec": "npm:^1.0.0" + commander: "npm:^10.0.0" + comment-json: "npm:^4.2.3" + inquirer: "npm:^8.2.5" + package-manager-detector: "npm:^0.2.0" + randexp: "npm:^0.5.3" + peerDependencies: + typescript: ">=4.8.0 <5.10.0" + bin: + typia: lib/executable/typia.js + checksum: 10/db5a671719afedcafff4f48b684d7afb76803d32ccb98df64071fd02e32bd932496d5b1c348112a4deab97d65f53be554ae9fd391ce6f6a90a92a33a6e1086d8 + languageName: node + linkType: hard + "ua-parser-js@npm:~1.0.41": version: 1.0.41 resolution: "ua-parser-js@npm:1.0.41" From 84754bb6331783a265ffec1a7a9b8c680d258f72 Mon Sep 17 00:00:00 2001 From: Nazareno Bucciarelli <84046180+nazabucciarelli@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:30:39 -0300 Subject: [PATCH 36/51] fix: slack importer not importing messages correctly (#40053) --- .changeset/mean-mails-pay.md | 5 +++++ .../server/classes/converters/MessageConverter.ts | 5 +++-- .../unit/app/importer/server/messageConverter.spec.ts | 10 ++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 .changeset/mean-mails-pay.md diff --git a/.changeset/mean-mails-pay.md b/.changeset/mean-mails-pay.md new file mode 100644 index 0000000000000..b2d32b798e1c1 --- /dev/null +++ b/.changeset/mean-mails-pay.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes Slack messages being incorrectly saved on import diff --git a/apps/meteor/app/importer/server/classes/converters/MessageConverter.ts b/apps/meteor/app/importer/server/classes/converters/MessageConverter.ts index cb4cf8047470d..e9e7295078c8d 100644 --- a/apps/meteor/app/importer/server/classes/converters/MessageConverter.ts +++ b/apps/meteor/app/importer/server/classes/converters/MessageConverter.ts @@ -1,5 +1,6 @@ import type { IImportMessageRecord, IMessage as IDBMessage, IImportMessage, IImportMessageReaction } from '@rocket.chat/core-typings'; import { Rooms } from '@rocket.chat/models'; +import { removeEmpty } from '@rocket.chat/tools'; import limax from 'limax'; import type { UserIdentification, MentionedChannel } from './ConverterCache'; @@ -84,7 +85,7 @@ export class MessageConverter extends RecordConverter { const mentions = data.mentions && (await this.convertMessageMentions(data)); const channels = data.channels && (await this.convertMessageChannels(data)); - return { + return removeEmpty({ rid, u: { _id: creator._id, @@ -110,7 +111,7 @@ export class MessageConverter extends RecordConverter { alias: data.alias, ...(data._id ? { _id: data._id } : {}), ...(data.reactions ? { reactions: await this.convertMessageReactions(data.reactions) } : {}), - }; + }); } protected async convertMessageChannels(message: IImportMessage): Promise { diff --git a/apps/meteor/tests/unit/app/importer/server/messageConverter.spec.ts b/apps/meteor/tests/unit/app/importer/server/messageConverter.spec.ts index dcf72bb9b50d6..22ffa2afd4f2a 100644 --- a/apps/meteor/tests/unit/app/importer/server/messageConverter.spec.ts +++ b/apps/meteor/tests/unit/app/importer/server/messageConverter.spec.ts @@ -92,6 +92,16 @@ describe('Message Converter', () => { }); }); + it('should not have properties with undefined values', async () => { + const converter = new MessageConverter({ workInMemory: true }); + + const converted = await converter.buildMessageObject(messageToImport, 'general', { _id: 'rocket.cat', username: 'rocket.cat' }); + + Object.entries(converted).forEach(([key, value]) => { + expect(value, `Property "${key}" should not be undefined`).to.not.be.undefined; + }); + }); + // #TODO: Validate all message attributes }); From 93e3193005878b3ce909382d650dc7a84080be61 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Thu, 9 Apr 2026 19:10:57 +0530 Subject: [PATCH 37/51] chore: remove outdated oplog error message from admin workspace page (#40066) Signed-off-by: Abhinav Kumar --- .../DeploymentCard/DeploymentCard.tsx | 4 +--- .../views/admin/workspace/WorkspacePage.tsx | 24 ------------------- packages/i18n/src/locales/af.i18n.json | 2 -- packages/i18n/src/locales/ar.i18n.json | 2 -- packages/i18n/src/locales/az.i18n.json | 2 -- packages/i18n/src/locales/bg.i18n.json | 2 -- packages/i18n/src/locales/ca.i18n.json | 2 -- packages/i18n/src/locales/cs.i18n.json | 2 -- packages/i18n/src/locales/da.i18n.json | 2 -- packages/i18n/src/locales/de-AT.i18n.json | 2 -- packages/i18n/src/locales/de.i18n.json | 2 -- packages/i18n/src/locales/el.i18n.json | 2 -- packages/i18n/src/locales/en.i18n.json | 2 -- packages/i18n/src/locales/eo.i18n.json | 2 -- packages/i18n/src/locales/es.i18n.json | 2 -- packages/i18n/src/locales/fa.i18n.json | 2 -- packages/i18n/src/locales/fi.i18n.json | 2 -- packages/i18n/src/locales/fr.i18n.json | 2 -- packages/i18n/src/locales/hi-IN.i18n.json | 2 -- packages/i18n/src/locales/hr.i18n.json | 2 -- packages/i18n/src/locales/hu.i18n.json | 2 -- packages/i18n/src/locales/id.i18n.json | 2 -- packages/i18n/src/locales/it.i18n.json | 2 -- packages/i18n/src/locales/ja.i18n.json | 2 -- packages/i18n/src/locales/ka-GE.i18n.json | 2 -- packages/i18n/src/locales/km.i18n.json | 2 -- packages/i18n/src/locales/ko.i18n.json | 2 -- packages/i18n/src/locales/ku.i18n.json | 2 -- packages/i18n/src/locales/lo.i18n.json | 2 -- packages/i18n/src/locales/lt.i18n.json | 2 -- packages/i18n/src/locales/lv.i18n.json | 2 -- packages/i18n/src/locales/mn.i18n.json | 2 -- packages/i18n/src/locales/ms-MY.i18n.json | 2 -- packages/i18n/src/locales/nb.i18n.json | 2 -- packages/i18n/src/locales/nl.i18n.json | 2 -- packages/i18n/src/locales/nn.i18n.json | 2 -- packages/i18n/src/locales/pl.i18n.json | 2 -- packages/i18n/src/locales/pt-BR.i18n.json | 2 -- packages/i18n/src/locales/pt.i18n.json | 2 -- packages/i18n/src/locales/ro.i18n.json | 2 -- packages/i18n/src/locales/ru.i18n.json | 2 -- packages/i18n/src/locales/sk-SK.i18n.json | 2 -- packages/i18n/src/locales/sl-SI.i18n.json | 2 -- packages/i18n/src/locales/sq.i18n.json | 2 -- packages/i18n/src/locales/sr.i18n.json | 2 -- packages/i18n/src/locales/sv.i18n.json | 2 -- packages/i18n/src/locales/ta-IN.i18n.json | 2 -- packages/i18n/src/locales/th-TH.i18n.json | 2 -- packages/i18n/src/locales/tr.i18n.json | 2 -- packages/i18n/src/locales/uk.i18n.json | 2 -- packages/i18n/src/locales/vi-VN.i18n.json | 2 -- packages/i18n/src/locales/zh-HK.i18n.json | 2 -- packages/i18n/src/locales/zh-TW.i18n.json | 2 -- packages/i18n/src/locales/zh.i18n.json | 2 -- 54 files changed, 1 insertion(+), 131 deletions(-) diff --git a/apps/meteor/client/views/admin/workspace/DeploymentCard/DeploymentCard.tsx b/apps/meteor/client/views/admin/workspace/DeploymentCard/DeploymentCard.tsx index fe724f60064ba..2d9c6e5e224d8 100644 --- a/apps/meteor/client/views/admin/workspace/DeploymentCard/DeploymentCard.tsx +++ b/apps/meteor/client/views/admin/workspace/DeploymentCard/DeploymentCard.tsx @@ -68,9 +68,7 @@ const DeploymentCard = ({ serverInfo: { info, cloudWorkspaceId }, statistics, in - {`${statistics.mongoVersion} / ${statistics.mongoStorageEngine} ${ - !statistics.msEnabled ? `(oplog ${statistics.oplogEnabled ? t('Enabled') : t('Disabled')})` : '' - }`} + {`${statistics.mongoVersion} / ${statistics.mongoStorageEngine}`} diff --git a/apps/meteor/client/views/admin/workspace/WorkspacePage.tsx b/apps/meteor/client/views/admin/workspace/WorkspacePage.tsx index 987bfaaec55ce..6ae19a63992bd 100644 --- a/apps/meteor/client/views/admin/workspace/WorkspacePage.tsx +++ b/apps/meteor/client/views/admin/workspace/WorkspacePage.tsx @@ -35,7 +35,6 @@ const WorkspacePage = ({ const { data } = useIsEnterprise(); const warningMultipleInstances = !data?.isEnterprise && !statistics?.msEnabled && statistics?.instanceCount > 1; - const alertOplogForMultipleInstances = warningMultipleInstances && !statistics.oplogEnabled; return ( @@ -55,29 +54,6 @@ const WorkspacePage = ({ {warningMultipleInstances && ( )} - {alertOplogForMultipleInstances && ( - - -

{t('Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details')}

-

- - {t('Click_here_for_more_info')} - -

-
-
- )} diff --git a/packages/i18n/src/locales/af.i18n.json b/packages/i18n/src/locales/af.i18n.json index 95b2ec5254b5e..ed1d13e362cef 100644 --- a/packages/i18n/src/locales/af.i18n.json +++ b/packages/i18n/src/locales/af.i18n.json @@ -864,8 +864,6 @@ "Entertainment": "Vermaak", "Error": "fout", "Error_404": "Fout: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Fout: Rocket.Chat vereis oplog tailing wanneer dit in verskeie gevalle uitgevoer word", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Maak asseblief seker dat jou MongoDB op ReplicaSet af is en MONGO_OPLOG_URL omgewingsveranderlike korrek is gedefinieer op die aansoek bediener", "Error_changing_password": "Kon nie wagwoord verander nie", "Error_loading_pages": "Kon nie bladsye laai nie", "Esc_to": "Esc to", diff --git a/packages/i18n/src/locales/ar.i18n.json b/packages/i18n/src/locales/ar.i18n.json index a9ec900089a61..bef2196cd4148 100644 --- a/packages/i18n/src/locales/ar.i18n.json +++ b/packages/i18n/src/locales/ar.i18n.json @@ -1454,8 +1454,6 @@ "Entertainment": "الترفيه", "Error": "خطأ", "Error_404": "خطأ: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "خطأ: يتطلب Rocket.Chat تتبع سجل العمليات عند التشغيل في حالات متعددة", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "يرجى التأكد من أن قاعدة البيانات MongoDB الخاصة بك في وضع ReplicaSet وأن متغير البيئة MONGO_OPLOG_URL محدد بشكل صحيح على خادم التطبيق", "Error_Site_URL": "Site_Url غير صالح", "Error_Site_URL_description": "يُرجى تحديث إعداد \"Site_Url\" الخاص بك، اعثر على مزيد من المعلومات [هنا](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "خطأ في تغيير كلمة المرور", diff --git a/packages/i18n/src/locales/az.i18n.json b/packages/i18n/src/locales/az.i18n.json index 790aaacd1f6a8..ee3a3b76f4770 100644 --- a/packages/i18n/src/locales/az.i18n.json +++ b/packages/i18n/src/locales/az.i18n.json @@ -864,8 +864,6 @@ "Entertainment": "Əyləncə", "Error": "Səhv", "Error_404": "Hata: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Hata: Rocket.Chat, birdən çox halında çalışırken oplog kuyruklamasını tələb edir", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "MongoDB-nin ReplicaSet rejimində olduğundan və MONGO_OPLOG_URL ətraf mühitə dəyişənlərin tətbiq serverində düzgün olduğundan əmin olun", "Error_changing_password": "Şifrəni dəyişməkdə səhv", "Error_loading_pages": "Səhifələr yüklənərkən səhv", "Esc_to": "Esc üçün", diff --git a/packages/i18n/src/locales/bg.i18n.json b/packages/i18n/src/locales/bg.i18n.json index 84720df14e7bd..c4b6b08a4df6c 100644 --- a/packages/i18n/src/locales/bg.i18n.json +++ b/packages/i18n/src/locales/bg.i18n.json @@ -864,8 +864,6 @@ "Entertainment": "забавление", "Error": "Грешка", "Error_404": "Грешка: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Грешка: Rocket.Chat изисква oplog tailing, когато се изпълнява в няколко случая", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Моля, уверете се, че вашият MongoDB е в режим ReplicaSet и че променливата на средата MONGO_OPLOG_URL е дефинирана правилно на сървъра на приложения", "Error_changing_password": "Грешка при промяна на паролата", "Error_loading_pages": "Грешка при зареждането на страници", "Esc_to": "Esc до", diff --git a/packages/i18n/src/locales/ca.i18n.json b/packages/i18n/src/locales/ca.i18n.json index bcf860d888ee4..41907b8b9f7b7 100644 --- a/packages/i18n/src/locales/ca.i18n.json +++ b/packages/i18n/src/locales/ca.i18n.json @@ -1446,8 +1446,6 @@ "Entertainment": "Entreteniment", "Error": "Error", "Error_404": "Error: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Error: El Rocket.Chat requereix oplog tailing quan s'executa en múltiples instàncies", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Comproveu que el MongoDB estigui en mode ReplicaSet i que la variable d'entorn MONGO_OPLOG_URL estigui definida correctament al servidor d'aplicacions", "Error_Site_URL": "Site_Url no vàlid", "Error_Site_URL_description": "Si us plau, actualitzi el valor de configuració \"Site_Url\", trobi més informació aquí", "Error_changing_password": "Error en canviar la contrasenya", diff --git a/packages/i18n/src/locales/cs.i18n.json b/packages/i18n/src/locales/cs.i18n.json index 12a1f107c94f8..745c101444a20 100644 --- a/packages/i18n/src/locales/cs.i18n.json +++ b/packages/i18n/src/locales/cs.i18n.json @@ -1229,8 +1229,6 @@ "Entertainment": "Zábava", "Error": "Chyba", "Error_404": "Chyba: 404 nenalezeno", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Chyba: Rocket.Chat vyžaduje tail oplogu pokud běží na více instancích.", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Prověřte, že je MongoDB v ReplicaSet módu a proměnná prostředí MONGO_OPLOG_URL je na aplikačním serveru nastavena správně", "Error_Site_URL": "Chybné Site_Url", "Error_Site_URL_description": "Prosím aktualizujte nastavení \"Site_Url\", více informací naleznete [zde](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Chyba změny hesla", diff --git a/packages/i18n/src/locales/da.i18n.json b/packages/i18n/src/locales/da.i18n.json index 48b243eba896e..80414c9d8c05e 100644 --- a/packages/i18n/src/locales/da.i18n.json +++ b/packages/i18n/src/locales/da.i18n.json @@ -1304,8 +1304,6 @@ "Entertainment": "Underholdning", "Error": "Fejl", "Error_404": "Fejl: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Fejl: Rocket.Chat kræver oplog-tailing når du anvender flere instanser", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Sørg for at din MongoDB er i ReplicaSet-mode og MONGO_OPLOG_URL miljøvariabel er defineret korrekt på applikationsserveren", "Error_Site_URL": "Ugyldigt Site_Url", "Error_Site_URL_description": "Opdatér venligst din \"Site_Url\" -indstilling. Se flere oplysninger [ her ](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Fejl ved ændring af adgangskode", diff --git a/packages/i18n/src/locales/de-AT.i18n.json b/packages/i18n/src/locales/de-AT.i18n.json index 6a6d986f4ded2..051e374efe0dc 100644 --- a/packages/i18n/src/locales/de-AT.i18n.json +++ b/packages/i18n/src/locales/de-AT.i18n.json @@ -865,8 +865,6 @@ "Entertainment": "Unterhaltung", "Error": "Fehler", "Error_404": "Fehler 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Fehler: Rocket.Chat erfordert einen oplog-Tailing, wenn er in mehreren Instanzen ausgeführt wird", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Stellen Sie sicher, dass sich Ihre MongoDB im ReplicaSet-Modus befindet und die Umgebungsvariable MONGO_OPLOG_URL auf dem Anwendungsserver korrekt definiert ist", "Error_changing_password": "Fehler beim Ändern des Passwortes", "Error_loading_pages": "Fehler beim Laden der Seiten", "Esc_to": "Esc: ", diff --git a/packages/i18n/src/locales/de.i18n.json b/packages/i18n/src/locales/de.i18n.json index 9bc31f8aff2ca..f2fadf329262c 100644 --- a/packages/i18n/src/locales/de.i18n.json +++ b/packages/i18n/src/locales/de.i18n.json @@ -1604,8 +1604,6 @@ "Entertainment": "Unterhaltung", "Error": "Fehler", "Error_404": "Fehler: 404(nicht gefunden)", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Fehler: Rocket.Chat erfordert Oplog-Tailing, wenn es auf mehreren Instanzen läuft", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Bitte stellen Sie sicher, dass die MongoDB als Replicaset konfiguriert ist und die Umgebungsvariable MONGO_OPLOG_URL korrekt auf Ihren Anwendungsservern gesetzt wurde.", "Error_Site_URL": "Ungültige URL", "Error_Site_URL_description": "Bitte aktualisieren Sie Ihre \"Site_Url\" -Einstellung. Weitere Informationen [finden Sie hier](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Fehler beim Ändern des Passwortes", diff --git a/packages/i18n/src/locales/el.i18n.json b/packages/i18n/src/locales/el.i18n.json index 29e4ca9225c21..192ee45726a59 100644 --- a/packages/i18n/src/locales/el.i18n.json +++ b/packages/i18n/src/locales/el.i18n.json @@ -868,8 +868,6 @@ "Entertainment": "Ψυχαγωγία", "Error": "Λάθος", "Error_404": "Σφάλμα 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Σφάλμα: Το Rocket.Chat απαιτεί oplog tailing όταν εκτελείται σε πολλαπλές περιπτώσεις", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Βεβαιωθείτε ότι το MongoDB βρίσκεται στη λειτουργία ReplicaSet και ότι η μεταβλητή περιβάλλοντος MONGO_OPLOG_URL ορίζεται σωστά στον διακομιστή εφαρμογών", "Error_changing_password": "Ο κωδικός άλλαξε", "Error_loading_pages": "Σφάλμα κατά την φόρτωση σελίδων", "Esc_to": "Esc για να", diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 6fc3ec4ef5cfd..2881b1432e9b7 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -2067,8 +2067,6 @@ "Error": "Error", "Error_404": "Error:404", "Error_encrypting_file": "Error while encrypting file", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Error: Rocket.Chat requires oplog tailing when running in multiple instances", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Please make sure your MongoDB is on ReplicaSet mode and MONGO_OPLOG_URL environment variable is defined correctly on the application server", "Error_Site_URL": "Invalid Site_Url", "Error_Site_URL_description": "Please, update your \"Site_Url\" setting find more information [here](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Error changing password", diff --git a/packages/i18n/src/locales/eo.i18n.json b/packages/i18n/src/locales/eo.i18n.json index 54f1bf1e55de1..7e4b947c71784 100644 --- a/packages/i18n/src/locales/eo.i18n.json +++ b/packages/i18n/src/locales/eo.i18n.json @@ -862,8 +862,6 @@ "Entertainment": "Amuzaĵo", "Error": "Eraro", "Error_404": "Eraro: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Eraro: Rocket.Chat postulas oplog-fiksi kiam kurante en multaj petskriboj", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Bonvolu certigi, ke via MongoDB estas en ReplicaSet mode kaj MONGO_OPLOG_URL-medio-variablo estas difinita ĝuste en la servilo de aplikaĵoj", "Error_changing_password": "Eraro ŝanĝi pasvorton", "Error_loading_pages": "Eraro ŝarĝante paĝojn", "Esc_to": "Esc al", diff --git a/packages/i18n/src/locales/es.i18n.json b/packages/i18n/src/locales/es.i18n.json index f16422bcaacc8..38c059508783b 100644 --- a/packages/i18n/src/locales/es.i18n.json +++ b/packages/i18n/src/locales/es.i18n.json @@ -1487,8 +1487,6 @@ "Entertainment": "Entretenimiento", "Error": "Error", "Error_404": "Error 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Error: Rocket.Chat requiere la puesta en cola de oplogs cuando se ejecuta en varias instancias", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Asegúrate de que tu base de datos MongoDB esté en modo ReplicaSet y de que la variable de entorno MONGO_OPLOG_URL esté definida correctamente en el servidor de aplicaciones.", "Error_Site_URL": "Site_Url no válida", "Error_Site_URL_description": "Actualiza el ajuste de \"Site_Url\". Más información [aquí](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Error al cambiar la contraseña", diff --git a/packages/i18n/src/locales/fa.i18n.json b/packages/i18n/src/locales/fa.i18n.json index 3679c67566457..c053b3fb7ec98 100644 --- a/packages/i18n/src/locales/fa.i18n.json +++ b/packages/i18n/src/locales/fa.i18n.json @@ -1085,8 +1085,6 @@ "Entertainment": "سرگرمی", "Error": "خطا", "Error_404": "خطای 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "خطا: Rocket.Chat در هنگام اجرا در چندین مرحله نیاز به oplog tailing دارد", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "لطفا مطمئن شوید MongoDB شما در حالت ReplicaSet است و متغیر محدوده MONGO_OPLOG_URL به طور صحیح در سرور برنامه تعریف شده است", "Error_changing_password": "خطا هنگام تغییر رمز عبور", "Error_loading_pages": "خطا هنگام بارگیری صفحات", "Error_sending_livechat_offline_message": "خطای ارسال پیام برون‌خط کانال همه‌کاره", diff --git a/packages/i18n/src/locales/fi.i18n.json b/packages/i18n/src/locales/fi.i18n.json index e5849b20c895c..d25c93247f5ee 100644 --- a/packages/i18n/src/locales/fi.i18n.json +++ b/packages/i18n/src/locales/fi.i18n.json @@ -1646,8 +1646,6 @@ "Entertainment": "Viihde", "Error": "Virhe", "Error_404": "Virhe: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Virhe: Rocket.Chat edellyttää oplog tailing -toimintoa käytettäessä useita esiintymiä", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Varmista, että MongoDB on ReplicaSet-tilassa ja että MONGO_OPLOG_URL-ympäristömuuttuja on määritetty oikein sovelluspalvelimessa", "Error_Site_URL": "Virheellinen Site_Url", "Error_Site_URL_description": "Päivitä \"Site_Url\"-asetus. Lisätietoja on [täällä](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Virhe vaihdettaessa salasanaa", diff --git a/packages/i18n/src/locales/fr.i18n.json b/packages/i18n/src/locales/fr.i18n.json index c3a712d08ba10..827ae272a1eea 100644 --- a/packages/i18n/src/locales/fr.i18n.json +++ b/packages/i18n/src/locales/fr.i18n.json @@ -1458,8 +1458,6 @@ "Entertainment": "Divertissement", "Error": "Erreur", "Error_404": "Erreur 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Erreur : Rocket.chat requiert l'activation de la fonction \"oplog tailing\" lors de l'exécution sur plusieurs instances", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Veuillez vous assurer que MongoDB est en mode ReplicaSet et que la variable d'environnement MONGO_OPLOG_URL est définie correctement sur le serveur de l'application", "Error_Site_URL": "Site_Url non valide", "Error_Site_URL_description": "Mettez à jour votre paramètre \"Site_Url\". Pour plus d'informations, [cliquez ici](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Erreur lors du changement de mot de passe", diff --git a/packages/i18n/src/locales/hi-IN.i18n.json b/packages/i18n/src/locales/hi-IN.i18n.json index 6ade5f01da838..6e0f115b446d2 100644 --- a/packages/i18n/src/locales/hi-IN.i18n.json +++ b/packages/i18n/src/locales/hi-IN.i18n.json @@ -1709,8 +1709,6 @@ "Entertainment": "मनोरंजन", "Error": "गलती", "Error_404": "त्रुटि 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "त्रुटि: रॉकेट.चैट को कई उदाहरणों में चलाने पर ओप्लॉग टेलिंग की आवश्यकता होती है", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "कृपया सुनिश्चित करें कि आपका MongoDB रेप्लिकासेट मोड पर है और MONGO_OPLOG_URL पर्यावरण चर एप्लिकेशन सर्वर पर सही ढंग से परिभाषित है", "Error_Site_URL": "अमान्य साइट_यूआरएल", "Error_Site_URL_description": "कृपया, अपनी \"साइट_यूआरएल\" सेटिंग अपडेट करें और अधिक जानकारी पाएं [यहां](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "पासवर्ड बदलने में त्रुटि", diff --git a/packages/i18n/src/locales/hr.i18n.json b/packages/i18n/src/locales/hr.i18n.json index 4ddf9275ab148..b8e3657681442 100644 --- a/packages/i18n/src/locales/hr.i18n.json +++ b/packages/i18n/src/locales/hr.i18n.json @@ -979,8 +979,6 @@ "Entertainment": "Zabava", "Error": "Pogreška", "Error_404": "Pogreška: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Pogreška: Rocket.Chat zahtijeva oplog repanje kada se izvodi u više slučajeva", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Provjerite je li vaš MongoDB na načinu ReplicaSet i da je varijabla okruženja MONGO_OPLOG_URL pravilno definirana na aplikacijskom poslužitelju", "Error_changing_password": "Greška pri izmjeni lozinke", "Error_loading_pages": "Pogreška prilikom učitavanja stranica", "Esc_to": "Esc za", diff --git a/packages/i18n/src/locales/hu.i18n.json b/packages/i18n/src/locales/hu.i18n.json index f517ea946834c..77b3355d9bef7 100644 --- a/packages/i18n/src/locales/hu.i18n.json +++ b/packages/i18n/src/locales/hu.i18n.json @@ -1575,8 +1575,6 @@ "Entertainment": "Szórakozás", "Error": "Hiba", "Error_404": "Hiba: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Hiba: a Rocket.Chat a műveleti napló megfigyelését igényli a több példányban történő futtatáskor", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Győződjön meg arról, hogy a MongoDB ReplicaSet módban legyen, és a MONGO_OPLOG_URL környezeti változó helyesen legyen meghatározva az alkalmazáskiszolgálón", "Error_Site_URL": "Érvénytelen „Site_Url”", "Error_Site_URL_description": "Frissítse a „Site_Url” beállítást, további információkat [itt találhat](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Hiba a jelszó megváltoztatáskor", diff --git a/packages/i18n/src/locales/id.i18n.json b/packages/i18n/src/locales/id.i18n.json index facac25d7069c..d21db5078a70b 100644 --- a/packages/i18n/src/locales/id.i18n.json +++ b/packages/i18n/src/locales/id.i18n.json @@ -863,8 +863,6 @@ "Entertainment": "Hiburan", "Error": "Kesalahan", "Error_404": "Kesalahan 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Kesalahan: Rocket.Chat membutuhkan oplog tailing saat berjalan dalam beberapa contoh", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Pastikan MongoDB Anda ada pada mode ReplicaSet dan variabel lingkungan MONGO_OPLOG_URL didefinisikan dengan benar di server aplikasi.", "Error_changing_password": "Terjadi kesalahan ketika merubah kata sandi", "Error_loading_pages": "Terjadi kesalahan saat memuat halaman", "Esc_to": "Keluar ke", diff --git a/packages/i18n/src/locales/it.i18n.json b/packages/i18n/src/locales/it.i18n.json index 0e97d59009f76..89a9aaf101707 100644 --- a/packages/i18n/src/locales/it.i18n.json +++ b/packages/i18n/src/locales/it.i18n.json @@ -1125,8 +1125,6 @@ "Entertainment": "Divertimento", "Error": "Errore", "Error_404": "Errore 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Errore: Rocket.Chat richiede la coda oplog quando in esecuzione su diverse instanze", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Verifica che il tuo MongoDB è in modalità ReplicaSet e la variabile di sistema MONGO_OPLOG_URL è definita correttamente sul server dell'applicativo", "Error_changing_password": "Errore nel cambio password", "Error_loading_pages": "Errore durante il caricamento delle pagine", "Esc_to": "Esc per", diff --git a/packages/i18n/src/locales/ja.i18n.json b/packages/i18n/src/locales/ja.i18n.json index fea01bd07f297..686b13e8f7cd5 100644 --- a/packages/i18n/src/locales/ja.i18n.json +++ b/packages/i18n/src/locales/ja.i18n.json @@ -1442,8 +1442,6 @@ "Entertainment": "エンターテインメント", "Error": "エラー", "Error_404": "エラー404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "エラー:Rocket.Chatでは、複数のインスタンスでの実行時にoplog tailingが必要です", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "MongoDBがReplicaSetモードであり、MONGO_OPLOG_URL環境変数がアプリケーションサーバー上で正しく定義されていることを確認してください", "Error_Site_URL": "無効なSite_Url", "Error_Site_URL_description": "「Site_Url」設定を更新し、詳細情報を[こちら](https://go.rocket.chat/i/invalid-site-url)で見つけてください", "Error_changing_password": "パスワードの変更中にエラーが発生しました", diff --git a/packages/i18n/src/locales/ka-GE.i18n.json b/packages/i18n/src/locales/ka-GE.i18n.json index d206f5a4bfd80..0fcce8d28fc9f 100644 --- a/packages/i18n/src/locales/ka-GE.i18n.json +++ b/packages/i18n/src/locales/ka-GE.i18n.json @@ -1169,8 +1169,6 @@ "Entertainment": "გართობა", "Error": "შეცდომა", "Error_404": "შეცდომა: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "შეცდომა: Rocket.Chat მოითხოვს ოპლოგის დაბოლოებას ხშირ შემთხვევაში", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "გთხოვთ დარწმუნდეთ, რომ თქვენი MongoDB ჩართულია ReplicaSet რეჟიმში და MONGO_OPLOG_URL გარემოს ცვლადი სწორად არის განსაზღვრული პროგრამის სერვერზე", "Error_Site_URL": "ვებგვერდის მისამართი არასწორია", "Error_Site_URL_description": "გთხოვთ, განაახლოთ თქვენი \"Site_Url\" პარამეტრები, იხილეთ მეტი ინფორმაცია [ აქ ](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": " შეცდომა პაროლის შეცვლისას", diff --git a/packages/i18n/src/locales/km.i18n.json b/packages/i18n/src/locales/km.i18n.json index 88decac3a1631..b2c8f0dada384 100644 --- a/packages/i18n/src/locales/km.i18n.json +++ b/packages/i18n/src/locales/km.i18n.json @@ -1065,8 +1065,6 @@ "Entertainment": "ការកំសាន្ត", "Error": "កំហុសក្នុងការ", "Error_404": "កំហុស: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "កំហុស: Rocket.Chat តម្រូវឱ្យមានកន្ទុយអុកនៅពេលកំពុងរត់ក្នុងករណីច្រើន", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "សូមប្រាកដថាម៉ុង MongDB របស់អ្នកស្ថិតនៅលើទម្រង់ ReplicaSet ហើយអថេរបរិស្ថាន MONGO_OPLOG_URL ត្រូវបានកំណត់យ៉ាងត្រឹមត្រូវលើម៉ាស៊ីនមេ។", "Error_changing_password": "ពាក្យ​សម្ងាត់​បាន​ប្តូរ", "Error_loading_pages": "មានកំហុសក្នុងការផ្ទុកទំព័រ", "Error_sending_livechat_offline_message": "កំហុសពេលកំពុងផ្ញើរសារ Livechat ក្រៅបណ្តាញ", diff --git a/packages/i18n/src/locales/ko.i18n.json b/packages/i18n/src/locales/ko.i18n.json index 8ad834a9ffcee..579a3f4bdd40b 100644 --- a/packages/i18n/src/locales/ko.i18n.json +++ b/packages/i18n/src/locales/ko.i18n.json @@ -1290,8 +1290,6 @@ "Entertainment": "엔터테인먼트", "Error": "오류", "Error_404": "오류: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "오류 : 여러 인스턴스에서 실행할 때 Rocket.Chat에서 oplog tailing이 필요합니다.", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "MongoDB가 ReplicaSet 모드에 있고 MONGO_OPLOG_URL 환경 변수가 응용 프로그램 서버에 올바르게 정의되어 있는지 확인하십시오.", "Error_Site_URL": "유효하지 않은 Site_Url", "Error_Site_URL_description": "\"Site_Url\"설정을 업데이트하여 자세한 정보를 찾으십시오. [ 여기 ](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "비밀번호 변경 중 오류 발생", diff --git a/packages/i18n/src/locales/ku.i18n.json b/packages/i18n/src/locales/ku.i18n.json index c467f5323b86f..6e6c4d14bba53 100644 --- a/packages/i18n/src/locales/ku.i18n.json +++ b/packages/i18n/src/locales/ku.i18n.json @@ -861,8 +861,6 @@ "Entertainment": "Axaftin", "Error": "Şaşî", "Error_404": "Çewt: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Çewtiya: Rocket. Dema ku di gelek rewşan de diçin dema hewlkirina oplogê hewce dike", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Ji kerema xwe re bisekinin ku MongoDB di modela ReplicaSet de ye û mongo_OPLOG_URL pîvana hawirdora rasteqîn li ser serverê pirtûk hatiye diyarkirin.", "Error_changing_password": "هەڵە ڕوویدا لە گۆڕینی تێپەڕەوشە", "Error_loading_pages": "Error pages loading", "Esc_to": "Esc to", diff --git a/packages/i18n/src/locales/lo.i18n.json b/packages/i18n/src/locales/lo.i18n.json index 2af8401d90444..cb1678379d699 100644 --- a/packages/i18n/src/locales/lo.i18n.json +++ b/packages/i18n/src/locales/lo.i18n.json @@ -886,8 +886,6 @@ "Entertainment": "ຄວາມບັນເທີງ", "Error": "Error", "Error_404": "ຂໍ້ຜິດພາດ: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "ຂໍ້ຜິດພາດ: RocketChat ຮຽກຮ້ອງ oplog tailing ໃນເວລາທີ່ແລ່ນໃນຫຼາຍໆກໍລະນີ", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "ກະລຸນາໃຫ້ແນ່ໃຈວ່າ MongoDB ຂອງທ່ານຢູ່ໃນຮູບແບບ ReplicaSet ແລະ MONGO_OPLOG_URL ຕົວແປສະພາບແວດລ້ອມຖືກກໍານົດຢ່າງຖືກຕ້ອງໃນເຄື່ອງແມ່ຂ່າຍຂອງແອັບພລິເຄຊັນ", "Error_changing_password": "Error ລະຫັດຜ່ານການປ່ຽນແປງ", "Error_loading_pages": "Error loading pages", "Esc_to": "Esc ກັບ", diff --git a/packages/i18n/src/locales/lt.i18n.json b/packages/i18n/src/locales/lt.i18n.json index 26c77c84ab205..3b21cc8197911 100644 --- a/packages/i18n/src/locales/lt.i18n.json +++ b/packages/i18n/src/locales/lt.i18n.json @@ -912,8 +912,6 @@ "Entertainment": "Pramogos", "Error": "Klaida", "Error_404": "Klaida: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Klaida: \"Rocket.Chat\" reikalauja \"oplog tailing\" paleidžiant kelis kartus", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Įsitikinkite, kad jūsų MongoDB yra \"ReplicaSet\" režime, o aplinkos kintamasis MONGO_OPLOG_URL yra tinkamai apibrėžtas programų serveryje", "Error_changing_password": "Klaida pakeičiant slaptažodį", "Error_loading_pages": "Įkeliant puslapius įvyko klaida", "Esc_to": "Esc į", diff --git a/packages/i18n/src/locales/lv.i18n.json b/packages/i18n/src/locales/lv.i18n.json index 99161e3f78d6b..b3f3c766f02ba 100644 --- a/packages/i18n/src/locales/lv.i18n.json +++ b/packages/i18n/src/locales/lv.i18n.json @@ -877,8 +877,6 @@ "Entertainment": "Izklaide", "Error": "Kļūda", "Error_404": "Kļūda: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Kļūda: Rocket.Chat prasa oplog tailing, kad darbojas vairākos gadījumos", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Lūdzu, pārliecinieties, ka jūsu MongoDB ir iekļauts ReplicaSet režīmā, un vides mainīgais MONGO_OPLOG_URL ir pareizi noteikts pieteikumu serverī.", "Error_changing_password": "Mainot paroli, radās kļūda", "Error_loading_pages": "Ielādējot lapas, radās kļūda", "Esc_to": "Esc uz", diff --git a/packages/i18n/src/locales/mn.i18n.json b/packages/i18n/src/locales/mn.i18n.json index 0038b53ac8705..b2130cf9e39f5 100644 --- a/packages/i18n/src/locales/mn.i18n.json +++ b/packages/i18n/src/locales/mn.i18n.json @@ -863,8 +863,6 @@ "Entertainment": "Үзвэр үйлчилгээ", "Error": "Алдаа", "Error_404": "Алдаа: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Алдаа: Rocket.Chat олон тохиолдол дээр ажиллаж байхдаа oplog tailing шаарддаг", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "MongoDB нь ReplicaSet горимд байгаа эсэхийг шалгаарай, мөн MONGO_OPLOG_URL орчны хувьсагч нь програмын сервер дээр зөвөөр тодорхойлогдсон эсэхийг шалгана уу.", "Error_changing_password": "Нууц үгийг өөрчлөх алдаа", "Error_loading_pages": "Хуудсыг ачаалах алдаа", "Esc_to": "Esc руу", diff --git a/packages/i18n/src/locales/ms-MY.i18n.json b/packages/i18n/src/locales/ms-MY.i18n.json index 1350515fab24c..6359616b6f148 100644 --- a/packages/i18n/src/locales/ms-MY.i18n.json +++ b/packages/i18n/src/locales/ms-MY.i18n.json @@ -866,8 +866,6 @@ "Entertainment": "Hiburan", "Error": "ralat", "Error_404": "Ralat: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Ralat: Rocket.Chat memerlukan tailing oplog apabila berjalan dalam beberapa keadaan", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Sila pastikan MongoDB anda berada pada mod ReplicaSet dan pembolehubah persekitaran MONGO_OPLOG_URL ditakrifkan dengan betul pada pelayan aplikasi", "Error_changing_password": "Ralat menukar kata laluan", "Error_loading_pages": "Ralat memuatkan halaman", "Esc_to": "Esc untuk", diff --git a/packages/i18n/src/locales/nb.i18n.json b/packages/i18n/src/locales/nb.i18n.json index 381ff716a5e12..fac1ddb285c0f 100644 --- a/packages/i18n/src/locales/nb.i18n.json +++ b/packages/i18n/src/locales/nb.i18n.json @@ -2057,8 +2057,6 @@ "Entertainment": "Underholdning", "Error": "Feil", "Error_404": "Feilmelding: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Feil: Rocket.Chat krever oplog-tailing når den kjøres i flere instanser", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Sørg for at MongoDB er i ReplicaSet-modus og at MONGO_OPLOG_URL miljøvariabelen er riktig definert på applikasjonsserveren", "Error_Site_URL": "Ugyldig Site_Url", "Error_Site_URL_description": "Vennligst oppdater \"Site_Url\"-innstillingen, finn mer informasjon [her](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Feil ved endring av passord", diff --git a/packages/i18n/src/locales/nl.i18n.json b/packages/i18n/src/locales/nl.i18n.json index 46f1cc2e4dfcb..536b88da0f702 100644 --- a/packages/i18n/src/locales/nl.i18n.json +++ b/packages/i18n/src/locales/nl.i18n.json @@ -1454,8 +1454,6 @@ "Entertainment": "Vermaak", "Error": "Fout", "Error_404": "Foutmelding 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Fout: Rocket.Chat vereist oplog-tailing wanneer het op meerdere instanties wordt uitgevoerd", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Zorg ervoor dat uw MongoDB in de ReplicaSet-modus staat en de omgevingsvariabele MONGO_OPLOG_URL correct is gedefinieerd op de applicatieserver", "Error_Site_URL": "Ongeldige Site_Url", "Error_Site_URL_description": "Werk alstublieft uw \"Site_Url\"-instelling bij. Vind [hier ](https://go.rocket.chat/i/invalid-site-url) meer informatie", "Error_changing_password": "Fout bij het wijzigen van wachtwoord", diff --git a/packages/i18n/src/locales/nn.i18n.json b/packages/i18n/src/locales/nn.i18n.json index aaefec0ecdcf0..c2a6f6e8ee1ea 100644 --- a/packages/i18n/src/locales/nn.i18n.json +++ b/packages/i18n/src/locales/nn.i18n.json @@ -1901,8 +1901,6 @@ "Entertainment": "Underholdning", "Error": "Feil", "Error_404": "Feil: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Feil: Rocket.Chat krever oplog tailing når du kjører i flere tilfeller", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Sørg for at MongoDB er på ReplicaSet-modus og MONGO_OPLOG_URL miljøvariabel er definert riktig på applikasjonsserveren", "Error_Site_URL": "Ugyldig Site_Url", "Error_Site_URL_description": "Vennligst oppdater \"Site_Url\"-innstillingen, finn mer informasjon [her](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Feil ved endring av passord", diff --git a/packages/i18n/src/locales/pl.i18n.json b/packages/i18n/src/locales/pl.i18n.json index 1a82977562428..7cb4d4b9ce8b4 100644 --- a/packages/i18n/src/locales/pl.i18n.json +++ b/packages/i18n/src/locales/pl.i18n.json @@ -1594,8 +1594,6 @@ "Entertainment": "Rozrywka", "Error": "Błąd", "Error_404": "Błąd 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Błąd: Rocket.Chat wymaga oględzin oplog podczas uruchamiania w wielu instancjach", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Upewnij się, że MongoDB jest w trybie ReplicaSet, a zmienna środowiskowa MONGO_OPLOG_URL jest poprawnie zdefiniowana na serwerze aplikacji", "Error_Site_URL": "Niepoprawny Site_Url", "Error_Site_URL_description": "Zaktualizuj ustawienia \"Site_Url\". Więcej informacji znajdziesz [tutaj](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Błąd zmiany hasła", diff --git a/packages/i18n/src/locales/pt-BR.i18n.json b/packages/i18n/src/locales/pt-BR.i18n.json index 844e3cf0d6876..87ac94a8c4baa 100644 --- a/packages/i18n/src/locales/pt-BR.i18n.json +++ b/packages/i18n/src/locales/pt-BR.i18n.json @@ -1935,8 +1935,6 @@ "Entertainment": "Entretenimento", "Error": "Erro", "Error_404": "Erro 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Erro: Rocket.Chat requer oplog tailing quando executado em várias instâncias", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Certifique-se de que seu MongoDB esteja no modo ReplicaSet e a variável de ambiente MONGO_OPLOG_URL esteja definida corretamente no servidor de aplicativos", "Error_Site_URL": "Site_Url inválido", "Error_Site_URL_description": "Atualize sua configuração \"Site_Url\". Saiba mais [aqui](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Erro ao alterar senha", diff --git a/packages/i18n/src/locales/pt.i18n.json b/packages/i18n/src/locales/pt.i18n.json index 747663407d5fa..b8315c14e2f58 100644 --- a/packages/i18n/src/locales/pt.i18n.json +++ b/packages/i18n/src/locales/pt.i18n.json @@ -1043,8 +1043,6 @@ "Entertainment": "Entretenimento", "Error": "Erro", "Error_404": "Erro:404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Erro: Rocket.Chat requer oplog tailing quando executado em várias instâncias", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Certifique-se de que seu MongoDB esteja no modo ReplicaSet e a variável de ambiente MONGO_OPLOG_URL esteja definida corretamente no servidor de aplicativos", "Error_changing_password": "Erro ao alterar palavra-passe", "Error_loading_pages": "Erro ao carregar páginas", "Error_sending_livechat_offline_message": "Erro ao enviar mensagem offline do Livechat", diff --git a/packages/i18n/src/locales/ro.i18n.json b/packages/i18n/src/locales/ro.i18n.json index 8f0ac8dba714f..37a7dd75a07b1 100644 --- a/packages/i18n/src/locales/ro.i18n.json +++ b/packages/i18n/src/locales/ro.i18n.json @@ -864,8 +864,6 @@ "Entertainment": "Divertisment", "Error": "Eroare", "Error_404": "Eroare 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Eroare: Rocket.Chat necesită tăiere oplog atunci când rulează în mai multe instanțe", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Asigurați-vă că MongoDB este în modul ReplicaSet și că variabila de mediu MONGO_OPLOG_URL este definită corect pe serverul de aplicații", "Error_changing_password": "Eroare la schimbarea parolei", "Error_loading_pages": "Eroare la încărcarea paginilor", "Esc_to": "Esc pentru a", diff --git a/packages/i18n/src/locales/ru.i18n.json b/packages/i18n/src/locales/ru.i18n.json index 902658f65a3df..bfdbedf830a48 100644 --- a/packages/i18n/src/locales/ru.i18n.json +++ b/packages/i18n/src/locales/ru.i18n.json @@ -1558,8 +1558,6 @@ "Entertainment": "Развлечения", "Error": "Ошибка", "Error_404": "Ошибка 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Ошибка: требуется слежение за Oplog при запуске Rocket.Chat на виртуальных машинах", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Пожалуйста, убедитесь, что ваш MongoDB находится в режиме ReplicaSet, а переменная среды MONGO_OPLOG_URL правильно определена на сервере приложений.", "Error_Site_URL": "Недействительный Site_Url", "Error_Site_URL_description": "Обновите настройку \"Site_Url\", чтобы найти дополнительную информацию [здесь](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Ошибка при изменении пароля", diff --git a/packages/i18n/src/locales/sk-SK.i18n.json b/packages/i18n/src/locales/sk-SK.i18n.json index bc4ad81b8ba2a..6a52906be4c78 100644 --- a/packages/i18n/src/locales/sk-SK.i18n.json +++ b/packages/i18n/src/locales/sk-SK.i18n.json @@ -871,8 +871,6 @@ "Entertainment": "zábava", "Error": "Chyba", "Error_404": "Chyba: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Chyba: Rocket.Chat vyžaduje oplog tailing pri spustení vo viacerých inštanciách", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Uistite sa, že váš MongoDB je v režime ReplicaSet a že premenná prostredia MONGO_OPLOG_URL je správne definovaná na aplikačnom serveri", "Error_changing_password": "Chyba pri zmene hesla", "Error_loading_pages": "Chyba pri načítavaní stránok", "Esc_to": "Esc to", diff --git a/packages/i18n/src/locales/sl-SI.i18n.json b/packages/i18n/src/locales/sl-SI.i18n.json index fb738e0282d44..0ce7963e5c8e8 100644 --- a/packages/i18n/src/locales/sl-SI.i18n.json +++ b/packages/i18n/src/locales/sl-SI.i18n.json @@ -860,8 +860,6 @@ "Entertainment": "Zabava", "Error": "Napaka", "Error_404": "Napaka: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Napaka: Rocket.Chat zahteva oplog tailing, ko teče na več primerih", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Poskrbite, da je naš MongoDB v načinu ReplicaSet in da je spremenljivka okolja MONGO_OPLOG_URL pravilno definirana na programskem strežniku", "Error_changing_password": "Napaka pri spreminjanju gesla", "Error_loading_pages": "Napaka pri nalaganju strani", "Esc_to": "Izhod na", diff --git a/packages/i18n/src/locales/sq.i18n.json b/packages/i18n/src/locales/sq.i18n.json index 79d83c53c7664..cb4ae1eda9764 100644 --- a/packages/i18n/src/locales/sq.i18n.json +++ b/packages/i18n/src/locales/sq.i18n.json @@ -865,8 +865,6 @@ "Entertainment": "argëtim", "Error": "gabim", "Error_404": "Error: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Gabim: Rocket.Chat kërkon oplog tailing kur kandidon në raste të shumta", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Ju lutemi sigurohuni që MongoDB juaj është në modalitetin ReplicaSet dhe vargu i mjedisit MONGO_OPLOG_URL është përcaktuar saktë në serverin e aplikacionit", "Error_changing_password": "Ndodhi një gabim në ndryshimin e fjalëkalimit", "Error_loading_pages": "Gabim gjatë ngarkimit të faqeve", "Esc_to": "Esc për të", diff --git a/packages/i18n/src/locales/sr.i18n.json b/packages/i18n/src/locales/sr.i18n.json index 323697438cab3..991b0cc8837f2 100644 --- a/packages/i18n/src/locales/sr.i18n.json +++ b/packages/i18n/src/locales/sr.i18n.json @@ -768,8 +768,6 @@ "Entertainment": "Забава", "Error": "Грешка", "Error_404": "Грешка: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Грешка: Роцкет.Цхат захтева оплог таилинг када ради у више инстанци", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Проверите да ли је ваш МонгоДБ на режиму РеплицаСет, а варијабла окружења МОНГО_ОПЛОГ_УРЛ је исправно дефинирана на серверу апликација", "Error_changing_password": "Грешка приликом промене лозинке", "Error_loading_pages": "Грешка у учитавању страница", "Esc_to": "Есц да", diff --git a/packages/i18n/src/locales/sv.i18n.json b/packages/i18n/src/locales/sv.i18n.json index 8f81d9148e43a..efa521aba0832 100644 --- a/packages/i18n/src/locales/sv.i18n.json +++ b/packages/i18n/src/locales/sv.i18n.json @@ -1941,8 +1941,6 @@ "Entertainment": "Underhållning", "Error": "Fel", "Error_404": "Fel 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Fel: Rocket.Chat kräver upplogning när det körs i flera instanser", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Se till att din MongoDB är på ReplicaSet-läge och MONGO_OPLOG_URL miljövariabel definieras korrekt på applikationsservern", "Error_Site_URL": "Ogiltig Site_Url", "Error_Site_URL_description": "Uppdatera inställningen för \"Site_Url\". Du hittar mer information [här](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Fel vid byte av lösenord", diff --git a/packages/i18n/src/locales/ta-IN.i18n.json b/packages/i18n/src/locales/ta-IN.i18n.json index 88bd24cfe150d..cfb3cafcf1a96 100644 --- a/packages/i18n/src/locales/ta-IN.i18n.json +++ b/packages/i18n/src/locales/ta-IN.i18n.json @@ -863,8 +863,6 @@ "Entertainment": "பொழுதுபோக்கு", "Error": "பிழை", "Error_404": "பிழை: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "பிழை: பல நிகழ்வுகளில் இயங்கும் போது ராக்கெட்", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "தயவுசெய்து உங்கள் மோங்கோ DB என்பது ReplicaSet முறைமை மற்றும் MONGO_OPLOG_URL சூழல் மாறி பயன்பாட்டு சேவையகத்தில் சரியாக வரையறுக்கப்பட்டுள்ளது", "Error_changing_password": "கடவுச்சொல் மாற்றப்பட்டது", "Error_loading_pages": "பக்கங்களை ஏற்றுவதில் பிழை", "Esc_to": "esc விசையை", diff --git a/packages/i18n/src/locales/th-TH.i18n.json b/packages/i18n/src/locales/th-TH.i18n.json index ed4ddcbff76c2..dbed57f39603f 100644 --- a/packages/i18n/src/locales/th-TH.i18n.json +++ b/packages/i18n/src/locales/th-TH.i18n.json @@ -862,8 +862,6 @@ "Entertainment": "การบันเทิง", "Error": "ความผิดพลาด", "Error_404": "ข้อผิดพลาด: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "ข้อผิดพลาด: Rocket.Chat ต้องใช้งาน oplog tailing เมื่อทำงานในหลาย ๆ กรณี", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "โปรดตรวจสอบให้แน่ใจว่า MongoDB ของคุณอยู่ในโหมด ReplicaSet และ MONGO_OPLOG_URL ตัวแปรสภาพแวดล้อมถูกกำหนดไว้อย่างถูกต้องบนเซิร์ฟเวอร์แอ็พพลิเคชัน", "Error_changing_password": "เกิดข้อผิดพลาดในการเปลี่ยนรหัสผ่าน", "Error_loading_pages": "เกิดข้อผิดพลาดในการโหลดหน้าเว็บ", "Esc_to": "Esc ไปที่", diff --git a/packages/i18n/src/locales/tr.i18n.json b/packages/i18n/src/locales/tr.i18n.json index 154fcd48cc378..c18390f8d9e52 100644 --- a/packages/i18n/src/locales/tr.i18n.json +++ b/packages/i18n/src/locales/tr.i18n.json @@ -1053,8 +1053,6 @@ "Entertainment": "Eğlence", "Error": "Hata", "Error_404": "Hata:404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Hata: Rocket.Chat, birden çok örnekte çalışırken oplog tailing gerektirir", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Lütfen MongoDB'nizin ReplicaSet modunda olduğundan ve MONGO_OPLOG_URL ortam değişkeninin uygulama sunucusunda doğru tanımlandığından emin olun", "Error_Site_URL": "Geçersiz Site Bağlantısı", "Error_changing_password": "Şifre değiştirmede hata", "Error_loading_pages": "Sayfalar yüklenirken hata oluştu", diff --git a/packages/i18n/src/locales/uk.i18n.json b/packages/i18n/src/locales/uk.i18n.json index a917a483a5b05..454e7a7c8ab3b 100644 --- a/packages/i18n/src/locales/uk.i18n.json +++ b/packages/i18n/src/locales/uk.i18n.json @@ -1150,8 +1150,6 @@ "Entertainment": "Розваги", "Error": "Помилка", "Error_404": "Помилка: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Помилка: Rocket.Chat вимагає закриття при роботі в декількох випадках", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Будь ласка, переконайтеся, що ваш MongoDB знаходиться в режимі ReplicaSet, і змінна середовища MONGO_OPLOG_URL правильно визначена на сервері додатків", "Error_Site_URL": "Недійсний Site_Url", "Error_Site_URL_description": "Оновіть будь-ласка Ваші налаштування \"Site_Url\", знайдіть більше інформації [тут](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Пароль змінено", diff --git a/packages/i18n/src/locales/vi-VN.i18n.json b/packages/i18n/src/locales/vi-VN.i18n.json index 1cbf7609bbac1..51a160596ae4a 100644 --- a/packages/i18n/src/locales/vi-VN.i18n.json +++ b/packages/i18n/src/locales/vi-VN.i18n.json @@ -957,8 +957,6 @@ "Entertainment": "Giải trí", "Error": "lỗi", "Error_404": "Lỗi: 404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Lỗi: Rocket.Chat yêu cầu oplog tailing khi chạy trong nhiều trường hợp", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Hãy đảm bảo rằng MongoDB của bạn ở chế độ ReplicaSet và biến môi trường MONGO_OPLOG_URL được định nghĩa chính xác trên máy chủ ứng dụng", "Error_changing_password": "Lỗi khi thay đổi mật khẩu", "Error_loading_pages": "Lỗi khi tải trang", "Esc_to": "Esc để", diff --git a/packages/i18n/src/locales/zh-HK.i18n.json b/packages/i18n/src/locales/zh-HK.i18n.json index 547d0fad75e49..3ba37f7611ea7 100644 --- a/packages/i18n/src/locales/zh-HK.i18n.json +++ b/packages/i18n/src/locales/zh-HK.i18n.json @@ -882,8 +882,6 @@ "Entertainment": "娱乐", "Error": "错误", "Error_404": "错误:404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "错误:Rocket.Chat在多个实例中运行时需要oplog拖尾", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "请确保您的MongoDB处于ReplicaSet模式,并且MONGO_OPLOG_URL环境变量已在应用程序服务器上正确定义", "Error_changing_password": "密码更改失败", "Error_loading_pages": "加载页面时出错", "Esc_to": "退出", diff --git a/packages/i18n/src/locales/zh-TW.i18n.json b/packages/i18n/src/locales/zh-TW.i18n.json index 560bfbfe7fd26..e60f3308788be 100644 --- a/packages/i18n/src/locales/zh-TW.i18n.json +++ b/packages/i18n/src/locales/zh-TW.i18n.json @@ -1442,8 +1442,6 @@ "Entertainment": "娛樂", "Error": "錯誤", "Error_404": "錯誤:404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "錯誤:Rocket.Chat在多個實例中運行時需要oplog拖尾", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "請確保您的MongoDB處於ReplicaSet模式,並且MONGO_OPLOG_URL環境變量已在應用程序服務器上正確定義", "Error_Site_URL": "無效的 Site_Url", "Error_Site_URL_description": "請更新您的 \"Site_Url\" 設定且更多資訊在[這裡](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "密碼變更失敗", diff --git a/packages/i18n/src/locales/zh.i18n.json b/packages/i18n/src/locales/zh.i18n.json index 1c6e4c16a29e6..1b6e0086d0eda 100644 --- a/packages/i18n/src/locales/zh.i18n.json +++ b/packages/i18n/src/locales/zh.i18n.json @@ -2058,8 +2058,6 @@ "Entertainment": "娱乐", "Error": "错误", "Error_404": "错误:404", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "错误:Rocket.Chat 在多个实例中运行时需要 oplog 跟踪", - "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "请确保您的 MongoDB 处于 ReplicaSet 模式,并且 MONGO_OPLOG_URL 环境变量已在应用程序服务器上正确定义", "Error_Site_URL": "无效的 Site_Url", "Error_Site_URL_description": "请更新您的“Site_Url”设置。[在此获得更多信息](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "密码更改失败", From b490ed5768674858c511306b0a96984a2f59a2f0 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 9 Apr 2026 11:19:42 -0300 Subject: [PATCH 38/51] test(federation): fix display name test flakyness (#40085) --- .../tests/end-to-end/dms.spec.ts | 543 ++++++++++-------- 1 file changed, 309 insertions(+), 234 deletions(-) diff --git a/ee/packages/federation-matrix/tests/end-to-end/dms.spec.ts b/ee/packages/federation-matrix/tests/end-to-end/dms.spec.ts index 688655ee5be69..5aa85e92ce6a6 100644 --- a/ee/packages/federation-matrix/tests/end-to-end/dms.spec.ts +++ b/ee/packages/federation-matrix/tests/end-to-end/dms.spec.ts @@ -16,7 +16,7 @@ const waitForRoomEvent = async ( room: Room, eventType: RoomEmittedEvents, validateEvent: (event: MatrixEvent) => void, - timeoutMs = 5000, + timeoutMs = 15000, ) => { return withTimeout(async (signal) => { return new Promise((resolve, reject) => { @@ -61,6 +61,25 @@ const waitForRoomEvent = async ( // Create admin Synapse client for HS1 hs1AdminApp = new SynapseClient(federationConfig.hs1.url, federationConfig.hs1.adminUser, federationConfig.hs1.adminPassword); await hs1AdminApp.initialize(); + + // Ensure the Synapse admin display name is reset to the expected value. + // A previous test run may have left it dirty if the "Display name changes" + // afterAll cleanup failed (federation propagation is inherently unreliable). + await hs1AdminApp.matrixClient.setDisplayName(federationConfig.hs1.adminUser); + + await retry( + 'waiting for Synapse admin displayname to be reset', + async () => { + const response = await rc1AdminRequestConfig.request + .get(api('users.info')) + .set(rc1AdminRequestConfig.credentials) + .query({ username: federationConfig.hs1.adminMatrixUserId }) + .expect(200); + + expect(response.body.user).toHaveProperty('name', federationConfig.hs1.adminUser); + }, + { retries: 5, delayMs: 1000 }, + ); }); afterAll(async () => { @@ -110,24 +129,28 @@ const waitForRoomEvent = async ( expect(hs1Room).toHaveProperty('roomId'); - await retry('this is an async operation, so we need to wait for the room to be created in RC', async () => { - const roomsResponse = await rcUserConfig.request.get(api('rooms.get')).set(rcUserConfig.credentials).expect(200); + await retry( + 'this is an async operation, so we need to wait for the room to be created in RC', + async () => { + const roomsResponse = await rcUserConfig.request.get(api('rooms.get')).set(rcUserConfig.credentials).expect(200); - expect(roomsResponse.body).toHaveProperty('success', true); - expect(roomsResponse.body).toHaveProperty('update'); + expect(roomsResponse.body).toHaveProperty('success', true); + expect(roomsResponse.body).toHaveProperty('update'); - rcRoom = roomsResponse.body.update.find((room: IRoomNativeFederated) => room.federation.mrid === hs1Room.roomId); + rcRoom = roomsResponse.body.update.find((room: IRoomNativeFederated) => room.federation.mrid === hs1Room.roomId); - expect(rcRoom).toHaveProperty('_id'); - expect(rcRoom).toHaveProperty('t', 'd'); - expect(rcRoom).toHaveProperty('uids'); - expect(rcRoom).not.toHaveProperty('fname'); + expect(rcRoom).toHaveProperty('_id'); + expect(rcRoom).toHaveProperty('t', 'd'); + expect(rcRoom).toHaveProperty('uids'); + expect(rcRoom).not.toHaveProperty('fname'); - subscriptionInvite = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); + subscriptionInvite = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); - expect(subscriptionInvite).toHaveProperty('status', 'INVITED'); - expect(subscriptionInvite).toHaveProperty('fname', federationConfig.hs1.adminUser); - }); + expect(subscriptionInvite).toHaveProperty('status', 'INVITED'); + expect(subscriptionInvite).toHaveProperty('fname', federationConfig.hs1.adminUser); + }, + { retries: 5, delayMs: 1000 }, + ); }); it('should accept the DM invitation from rc', async () => { @@ -181,7 +204,7 @@ const waitForRoomEvent = async ( expect(roomInfo.room?.usernames).toHaveLength(1); expect(roomInfo.room?.usernames).toEqual([rcUser.username]); }, - { delayMs: 100 }, + { retries: 15, delayMs: 2000 }, ); }); }); @@ -221,23 +244,27 @@ const waitForRoomEvent = async ( expect(hs1Room).toHaveProperty('roomId'); - await retry('this is an async operation, so we need to wait for the room to be created in RC', async () => { - const roomsResponse = await rcUserConfig.request.get(api('rooms.get')).set(rcUserConfig.credentials).expect(200); - expect(roomsResponse.body).toHaveProperty('success', true); - expect(roomsResponse.body).toHaveProperty('update'); + await retry( + 'this is an async operation, so we need to wait for the room to be created in RC', + async () => { + const roomsResponse = await rcUserConfig.request.get(api('rooms.get')).set(rcUserConfig.credentials).expect(200); + expect(roomsResponse.body).toHaveProperty('success', true); + expect(roomsResponse.body).toHaveProperty('update'); - rcRoom = roomsResponse.body.update.find((room: IRoomNativeFederated) => room.federation.mrid === hs1Room.roomId); + rcRoom = roomsResponse.body.update.find((room: IRoomNativeFederated) => room.federation.mrid === hs1Room.roomId); - expect(rcRoom).toHaveProperty('_id'); - expect(rcRoom).toHaveProperty('t', 'd'); - expect(rcRoom).toHaveProperty('uids'); - expect(rcRoom).not.toHaveProperty('fname'); + expect(rcRoom).toHaveProperty('_id'); + expect(rcRoom).toHaveProperty('t', 'd'); + expect(rcRoom).toHaveProperty('uids'); + expect(rcRoom).not.toHaveProperty('fname'); - subscriptionInvite = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); + subscriptionInvite = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); - expect(subscriptionInvite).toHaveProperty('status', 'INVITED'); - expect(subscriptionInvite).toHaveProperty('fname', federationConfig.hs1.adminUser); - }); + expect(subscriptionInvite).toHaveProperty('status', 'INVITED'); + expect(subscriptionInvite).toHaveProperty('fname', federationConfig.hs1.adminUser); + }, + { retries: 5, delayMs: 1000 }, + ); }); it('should accept the DM invitation from rc', async () => { @@ -286,99 +313,6 @@ const waitForRoomEvent = async ( await leaveEventPromise; }); }); - - describe('Display name changes', () => { - let rcUser: TestUser; - let rcUserConfig: IRequestConfig; - let hs1Room: Room; - let rcRoom: IRoom; - - const userDm = `dm-federation-displayname-user-${Date.now()}`; - const userDmId = `@${userDm}:${federationConfig.rc1.domain}`; - const initialDisplayName = `DM User ${Date.now()}`; - const updatedDisplayName = `Updated Display Name ${Date.now()}`; - - beforeAll(async () => { - rcUser = await createUser( - { - username: userDm, - password: 'random', - email: `${userDm}@rocket.chat`, - name: initialDisplayName, - }, - rc1AdminRequestConfig, - ); - - rcUserConfig = await getRequestConfig(federationConfig.rc1.url, rcUser.username, 'random'); - - hs1Room = (await hs1AdminApp.createDM([userDmId])) as Room; - - await retry('waiting for the room to be created in RC', async () => { - const roomsResponse = await rcUserConfig.request.get(api('rooms.get')).set(rcUserConfig.credentials).expect(200); - - rcRoom = roomsResponse.body.update.find((room: IRoomNativeFederated) => room.federation.mrid === hs1Room.roomId); - - expect(rcRoom).toHaveProperty('_id'); - }); - }); - - afterAll(async () => { - // Reset display name back to original before deleting the user - await hs1AdminApp.matrixClient.setDisplayName(federationConfig.hs1.adminUser); - - // wait until the name change is reflected in RC before finishing the test - await retry( - 'waiting for Synapse user displayname to propagate to RC', - async () => { - const response = await rc1AdminRequestConfig.request - .get(api('users.info')) - .set(rc1AdminRequestConfig.credentials) - .query({ username: federationConfig.hs1.adminMatrixUserId }) - .expect(200); - - expect(response.body.user).toHaveProperty('name', federationConfig.hs1.adminUser); - }, - { retries: 15, delayMs: 1000 }, - ); - - // Also wait for the DM subscription fname to be updated, since this propagates - // asynchronously after the user name change via debounced Room.updateDirectMessageRoomName - await retry( - 'waiting for subscription fname to reflect reset display name', - async () => { - const sub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); - expect(sub).toHaveProperty('fname', federationConfig.hs1.adminUser); - }, - { retries: 10, delayMs: 1000 }, - ); - - await deleteUser(rcUser, {}, rc1AdminRequestConfig); - }); - - it('should accept the DM invitation from RC', async () => { - const response = await acceptRoomInvite(rcRoom._id, rcUserConfig); - expect(response.success).toBe(true); - }); - - it('should update DM room name after Synapse user changes their display name', async () => { - // Verify initial state: room name should be the Synapse admin initial display name - const initialSub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); - expect(initialSub).toHaveProperty('fname', federationConfig.hs1.adminUser); - - // Action: update the Synapse user's displayname - await hs1AdminApp.matrixClient.setDisplayName(updatedDisplayName); - - // Verify: the DM room name should be updated after the debounced name update completes - await retry( - 'waiting for DM room name to be updated after display name change', - async () => { - const updatedSub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); - expect(updatedSub).toHaveProperty('fname', updatedDisplayName); - }, - { delayMs: 1000 }, - ); - }); - }); }); describe('Rocket.Chat as the resident server', () => { @@ -448,24 +382,32 @@ const waitForRoomEvent = async ( expect(rcRoom).toHaveProperty('federation.mrid'); // Wait for the room to appear in Synapse - await retry('this is an async operation, so we need to wait for the room to be created in Synapse', async () => { - hs1Room = (await hs1User.matrixClient.getRoom(rcRoom.federation.mrid)) as Room; + await retry( + 'this is an async operation, so we need to wait for the room to be created in Synapse', + async () => { + hs1Room = (await hs1User.matrixClient.getRoom(rcRoom.federation.mrid)) as Room; - expect(hs1Room).toBeDefined(); - expect(hs1Room.getMyMembership()).toBe('invite'); - }); + expect(hs1Room).toBeDefined(); + expect(hs1Room.getMyMembership()).toBe('invite'); + }, + { retries: 5, delayMs: 1000 }, + ); }); it('should display the fname properly after reject the invitation', async () => { // Reject the invitation from Synapse await hs1User.matrixClient.leave(hs1Room.roomId); - await retry('this is an async operation, so we need to wait for the rejection to be processed', async () => { - const sub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); + await retry( + 'this is an async operation, so we need to wait for the rejection to be processed', + async () => { + const sub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); - expect(sub).toHaveProperty('name', userDm); - expect(sub).toHaveProperty('fname', userDmName); - }); + expect(sub).toHaveProperty('name', userDm); + expect(sub).toHaveProperty('fname', userDmName); + }, + { retries: 5, delayMs: 1000 }, + ); }); }); @@ -491,33 +433,45 @@ const waitForRoomEvent = async ( rcRoom = roomInfo.room as IRoomNativeFederated; // Wait for invitation in Synapse - await retry('waiting for room invitation', async () => { - const room = await hs1User.matrixClient.getRoom(rcRoom.federation.mrid); + await retry( + 'waiting for room invitation', + async () => { + const room = await hs1User.matrixClient.getRoom(rcRoom.federation.mrid); - expect(room).toBeDefined(); - expect(room!.getMyMembership()).toBe('invite'); - }); + expect(room).toBeDefined(); + expect(room!.getMyMembership()).toBe('invite'); + }, + { retries: 5, delayMs: 1000 }, + ); // Accept the invitation await hs1User.matrixClient.joinRoom(rcRoom.federation.mrid); - await retry('this is an async operation, so we need to wait for the join to be processed', async () => { - const sub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); + await retry( + 'this is an async operation, so we need to wait for the join to be processed', + async () => { + const sub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); - // After acceptance, should display the Synapse user's ID - expect(sub).toHaveProperty('fname', federationConfig.hs1.additionalUser1.username); - }); + // After acceptance, should display the Synapse user's ID + expect(sub).toHaveProperty('fname', federationConfig.hs1.additionalUser1.username); + }, + { retries: 5, delayMs: 1000 }, + ); }); it('should allow the external user to leave the DM', async () => { // Synapse user leaves first await hs1User.matrixClient.leave(rcRoom.federation.mrid); - await retry('waiting for leave event to be processed', async () => { - const roomInfo = await getRoomInfo(rcRoom._id, rcUserConfig); + await retry( + 'waiting for leave event to be processed', + async () => { + const roomInfo = await getRoomInfo(rcRoom._id, rcUserConfig); - expect(roomInfo.room).toHaveProperty('usersCount', 1); - }); + expect(roomInfo.room).toHaveProperty('usersCount', 1); + }, + { retries: 5, delayMs: 1000 }, + ); }); it('should not allow to leave if the user is the only member', async () => { @@ -609,19 +563,23 @@ const waitForRoomEvent = async ( expect(hs1Room).toHaveProperty('roomId'); - await retry('this is an async operation, so we need to wait for the room to be created in RC', async () => { - const roomsResponse = await rcUserConfig1.request.get(api('rooms.get')).set(rcUserConfig1.credentials).expect(200); + await retry( + 'this is an async operation, so we need to wait for the room to be created in RC', + async () => { + const roomsResponse = await rcUserConfig1.request.get(api('rooms.get')).set(rcUserConfig1.credentials).expect(200); - expect(roomsResponse.body).toHaveProperty('success', true); - expect(roomsResponse.body).toHaveProperty('update'); + expect(roomsResponse.body).toHaveProperty('success', true); + expect(roomsResponse.body).toHaveProperty('update'); - rcRoom1 = roomsResponse.body.update.find((room: IRoomNativeFederated) => room.federation.mrid === hs1Room.roomId); + rcRoom1 = roomsResponse.body.update.find((room: IRoomNativeFederated) => room.federation.mrid === hs1Room.roomId); - expect(rcRoom1).toHaveProperty('_id'); - expect(rcRoom1).toHaveProperty('t', 'd'); - expect(rcRoom1).toHaveProperty('uids'); - expect(rcRoom1).not.toHaveProperty('fname'); - }); + expect(rcRoom1).toHaveProperty('_id'); + expect(rcRoom1).toHaveProperty('t', 'd'); + expect(rcRoom1).toHaveProperty('uids'); + expect(rcRoom1).not.toHaveProperty('fname'); + }, + { retries: 5, delayMs: 1000 }, + ); const membersBefore = await hs1Room.getMembers(); expect(membersBefore.length).toBe(3); @@ -675,7 +633,7 @@ const waitForRoomEvent = async ( expect(sub).toHaveProperty('name', `${federationConfig.hs1.adminMatrixUserId}, ${userDm2}`); expect(sub).toHaveProperty('fname', `${federationConfig.hs1.adminUser}, ${userDm2Name}`); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); }); @@ -698,7 +656,7 @@ const waitForRoomEvent = async ( expect(sub).toHaveProperty('name', userDm2); expect(sub).toHaveProperty('fname', userDm2Name); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); }); @@ -771,14 +729,18 @@ const waitForRoomEvent = async ( expect(response.body).toHaveProperty('success', true); // Verify room is no longer accessible to RC users - await retry('waiting for room cleanup', async () => { - const roomsResponse = await rcUserConfig1.request.get(api('rooms.get')).set(rcUserConfig1.credentials).expect(200); + await retry( + 'waiting for room cleanup', + async () => { + const roomsResponse = await rcUserConfig1.request.get(api('rooms.get')).set(rcUserConfig1.credentials).expect(200); - const room = roomsResponse.body.update?.find((r: IRoom) => r._id === rcRoom1._id); + const room = roomsResponse.body.update?.find((r: IRoom) => r._id === rcRoom1._id); - // Room should not be in active rooms list - expect(room).toBeUndefined(); - }); + // Room should not be in active rooms list + expect(room).toBeUndefined(); + }, + { retries: 5, delayMs: 1000 }, + ); }); }); @@ -831,19 +793,23 @@ const waitForRoomEvent = async ( expect(hs1RoomConverted).toHaveProperty('roomId'); - await retry('this is an async operation, so we need to wait for the room to be created in RC', async () => { - const roomsResponse = await rcUserConfigA.request.get(api('rooms.get')).set(rcUserConfigA.credentials).expect(200); + await retry( + 'this is an async operation, so we need to wait for the room to be created in RC', + async () => { + const roomsResponse = await rcUserConfigA.request.get(api('rooms.get')).set(rcUserConfigA.credentials).expect(200); - expect(roomsResponse.body).toHaveProperty('success', true); - expect(roomsResponse.body).toHaveProperty('update'); + expect(roomsResponse.body).toHaveProperty('success', true); + expect(roomsResponse.body).toHaveProperty('update'); - rcRoomConverted = roomsResponse.body.update.find( - (room: IRoomNativeFederated) => room.federation.mrid === hs1RoomConverted.roomId, - ); + rcRoomConverted = roomsResponse.body.update.find( + (room: IRoomNativeFederated) => room.federation.mrid === hs1RoomConverted.roomId, + ); - expect(rcRoomConverted).toHaveProperty('_id'); - expect(rcRoomConverted).toHaveProperty('t', 'd'); - }); + expect(rcRoomConverted).toHaveProperty('_id'); + expect(rcRoomConverted).toHaveProperty('t', 'd'); + }, + { retries: 5, delayMs: 1000 }, + ); // UserA accepts the invitation const waitForJoinEventPromise = waitForRoomEvent(hs1RoomConverted, RoomStateEvent.Members, ({ event }) => { @@ -865,12 +831,20 @@ const waitForRoomEvent = async ( }); it('should show the invite to the third user', async () => { - await retry('this is an async operation, so we need to wait for the invite to reach RC', async () => { - const pendingInvitationB = await getSubscriptionByRoomId(rcRoomConverted._id, rcUserConfigB.credentials, rcUserConfigB.request); + await retry( + 'this is an async operation, so we need to wait for the invite to reach RC', + async () => { + const pendingInvitationB = await getSubscriptionByRoomId( + rcRoomConverted._id, + rcUserConfigB.credentials, + rcUserConfigB.request, + ); - expect(pendingInvitationB).toHaveProperty('status', 'INVITED'); - expect(pendingInvitationB).toHaveProperty('fname', federationConfig.hs1.adminUser); - }); + expect(pendingInvitationB).toHaveProperty('status', 'INVITED'); + expect(pendingInvitationB).toHaveProperty('fname', federationConfig.hs1.adminUser); + }, + { retries: 5, delayMs: 1000 }, + ); const membersInMatrix = await hs1RoomConverted.getMembers(); @@ -909,7 +883,7 @@ const waitForRoomEvent = async ( expect(subB).toHaveProperty('name', `${federationConfig.hs1.adminMatrixUserId}, ${userDmA}`); expect(subB).toHaveProperty('fname', `${federationConfig.hs1.adminUser}, ${userDmAName}`); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); // Verify room info shows correct user count @@ -1017,12 +991,16 @@ const waitForRoomEvent = async ( expect(rcRoom).toHaveProperty('federation.mrid'); // Wait for invitation in Synapse - await retry('waiting for room invitation', async () => { - hs1Room1 = (await hs1AdminApp.matrixClient.getRoom(rcRoom.federation.mrid)) as Room; + await retry( + 'waiting for room invitation', + async () => { + hs1Room1 = (await hs1AdminApp.matrixClient.getRoom(rcRoom.federation.mrid)) as Room; - expect(hs1Room1).toBeDefined(); - expect(hs1Room1.getMyMembership()).toBe('invite'); - }); + expect(hs1Room1).toBeDefined(); + expect(hs1Room1.getMyMembership()).toBe('invite'); + }, + { retries: 5, delayMs: 1000 }, + ); }); it('should show the room name as the inviter name on Synapse before join', async () => { @@ -1054,7 +1032,7 @@ const waitForRoomEvent = async ( async () => { expect(hs1Room1.getMyMembership()).toBe('join'); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); }); @@ -1072,7 +1050,7 @@ const waitForRoomEvent = async ( expect(sub).toHaveProperty('name', `${federationConfig.hs1.adminMatrixUserId}, ${rcUser1.username}`); expect(sub).toHaveProperty('fname', `${federationConfig.hs1.adminUser}, ${rcUser1.fullName}`); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); }); @@ -1087,7 +1065,7 @@ const waitForRoomEvent = async ( expect(sub).toHaveProperty('name', rcUser2.username); expect(sub).toHaveProperty('fname', rcUser2.fullName); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); }); }); @@ -1182,13 +1160,17 @@ const waitForRoomEvent = async ( expect(rcRoom).toHaveProperty('federation.mrid'); // Wait for invitation in Synapse - await retry('waiting for room invitation', async () => { - hs1Room1 = (await hs1AdminApp.matrixClient.getRoom(rcRoom.federation.mrid)) as Room; + await retry( + 'waiting for room invitation', + async () => { + hs1Room1 = (await hs1AdminApp.matrixClient.getRoom(rcRoom.federation.mrid)) as Room; - expect(hs1Room1).toBeDefined(); - expect(hs1Room1).toHaveProperty('roomId', rcRoom.federation.mrid); - expect(hs1Room1.getMyMembership()).toBe('invite'); - }); + expect(hs1Room1).toBeDefined(); + expect(hs1Room1).toHaveProperty('roomId', rcRoom.federation.mrid); + expect(hs1Room1.getMyMembership()).toBe('invite'); + }, + { retries: 5, delayMs: 1000 }, + ); }); it('should accept the invitation by the Rocket.Chat user', async () => { @@ -1224,7 +1206,7 @@ const waitForRoomEvent = async ( const members = await hs1Room1.getMembers(); expect(members.length).toBe(3); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); await hs1AdminApp.inviteUserToRoom(hs1Room1.roomId, userDmId3); @@ -1237,7 +1219,7 @@ const waitForRoomEvent = async ( expect(user4Member).toBeDefined(); expect(user4Member?.membership).toBe('invite'); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); }); }); @@ -1328,25 +1310,33 @@ const waitForRoomEvent = async ( expect(rcRoom).toHaveProperty('federation.mrid'); // Wait for invitation in Synapse - await retry('waiting for room invitation', async () => { - hs1Room1 = hs1AdminApp.matrixClient.getRoom(rcRoom.federation.mrid) as Room; + await retry( + 'waiting for room invitation', + async () => { + hs1Room1 = hs1AdminApp.matrixClient.getRoom(rcRoom.federation.mrid) as Room; - expect(hs1Room1).toBeDefined(); - expect(hs1Room1).toHaveProperty('roomId', rcRoom.federation.mrid); - expect(hs1Room1.getMyMembership()).toBe('invite'); - }); + expect(hs1Room1).toBeDefined(); + expect(hs1Room1).toHaveProperty('roomId', rcRoom.federation.mrid); + expect(hs1Room1.getMyMembership()).toBe('invite'); + }, + { retries: 5, delayMs: 1000 }, + ); // Accept the invitation await hs1AdminApp.matrixClient.joinRoom(rcRoom.federation.mrid); - await retry('wait for the join to be processed', async () => { - expect(hs1Room1.getMyMembership()).toBe('join'); + await retry( + 'wait for the join to be processed', + async () => { + expect(hs1Room1.getMyMembership()).toBe('join'); - const sub = await getSubscriptionByRoomId(rcRoom._id, rcUser2.config.credentials, rcUser2.config.request); + const sub = await getSubscriptionByRoomId(rcRoom._id, rcUser2.config.credentials, rcUser2.config.request); - // After acceptance, should display the Synapse user's ID - expect(sub).toHaveProperty('fname', `${federationConfig.hs1.adminUser}, ${rcUser1.fullName}`); - }); + // After acceptance, should display the Synapse user's ID + expect(sub).toHaveProperty('fname', `${federationConfig.hs1.adminUser}, ${rcUser1.fullName}`); + }, + { retries: 5, delayMs: 1000 }, + ); // Then create non-federated DM between rcUser1 and rcUser2 which should be returned on duplication const nonFedDmResponse = await rcUser1.config.request @@ -1392,7 +1382,7 @@ const waitForRoomEvent = async ( // After leave, should display only the RC user's full name expect(sub).toHaveProperty('fname', rcUser2.fullName); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); // now there should be two DMs with the same users @@ -1513,25 +1503,33 @@ const waitForRoomEvent = async ( expect(rcRoom1on1).toHaveProperty('usersCount', 2); // Wait for invitation in Synapse - await retry('waiting for room invitation', async () => { - hs1Room1 = hs1AdminApp.matrixClient.getRoom(rcRoom1on1.federation.mrid) as Room; + await retry( + 'waiting for room invitation', + async () => { + hs1Room1 = hs1AdminApp.matrixClient.getRoom(rcRoom1on1.federation.mrid) as Room; - expect(hs1Room1).toBeDefined(); - expect(hs1Room1).toHaveProperty('roomId', rcRoom1on1.federation.mrid); - expect(hs1Room1.getMyMembership()).toBe('invite'); - }); + expect(hs1Room1).toBeDefined(); + expect(hs1Room1).toHaveProperty('roomId', rcRoom1on1.federation.mrid); + expect(hs1Room1.getMyMembership()).toBe('invite'); + }, + { retries: 5, delayMs: 1000 }, + ); // Accept the invitation await hs1AdminApp.matrixClient.joinRoom(rcRoom1on1.federation.mrid); - await retry('wait for the join to be processed', async () => { - expect(hs1Room1.getMyMembership()).toBe('join'); + await retry( + 'wait for the join to be processed', + async () => { + expect(hs1Room1.getMyMembership()).toBe('join'); - const sub = await getSubscriptionByRoomId(rcRoom1on1._id, rcUser1.config.credentials, rcUser1.config.request); + const sub = await getSubscriptionByRoomId(rcRoom1on1._id, rcUser1.config.credentials, rcUser1.config.request); - // After acceptance, should display the Synapse user's ID - expect(sub).toHaveProperty('fname', federationConfig.hs1.adminUser); - }); + // After acceptance, should display the Synapse user's ID + expect(sub).toHaveProperty('fname', federationConfig.hs1.adminUser); + }, + { retries: 5, delayMs: 1000 }, + ); }); it('should create a federated DM between rcUser1 and rcUser2 and the Synapse user', async () => { @@ -1566,7 +1564,7 @@ const waitForRoomEvent = async ( expect(hs1Room1).toHaveProperty('roomId', rcRoom.federation.mrid); expect(hs1Room1.getMyMembership()).toBe('invite'); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); // Accept the invitation @@ -1582,7 +1580,7 @@ const waitForRoomEvent = async ( // After acceptance, should display the Synapse user's ID expect(sub).toHaveProperty('fname', `${federationConfig.hs1.adminUser}, ${rcUser1.fullName}`); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); const response = await acceptRoomInvite(rcRoom._id, rcUser2.config); @@ -1595,7 +1593,7 @@ const waitForRoomEvent = async ( expect(sub).not.toHaveProperty('status'); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); }); @@ -1628,17 +1626,21 @@ const waitForRoomEvent = async ( expect(response.body).toHaveProperty('success', true); // Verify room is no longer accessible to RC users - await retry('waiting for room cleanup', async () => { - const roomsResponse = await rcUser2.config.request.get(api('rooms.get')).set(rcUser2.config.credentials).expect(200); + await retry( + 'waiting for room cleanup', + async () => { + const roomsResponse = await rcUser2.config.request.get(api('rooms.get')).set(rcUser2.config.credentials).expect(200); - expect(roomsResponse.body).toHaveProperty('update'); - expect(roomsResponse.body.update).toBeInstanceOf(Array); + expect(roomsResponse.body).toHaveProperty('update'); + expect(roomsResponse.body.update).toBeInstanceOf(Array); - const room = roomsResponse.body.update?.find((r: IRoom) => r._id === rcRoom._id); + const room = roomsResponse.body.update?.find((r: IRoom) => r._id === rcRoom._id); - // Room should not be in active rooms list - expect(room).toBeUndefined(); - }); + // Room should not be in active rooms list + expect(room).toBeUndefined(); + }, + { retries: 5, delayMs: 1000 }, + ); }); it('should have two DMs with same users', async () => { @@ -1833,7 +1835,7 @@ const waitForRoomEvent = async ( ); expect(subA).toHaveProperty('fname', `${federationConfig.hs1.adminUser}, ${federationConfig.hs1.additionalUser1.username}`); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); // Verify room info shows correct user count @@ -1856,7 +1858,7 @@ const waitForRoomEvent = async ( expect(user4Member).toBeDefined(); expect(user4Member?.membership).toBe('invite'); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); await retry( @@ -1868,10 +1870,83 @@ const waitForRoomEvent = async ( expect(sub).toHaveProperty('name', federationConfig.hs1.additionalUser1.matrixUserId); expect(sub).toHaveProperty('fname', federationConfig.hs1.additionalUser1.username); }, - { delayMs: 100 }, + { retries: 5, delayMs: 1000 }, ); }); }); }); }); + + describe('Display name changes', () => { + let rcUser: TestUser; + let rcUserConfig: IRequestConfig; + let hs1Room: Room; + let rcRoom: IRoom; + + const userDm = `dm-federation-displayname-user-${Date.now()}`; + const userDmId = `@${userDm}:${federationConfig.rc1.domain}`; + const initialDisplayName = `DM User ${Date.now()}`; + const updatedDisplayName = `Updated Display Name ${Date.now()}`; + + beforeAll(async () => { + rcUser = await createUser( + { + username: userDm, + password: 'random', + email: `${userDm}@rocket.chat`, + name: initialDisplayName, + }, + rc1AdminRequestConfig, + ); + + rcUserConfig = await getRequestConfig(federationConfig.rc1.url, rcUser.username, 'random'); + + hs1Room = (await hs1AdminApp.createDM([userDmId])) as Room; + + await retry('waiting for the room to be created in RC', async () => { + const roomsResponse = await rcUserConfig.request.get(api('rooms.get')).set(rcUserConfig.credentials).expect(200); + + rcRoom = roomsResponse.body.update.find((room: IRoomNativeFederated) => room.federation.mrid === hs1Room.roomId); + + expect(rcRoom).toHaveProperty('_id'); + }); + }); + + afterAll(async () => { + await deleteUser(rcUser, {}, rc1AdminRequestConfig); + + // Best-effort reset of the Synapse admin display name. + // The top-level beforeAll will also reset it on the next run, + // so this is not critical for test reliability. + try { + await hs1AdminApp.matrixClient.setDisplayName(federationConfig.hs1.adminUser); + } catch { + // ignore — the top-level beforeAll will handle it + } + }); + + it('should accept the DM invitation from RC', async () => { + const response = await acceptRoomInvite(rcRoom._id, rcUserConfig); + expect(response.success).toBe(true); + }); + + it('should update DM room name after Synapse user changes their display name', async () => { + // Verify initial state: room name should be the Synapse admin initial display name + const initialSub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); + expect(initialSub).toHaveProperty('fname', federationConfig.hs1.adminUser); + + // Action: update the Synapse user's displayname + await hs1AdminApp.matrixClient.setDisplayName(updatedDisplayName); + + // Verify: the DM room name should be updated after the debounced name update completes + await retry( + 'waiting for DM room name to be updated after display name change', + async () => { + const updatedSub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig.credentials, rcUserConfig.request); + expect(updatedSub).toHaveProperty('fname', updatedDisplayName); + }, + { retries: 5, delayMs: 1000 }, + ); + }); + }); }); From 85f001c3806438dc64bdfc593eee49083044420c Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 9 Apr 2026 11:50:25 -0300 Subject: [PATCH 39/51] ci: Update cache key for packages-build in CI workflow (#40101) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1dcde726f5941..fdd15f9d75bdf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -185,7 +185,7 @@ jobs: with: path: | /tmp/RocketChat-packages-build.tar.gz - key: ${{ runner.arch }}-${{ runner.os }}-packages-build-${{ needs.release-versions.outputs.packages-build-cache-key }} + key: ${{ runner.arch }}-${{ runner.os }}-packages-build-${{ needs.release-versions.outputs.source-hash }} - name: Cache observability (packages-build) run: | From a6c863a35dd535b5c4e2ad6e4621a43372dd7ade Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Thu, 9 Apr 2026 21:54:31 +0530 Subject: [PATCH 40/51] fix: engagement dashboard becoming unresponsive when clicking "See on Engagement Dashboard" (#40058) Signed-off-by: Abhinav Kumar Co-authored-by: Douglas Fabris --- .changeset/cool-parents-buy.md | 6 + .../EngagementDashboardRoute.spec.tsx | 137 ++++++++++++++++++ .../EngagementDashboardRoute.tsx | 6 +- .../src/MockedAppRootBuilder.tsx | 11 ++ 4 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 .changeset/cool-parents-buy.md create mode 100644 apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.spec.tsx diff --git a/.changeset/cool-parents-buy.md b/.changeset/cool-parents-buy.md new file mode 100644 index 0000000000000..d2eff43bbfc5b --- /dev/null +++ b/.changeset/cool-parents-buy.md @@ -0,0 +1,6 @@ +--- +'@rocket.chat/meteor': patch +'@rocket.chat/mock-providers': patch +--- + +Fixed UI becoming unresponsive after clicking "See on Engagement Dashboard" from the workspace info card, which required a manual page refresh to recover. diff --git a/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.spec.tsx b/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.spec.tsx new file mode 100644 index 0000000000000..d5d70436bb7a3 --- /dev/null +++ b/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.spec.tsx @@ -0,0 +1,137 @@ +import { mockAppRoot } from '@rocket.chat/mock-providers'; +import type { RouterContextValue } from '@rocket.chat/ui-contexts'; +import { render } from '@testing-library/react'; + +import EngagementDashboardRoute from './EngagementDashboardRoute'; +import { useUpsellActions } from '../../../components/GenericUpsellModal/hooks'; +import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; + +jest.mock('../../../hooks/useHasLicenseModule', () => ({ useHasLicenseModule: jest.fn() })); +jest.mock('../../../components/GenericUpsellModal/hooks', () => ({ useUpsellActions: jest.fn() })); +jest.mock('./EngagementDashboardPage', () => () => null); +jest.mock('../../../components/PageSkeleton', () => () => null); +jest.mock('../../notAuthorized/NotAuthorizedPage', () => () => null); +jest.mock('../../../../app/utils/client/getURL', () => ({ getURL: (path: string) => path })); + +const buildWrapper = (router: Partial, tab?: string) => { + const builder = mockAppRoot() + .withPermission('view-engagement-dashboard') + .withEndpoint('POST', '/v1/statistics.telemetry', () => ({})) + .withRouter(router); + + if (tab) { + builder.withRouteParameter('tab', tab); + } + + return builder.build(); +}; + +const createSubscribeTracker = () => { + const unsubscribes: jest.Mock[] = []; + + const subscribeToRouteChange = jest.fn((_cb: () => void) => { + const unsub = jest.fn(); + unsubscribes.push(unsub); + return unsub; + }); + + const allUnsubscribed = () => unsubscribes.length > 0 && unsubscribes.every((u) => u.mock.calls.length > 0); + + const noneUnsubscribed = () => unsubscribes.every((u) => u.mock.calls.length === 0); + + const getLastRouteChangeCallback = () => { + const callback = subscribeToRouteChange.mock.calls.at(-1)?.[0]; + expect(callback).toBeDefined(); + return callback as () => void; + }; + + return { subscribeToRouteChange, allUnsubscribed, noneUnsubscribed, getLastRouteChangeCallback }; +}; + +beforeEach(() => { + jest.clearAllMocks(); + + jest.mocked(useHasLicenseModule).mockReturnValue({ + isPending: false, + data: true, + } as unknown as ReturnType); + + jest.mocked(useUpsellActions).mockReturnValue({ + shouldShowUpsell: false, + cloudWorkspaceHadTrial: false, + handleManageSubscription: jest.fn(), + handleTalkToSales: jest.fn(), + }); +}); + +describe('EngagementDashboardRoute', () => { + it('subscribes to route changes on mount', () => { + const { subscribeToRouteChange } = createSubscribeTracker(); + + render(, { + wrapper: buildWrapper({ subscribeToRouteChange }, 'users'), + }); + + expect(subscribeToRouteChange).toHaveBeenCalled(); + }); + + it('unsubscribes all listeners on unmount', () => { + const { subscribeToRouteChange, allUnsubscribed } = createSubscribeTracker(); + + const { unmount } = render(, { + wrapper: buildWrapper({ subscribeToRouteChange }, 'users'), + }); + + unmount(); + expect(allUnsubscribed()).toBe(true); + }); + + it('does not redirect when the tab is valid', () => { + const navigate = jest.fn(); + const { subscribeToRouteChange, getLastRouteChangeCallback } = createSubscribeTracker(); + + render(, { + wrapper: buildWrapper({ subscribeToRouteChange, navigate }, 'users'), + }); + + const routeChangeCallback = getLastRouteChangeCallback(); + routeChangeCallback(); + + expect(navigate).not.toHaveBeenCalled(); + }); + + it('redirects to the users tab when the tab is invalid', () => { + const navigate = jest.fn(); + const { subscribeToRouteChange, getLastRouteChangeCallback } = createSubscribeTracker(); + + render(, { + wrapper: buildWrapper({ subscribeToRouteChange, navigate }), + }); + + const routeChangeCallback = getLastRouteChangeCallback(); + routeChangeCallback(); + + expect(navigate).toHaveBeenCalledWith({ pattern: '/admin/engagement/:tab?', params: { tab: 'users' } }, { replace: true }); + }); + + it('cleans up all subscriptions on unmount and resubscribes on remount', () => { + const first = createSubscribeTracker(); + + const { unmount } = render(, { + wrapper: buildWrapper({ subscribeToRouteChange: first.subscribeToRouteChange }, 'users'), + }); + + expect(first.subscribeToRouteChange).toHaveBeenCalled(); + unmount(); + expect(first.allUnsubscribed()).toBe(true); + + const second = createSubscribeTracker(); + + render(, { + wrapper: buildWrapper({ subscribeToRouteChange: second.subscribeToRouteChange }, 'messages'), + }); + + expect(second.subscribeToRouteChange).toHaveBeenCalled(); + expect(second.noneUnsubscribed()).toBe(true); + }); +}); diff --git a/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx b/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx index a1a74535025e6..1a9d79b37aeae 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx @@ -50,8 +50,10 @@ const EngagementDashboardRoute = (): ReactElement | null => { />, ); } + }, [shouldShowUpsell, setModal, t, handleManageSubscription]); - router.subscribeToRouteChange(() => { + useEffect(() => { + return router.subscribeToRouteChange(() => { if (!isValidTab(tab)) { router.navigate( { @@ -62,7 +64,7 @@ const EngagementDashboardRoute = (): ReactElement | null => { ); } }); - }, [shouldShowUpsell, router, tab, setModal, t, handleManageSubscription]); + }, [router, tab]); if (isModalOpen || isPending) { return ; diff --git a/packages/mock-providers/src/MockedAppRootBuilder.tsx b/packages/mock-providers/src/MockedAppRootBuilder.tsx index 40ac48cfa7249..c530753ae6477 100644 --- a/packages/mock-providers/src/MockedAppRootBuilder.tsx +++ b/packages/mock-providers/src/MockedAppRootBuilder.tsx @@ -474,6 +474,17 @@ export class MockedAppRootBuilder { return this; } + withRouter(overrides: Partial>): this { + this.router = { ...this.router, ...overrides }; + return this; + } + + withRouteParameter(name: string, value: string): this { + const innerFn = this.router.getRouteParameters; + this.router.getRouteParameters = () => ({ ...innerFn(), [name]: value }); + return this; + } + withRole(role: string): this { if (!this.user.user) { throw new Error('user is not defined'); From eb78ae4e4f8123712f09f110f5a3ffb415b69e9a Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Fri, 10 Apr 2026 00:14:36 +0530 Subject: [PATCH 41/51] fix: DDP method calls returning 404 for void methods (#40057) Signed-off-by: Abhinav Kumar --- .changeset/empty-spiders-vanish.md | 5 ++ ee/apps/ddp-streamer/jest.config.ts | 7 ++ ee/apps/ddp-streamer/package.json | 6 +- ee/apps/ddp-streamer/src/Server.spec.ts | 108 ++++++++++++++++++++++++ ee/apps/ddp-streamer/src/Server.ts | 6 +- ee/apps/ddp-streamer/tsconfig.json | 3 +- yarn.lock | 5 +- 7 files changed, 132 insertions(+), 8 deletions(-) create mode 100644 .changeset/empty-spiders-vanish.md create mode 100644 ee/apps/ddp-streamer/jest.config.ts create mode 100644 ee/apps/ddp-streamer/src/Server.spec.ts diff --git a/.changeset/empty-spiders-vanish.md b/.changeset/empty-spiders-vanish.md new file mode 100644 index 0000000000000..8c7a62f6d2dd5 --- /dev/null +++ b/.changeset/empty-spiders-vanish.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/ddp-streamer': patch +--- + +Fixes an issue where some DDP method calls could incorrectly return a 404 error. diff --git a/ee/apps/ddp-streamer/jest.config.ts b/ee/apps/ddp-streamer/jest.config.ts new file mode 100644 index 0000000000000..46e41b9ab1707 --- /dev/null +++ b/ee/apps/ddp-streamer/jest.config.ts @@ -0,0 +1,7 @@ +import server from '@rocket.chat/jest-presets/server'; +import type { Config } from 'jest'; + +export default { + preset: server.preset, + testMatch: ['/src/**/*.spec.(ts|js|mjs)'], +} satisfies Config; diff --git a/ee/apps/ddp-streamer/package.json b/ee/apps/ddp-streamer/package.json index 36ad0bea51a83..1c57fb5ae607c 100644 --- a/ee/apps/ddp-streamer/package.json +++ b/ee/apps/ddp-streamer/package.json @@ -15,7 +15,8 @@ "build": "tsc -p tsconfig.json", "lint": "eslint .", "ms": "TRANSPORTER=${TRANSPORTER:-TCP} MONGO_URL=${MONGO_URL:-mongodb://localhost:3001/meteor} ts-node --files src/service.ts", - "test": "echo \"Error: no test specified\" && exit 1", + "test": "jest", + "testunit": "jest", "typecheck": "tsc --noEmit --skipLibCheck -p tsconfig.json" }, "dependencies": { @@ -50,7 +51,9 @@ "devDependencies": { "@rocket.chat/apps-engine": "workspace:^", "@rocket.chat/ddp-client": "workspace:~", + "@rocket.chat/jest-presets": "workspace:*", "@types/ejson": "^2.2.2", + "@types/jest": "~30.0.0", "@types/node": "~22.16.5", "@types/polka": "^0.5.8", "@types/prometheus-gc-stats": "^0.6.4", @@ -58,6 +61,7 @@ "@types/uuid": "^10.0.0", "@types/ws": "^8.18.1", "eslint": "~9.39.3", + "jest": "~30.2.0", "pino-pretty": "13.1.3", "ts-node": "^10.9.2", "typescript": "~5.9.3" diff --git a/ee/apps/ddp-streamer/src/Server.spec.ts b/ee/apps/ddp-streamer/src/Server.spec.ts new file mode 100644 index 0000000000000..0f8bece0251c3 --- /dev/null +++ b/ee/apps/ddp-streamer/src/Server.spec.ts @@ -0,0 +1,108 @@ +import { MeteorService } from '@rocket.chat/core-services'; +import WebSocket from 'ws'; + +import { Server } from './Server'; +import type { IPacket } from './types/IPacket'; + +jest.mock('@rocket.chat/core-services', () => ({ + ...jest.requireActual('@rocket.chat/core-services'), + MeteorService: { + callMethodWithToken: jest.fn(), + }, +})); + +jest.mock('@rocket.chat/logger', () => ({ + Logger: jest.fn().mockReturnValue({ + error: jest.fn(), + }), +})); + +const mockCallMethodWithToken = jest.mocked(MeteorService.callMethodWithToken); + +function makeClient(readyState: number = WebSocket.OPEN) { + return { + ws: { readyState }, + userId: 'user1', + userToken: 'token1', + send: jest.fn(), + } as unknown as Parameters[0]; +} + +function makePacket(method: string, id = 'test-id'): IPacket { + return { msg: 'method', method, id, params: [] } as unknown as IPacket; +} + +describe('Server.call', () => { + let server: Server; + + beforeEach(() => { + server = new Server(); + jest.clearAllMocks(); + }); + + describe('when the method is delegated to MeteorService', () => { + it('returns the result value from MeteorService', async () => { + mockCallMethodWithToken.mockResolvedValue({ result: 'some-value' } as any); + const client = makeClient(); + const resultSpy = jest.spyOn(server, 'result'); + + await server.call(client, makePacket('someMethod')); + + expect(resultSpy).toHaveBeenCalledWith(client, expect.objectContaining({ id: 'test-id' }), 'some-value'); + }); + + it('does not return an error when the method returns void', async () => { + mockCallMethodWithToken.mockResolvedValue({ result: undefined } as any); + const client = makeClient(); + const resultSpy = jest.spyOn(server, 'result'); + + await server.call(client, makePacket('setAvatarFromService')); + + expect(resultSpy).toHaveBeenCalledWith(client, expect.objectContaining({ id: 'test-id' }), undefined); + }); + + it('calls result with an error when MeteorService throws', async () => { + mockCallMethodWithToken.mockRejectedValue(new Error('boom')); + const client = makeClient(); + const resultSpy = jest.spyOn(server, 'result'); + + await server.call(client, makePacket('someMethod')); + + expect(resultSpy).toHaveBeenCalledWith(client, expect.objectContaining({ id: 'test-id' }), null, expect.any(Error)); + }); + }); + + describe('when the method is registered locally', () => { + it('returns the result value from the local method', async () => { + server.methods({ localMethod: async () => 'local-result' }); + const client = makeClient(); + const resultSpy = jest.spyOn(server, 'result'); + + await server.call(client, makePacket('localMethod')); + + expect(resultSpy).toHaveBeenCalledWith(client, expect.objectContaining({ id: 'test-id' }), 'local-result'); + }); + + it('does not return an error when the local method returns void', async () => { + server.methods({ voidMethod: async () => undefined }); + const client = makeClient(); + const resultSpy = jest.spyOn(server, 'result'); + + await server.call(client, makePacket('voidMethod')); + + expect(resultSpy).toHaveBeenCalledWith(client, expect.objectContaining({ id: 'test-id' }), undefined); + }); + }); + + describe('when the client WebSocket is not open', () => { + it('does nothing', async () => { + const client = makeClient(WebSocket.CLOSED); + const resultSpy = jest.spyOn(server, 'result'); + + await server.call(client, makePacket('anyMethod')); + + expect(resultSpy).not.toHaveBeenCalled(); + expect(mockCallMethodWithToken).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/ee/apps/ddp-streamer/src/Server.ts b/ee/apps/ddp-streamer/src/Server.ts index 2aaa028fab6e7..b5a2a6ae6b3e6 100644 --- a/ee/apps/ddp-streamer/src/Server.ts +++ b/ee/apps/ddp-streamer/src/Server.ts @@ -68,11 +68,7 @@ export class Server extends EventEmitter { // if method was not defined on DDP Streamer we fall back to Meteor if (!this._methods.has(packet.method)) { const result = await MeteorService.callMethodWithToken(client.userId, client.userToken, packet.method, packet.params); - if (result?.result) { - return this.result(client, packet, result.result); - } - - throw new MeteorError(404, `Method '${packet.method}' not found`); + return this.result(client, packet, result.result); } const fn = this._methods.get(packet.method); diff --git a/ee/apps/ddp-streamer/tsconfig.json b/ee/apps/ddp-streamer/tsconfig.json index 72e3c71e0971b..acd89a29157f2 100644 --- a/ee/apps/ddp-streamer/tsconfig.json +++ b/ee/apps/ddp-streamer/tsconfig.json @@ -2,7 +2,8 @@ "extends": "@rocket.chat/tsconfig/server.json", "compilerOptions": { "strictPropertyInitialization": false, // TODO: Remove this line - "outDir": "./dist" + "outDir": "./dist", + "types": ["jest", "node"] }, "include": ["./src/**/*", "./definition"], "exclude": ["./dist", "./ecosystem.config.js"] diff --git a/yarn.lock b/yarn.lock index 593c43b9c9c68..a46ba00f1d120 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9248,6 +9248,7 @@ __metadata: "@rocket.chat/ddp-client": "workspace:~" "@rocket.chat/emitter": "npm:^0.32.0" "@rocket.chat/instance-status": "workspace:^" + "@rocket.chat/jest-presets": "workspace:*" "@rocket.chat/logger": "workspace:^" "@rocket.chat/model-typings": "workspace:^" "@rocket.chat/models": "workspace:^" @@ -9256,6 +9257,7 @@ __metadata: "@rocket.chat/string-helpers": "npm:~0.32.0" "@rocket.chat/tracing": "workspace:^" "@types/ejson": "npm:^2.2.2" + "@types/jest": "npm:~30.0.0" "@types/node": "npm:~22.16.5" "@types/polka": "npm:^0.5.8" "@types/prometheus-gc-stats": "npm:^0.6.4" @@ -9267,6 +9269,7 @@ __metadata: eslint: "npm:~9.39.3" eventemitter3: "npm:^5.0.4" jaeger-client: "npm:^3.19.0" + jest: "npm:~30.2.0" mem: "npm:^8.1.1" moleculer: "npm:^0.14.35" mongodb: "npm:6.16.0" @@ -9671,7 +9674,7 @@ __metadata: languageName: unknown linkType: soft -"@rocket.chat/jest-presets@workspace:^, @rocket.chat/jest-presets@workspace:packages/jest-presets, @rocket.chat/jest-presets@workspace:~": +"@rocket.chat/jest-presets@workspace:*, @rocket.chat/jest-presets@workspace:^, @rocket.chat/jest-presets@workspace:packages/jest-presets, @rocket.chat/jest-presets@workspace:~": version: 0.0.0-use.local resolution: "@rocket.chat/jest-presets@workspace:packages/jest-presets" dependencies: From 9875f670950b2bf0ca5355377902443f87d14be6 Mon Sep 17 00:00:00 2001 From: Ricardo Garim Date: Thu, 9 Apr 2026 17:10:51 -0300 Subject: [PATCH 42/51] chore: add helper descriptions to Auto Away user preference settings (#40050) --- .../account/preferences/PreferencesUserPresenceSection.tsx | 4 +++- packages/i18n/src/locales/en.i18n.json | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/meteor/client/views/account/preferences/PreferencesUserPresenceSection.tsx b/apps/meteor/client/views/account/preferences/PreferencesUserPresenceSection.tsx index c9bc4df15b13a..bbc3a490454c4 100644 --- a/apps/meteor/client/views/account/preferences/PreferencesUserPresenceSection.tsx +++ b/apps/meteor/client/views/account/preferences/PreferencesUserPresenceSection.tsx @@ -1,5 +1,5 @@ import { AccordionItem } from '@rocket.chat/fuselage'; -import { Field, FieldGroup, FieldLabel, FieldRow, ToggleSwitch, NumberInput } from '@rocket.chat/fuselage-forms'; +import { Field, FieldGroup, FieldHint, FieldLabel, FieldRow, ToggleSwitch, NumberInput } from '@rocket.chat/fuselage-forms'; import { Controller, useFormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; @@ -19,6 +19,7 @@ const PreferencesUserPresenceSection = () => { render={({ field: { value, ...field } }) => } /> + {t('Enable_Auto_Away_Description')} {t('Idle_Time_Limit')} @@ -29,6 +30,7 @@ const PreferencesUserPresenceSection = () => { render={({ field: { value, ...field } }) => } /> + {t('Idle_Time_Limit_Description')} diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 2881b1432e9b7..be94325cc9237 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -1976,6 +1976,7 @@ "Empty_title": "Empty title", "Enable": "Enable", "Enable_Auto_Away": "Enable Auto Away", + "Enable_Auto_Away_Description": "Switches your status to Away after a period of inactivity. Has no effect if status is manually set to Busy or Away.", "Enable_CSP": "Enable Content-Security-Policy", "Enable_CSP_Description": "Do not disable this option unless you have a custom build and are having problems due to inline-scripts", "Enable_Desktop_Notifications": "Enable Desktop Notifications", @@ -2556,7 +2557,7 @@ "I_Saved_My_Password": "I saved my password", "Icon": "Icon", "Idle_Time_Limit": "Idle Time Limit", - "Idle_Time_Limit_Description": "Period of time until status changes to away. Value needs to be in seconds.", + "Idle_Time_Limit_Description": "Set how long (in seconds) the app waits before marking you as Away when you're not active. Minimum: 60 seconds", "If_this_email_is_registered": "If this email is registered, we'll send instructions on how to reset your password. If you do not receive an email shortly, please come back and try again.", "If_you_didnt_ask_for_reset_ignore_this_email": "If you didn't ask for your password reset, you can ignore this email.", "If_you_didnt_try_to_login_in_your_account_please_ignore_this_email": "If you didn't try to login in your account please ignore this email.", From 5052af2e4fcae2d9ff652d427dcfb23a0c0a8c8c Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 9 Apr 2026 17:11:14 -0300 Subject: [PATCH 43/51] chore: migrate client-side code from moment to date-fns (#40076) Co-authored-by: Douglas Fabris --- .../RetentionPolicyCallout.spec.tsx.snap | 4 +- .../InvitationBadge.spec.tsx.snap | 4 +- .../__snapshots__/UserInfo.spec.tsx.snap | 2 +- .../client/components/dashboards/periods.ts | 88 ++++++++++++++--- .../message/content/ThreadMetrics.spec.tsx | 2 +- .../message/toolbar/useEditMessageAction.ts | 5 +- apps/meteor/client/definitions/cron.d.ts | 2 +- apps/meteor/client/hooks/useFormatDate.ts | 5 +- .../client/hooks/useFormatDateAndTime.ts | 12 +-- apps/meteor/client/hooks/useFormatTime.ts | 10 +- .../client/hooks/useFormattedRelativeTime.ts | 13 +-- .../hooks/usePruneWarningMessage.spec.ts | 20 ++-- apps/meteor/client/hooks/useTimeAgo.ts | 46 ++++----- apps/meteor/client/hooks/useTimeFromNow.ts | 5 +- .../client/hooks/useTimezoneNameList.ts | 8 +- apps/meteor/client/hooks/useTimezoneTime.ts | 26 ++--- apps/meteor/client/lib/chats/data.ts | 6 +- apps/meteor/client/lib/utils/dateFormat.ts | 97 +++++++++++++++++++ apps/meteor/client/lib/utils/getDateRange.ts | 11 +-- apps/meteor/client/lib/utils/timeAgo.ts | 19 ++-- .../client/providers/TranslationProvider.tsx | 24 +---- .../sidebar/badges/SidebarItemBadges.spec.tsx | 2 +- apps/meteor/client/startup/startup.ts | 3 +- .../channels/ChannelsOverview.tsx | 8 +- .../messages/MessagesSentSection.tsx | 13 ++- .../users/ActiveUsersSection.tsx | 22 +++-- .../users/ContentForDays.tsx | 23 ++--- .../users/ContentForHours.tsx | 6 +- .../users/NewUsersSection.tsx | 14 ++- .../users/UsersByTimeOfTheDaySection.tsx | 57 ++++++----- .../users/useHourlyChatActivity.ts | 17 +++- .../users/useWeeklyChatActivity.ts | 10 +- .../moderation/helpers/DateRangePicker.tsx | 28 ++++-- .../inputs/SelectTimezoneSettingInput.tsx | 6 +- .../components/forms/DateRangePicker.tsx | 39 +++++--- .../client/views/audit/utils/dateRange.ts | 6 +- .../AppDetailsPage/AppDetailsPageHeader.tsx | 4 +- .../__snapshots__/AppLogsItem.spec.tsx.snap | 2 +- .../sidebar/badges/SidebarItemBadges.spec.tsx | 2 +- .../RoomSidePanelItemBadges.spec.tsx | 2 +- .../omnichannel/analytics/DateRangePicker.tsx | 38 +++++--- .../RecipientForm/RecipientForm.spec.tsx | 2 +- .../directory/utils/formatQueuedAt.ts | 20 ++-- .../getMomentChartLabelsAndData.spec.ts | 60 +++--------- .../charts/getMomentChartLabelsAndData.ts | 17 ++-- .../charts/getMomentCurrentLabel.spec.ts | 17 +--- .../charts/getMomentCurrentLabel.ts | 8 +- .../room/body/RetentionPolicyWarning.spec.tsx | 2 +- .../PruneMessages/PruneMessagesWithData.tsx | 8 +- apps/meteor/package.json | 1 + apps/uikit-playground/package.json | 1 - apps/uikit-playground/src/utils/formatDate.ts | 19 +++- packages/i18n/src/locales/en.i18n.json | 1 + packages/tools/package.json | 3 - packages/tools/src/timezone.ts | 42 ++++++-- packages/tools/tsconfig.json | 3 +- 56 files changed, 532 insertions(+), 383 deletions(-) create mode 100644 apps/meteor/client/lib/utils/dateFormat.ts diff --git a/apps/meteor/client/components/InfoPanel/__snapshots__/RetentionPolicyCallout.spec.tsx.snap b/apps/meteor/client/components/InfoPanel/__snapshots__/RetentionPolicyCallout.spec.tsx.snap index 8b1d477b28c52..4a717b0108484 100644 --- a/apps/meteor/client/components/InfoPanel/__snapshots__/RetentionPolicyCallout.spec.tsx.snap +++ b/apps/meteor/client/components/InfoPanel/__snapshots__/RetentionPolicyCallout.spec.tsx.snap @@ -26,7 +26,7 @@ exports[`renders Default without crashing 1`] = ` >

- a minute June 1, 2024 at 12:30 AM + 1 minute June 1, 2024 at 12:30 AM

@@ -63,7 +63,7 @@ exports[`renders InvalidSettings without crashing 1`] = ` >

- a minute June 12, 2024 at 12:00 AM + 1 minute June 12, 2024 at 12:00 AM

diff --git a/apps/meteor/client/components/InvitationBadge/__snapshots__/InvitationBadge.spec.tsx.snap b/apps/meteor/client/components/InvitationBadge/__snapshots__/InvitationBadge.spec.tsx.snap index da3763aaf4e55..32132535fbba5 100644 --- a/apps/meteor/client/components/InvitationBadge/__snapshots__/InvitationBadge.spec.tsx.snap +++ b/apps/meteor/client/components/InvitationBadge/__snapshots__/InvitationBadge.spec.tsx.snap @@ -7,7 +7,7 @@ exports[`renders WithDateObject without crashing 1`] = ` aria-hidden="false" class="rcx-box rcx-box--full rcx-icon--name-mail rcx-icon rcx-css-1p3fsdk" role="status" - title="Invited January 1, 2025" + title="Invited January 1st, 2025" >  @@ -22,7 +22,7 @@ exports[`renders WithISOStringDate without crashing 1`] = ` aria-hidden="false" class="rcx-box rcx-box--full rcx-icon--name-mail rcx-icon rcx-css-1p3fsdk" role="status" - title="Invited January 1, 2025" + title="Invited January 1st, 2025" >  diff --git a/apps/meteor/client/components/UserInfo/__snapshots__/UserInfo.spec.tsx.snap b/apps/meteor/client/components/UserInfo/__snapshots__/UserInfo.spec.tsx.snap index d9a9819ddbc26..07e5652512bc2 100644 --- a/apps/meteor/client/components/UserInfo/__snapshots__/UserInfo.spec.tsx.snap +++ b/apps/meteor/client/components/UserInfo/__snapshots__/UserInfo.spec.tsx.snap @@ -541,7 +541,7 @@ exports[`renders InvitedUser without crashing 1`] = `
- January 1, 2025 + January 1st, 2025
diff --git a/apps/meteor/client/components/dashboards/periods.ts b/apps/meteor/client/components/dashboards/periods.ts index 637a2e0ac0b9f..dcdcae33b2876 100644 --- a/apps/meteor/client/components/dashboards/periods.ts +++ b/apps/meteor/client/components/dashboards/periods.ts @@ -1,32 +1,92 @@ import type { TranslationKey } from '@rocket.chat/ui-contexts'; -import type { DurationInputArg1, DurationInputArg2 } from 'moment'; -import moment from 'moment'; +import { startOfDay, startOfWeek, startOfMonth, startOfYear, endOfDay, subDays, subMonths } from 'date-fns'; const label = (translationKey: TranslationKey): readonly [translationKey: TranslationKey] => [translationKey]; +function startOfDayUTC(d: Date): Date { + return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), 0, 0, 0, 0)); +} + +function endOfDayUTC(d: Date): Date { + return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), 23, 59, 59, 999)); +} + +function startOfWeekUTC(d: Date): Date { + const day = d.getUTCDay(); // 0 = Sunday + const sunday = new Date(d); + sunday.setUTCDate(d.getUTCDate() - day); + return startOfDayUTC(sunday); +} + +function startOfMonthUTC(d: Date): Date { + return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1, 0, 0, 0, 0)); +} + +function startOfYearUTC(d: Date): Date { + return new Date(Date.UTC(d.getUTCFullYear(), 0, 1, 0, 0, 0, 0)); +} + +type StartOf = 'day' | 'year' | 'month' | 'week'; +type Subtract = { amount: number; unit: 'days' | 'months' }; + export const getClosedPeriod = ({ - startOf, - subtract, + startOf: startOfKey, + subtract: subtractOpt, }: { - startOf: 'day' | 'year' | 'month' | 'week'; - subtract?: { amount: DurationInputArg1; unit: DurationInputArg2 }; + startOf: StartOf; + subtract?: Subtract; }): ((utc: boolean) => { start: Date; end: Date; }) => - (utc): { start: Date; end: Date } => { - const start = utc ? moment().utc() : moment(); - const end = utc ? moment().utc() : moment(); + (utc: boolean): { start: Date; end: Date } => { + const now = new Date(); + + let start: Date; + if (subtractOpt) { + const { amount, unit } = subtractOpt; + start = unit === 'days' ? subDays(now, amount) : subMonths(now, amount); + } else { + start = new Date(now.getTime()); + } + + if (utc) { + switch (startOfKey) { + case 'day': + start = startOfDayUTC(start); + break; + case 'week': + start = startOfWeekUTC(start); + break; + case 'month': + start = startOfMonthUTC(start); + break; + case 'year': + start = startOfYearUTC(start); + break; + } + return { start, end: endOfDayUTC(now) }; + } - if (subtract) { - const { amount, unit } = subtract; - start.subtract(amount, unit); + switch (startOfKey) { + case 'day': + start = startOfDay(start); + break; + case 'week': + start = startOfWeek(start); + break; + case 'month': + start = startOfMonth(start); + break; + case 'year': + start = startOfYear(start); + break; } return { - start: start.startOf(startOf).toDate(), - end: end.endOf('day').toDate(), + start, + end: endOfDay(now), }; }; diff --git a/apps/meteor/client/components/message/content/ThreadMetrics.spec.tsx b/apps/meteor/client/components/message/content/ThreadMetrics.spec.tsx index 363eb1f2870b8..c6138e9dd342d 100644 --- a/apps/meteor/client/components/message/content/ThreadMetrics.spec.tsx +++ b/apps/meteor/client/components/message/content/ThreadMetrics.spec.tsx @@ -112,7 +112,7 @@ describe('Thread Metrics', () => { expect(navigateSpy).toHaveBeenCalledWith('thread', 'rid', 'thread', 'mid'); const threadCount = screen.getByTitle('Last_message__date__'); - expect(threadCount).toHaveTextContent('5 replies July 1, 2024'); + expect(threadCount).toHaveTextContent('5 replies July 1st, 2024'); }); it('should render small not followed with 3 participants and unread', async () => { diff --git a/apps/meteor/client/components/message/toolbar/useEditMessageAction.ts b/apps/meteor/client/components/message/toolbar/useEditMessageAction.ts index 92df4f7cea35a..39ef7e94e2fd6 100644 --- a/apps/meteor/client/components/message/toolbar/useEditMessageAction.ts +++ b/apps/meteor/client/components/message/toolbar/useEditMessageAction.ts @@ -1,7 +1,7 @@ import { isRoomFederated } from '@rocket.chat/core-typings'; import type { IRoom, IMessage, ISubscription } from '@rocket.chat/core-typings'; import { usePermission, useSetting, useUser } from '@rocket.chat/ui-contexts'; -import moment from 'moment'; +import { differenceInMinutes } from 'date-fns'; import type { MessageActionConfig } from '../../../../app/ui-utils/client/lib/MessageAction'; import { useChat } from '../../../views/room/contexts/ChatContext'; @@ -32,8 +32,7 @@ export const useEditMessageAction = ( } if (!canBypassBlockTimeLimit && blockEditInMinutes) { - const msgTs = message.ts ? moment(message.ts) : undefined; - const currentTsDiff = msgTs ? moment().diff(msgTs, 'minutes') : undefined; + const currentTsDiff = message.ts ? differenceInMinutes(new Date(), message.ts) : undefined; return typeof currentTsDiff === 'number' && currentTsDiff < blockEditInMinutes; } diff --git a/apps/meteor/client/definitions/cron.d.ts b/apps/meteor/client/definitions/cron.d.ts index 25c4be4f97a7c..f3c1e67e19795 100644 --- a/apps/meteor/client/definitions/cron.d.ts +++ b/apps/meteor/client/definitions/cron.d.ts @@ -1,3 +1,3 @@ declare module 'cron' { - export declare function sendAt(precision: string): Moment; + export declare function sendAt(precision: string): { valueOf(): number }; } diff --git a/apps/meteor/client/hooks/useFormatDate.ts b/apps/meteor/client/hooks/useFormatDate.ts index 4beeb1d70b051..35410591ddd9d 100644 --- a/apps/meteor/client/hooks/useFormatDate.ts +++ b/apps/meteor/client/hooks/useFormatDate.ts @@ -1,8 +1,9 @@ import { useSetting } from '@rocket.chat/ui-contexts'; -import moment from 'moment'; import { useCallback } from 'react'; +import { formatDate } from '../lib/utils/dateFormat'; + export const useFormatDate = () => { const format = useSetting('Message_DateFormat'); - return useCallback((time: string | Date | number) => moment(time).format(String(format)), [format]); + return useCallback((time: string | Date | number) => formatDate(time, String(format)), [format]); }; diff --git a/apps/meteor/client/hooks/useFormatDateAndTime.ts b/apps/meteor/client/hooks/useFormatDateAndTime.ts index 9f73cc5718ea2..2f2ddaa182d6f 100644 --- a/apps/meteor/client/hooks/useFormatDateAndTime.ts +++ b/apps/meteor/client/hooks/useFormatDateAndTime.ts @@ -1,8 +1,8 @@ import { useUserPreference, useSetting } from '@rocket.chat/ui-contexts'; -import type { MomentInput } from 'moment'; -import moment from 'moment'; import { useCallback } from 'react'; +import { formatDate } from '../lib/utils/dateFormat'; + type UseFormatDateAndTimeParams = { withSeconds?: boolean; }; @@ -12,15 +12,15 @@ export const useFormatDateAndTime = ({ withSeconds }: UseFormatDateAndTimeParams const format = useSetting('Message_TimeAndDateFormat', 'LLL'); return useCallback( - (time: MomentInput) => { + (time: string | Date | number = new Date()) => { switch (clockMode) { case 1: - return moment(time).format(withSeconds ? 'MMMM D, Y h:mm:ss A' : 'MMMM D, Y h:mm A'); + return formatDate(time, withSeconds ? 'MMMM D, YYYY h:mm:ss A' : 'MMMM D, YYYY h:mm A'); case 2: - return moment(time).format(withSeconds ? 'MMMM D, Y H:mm:ss' : 'MMMM D, Y H:mm'); + return formatDate(time, withSeconds ? 'MMMM D, YYYY H:mm:ss' : 'MMMM D, YYYY H:mm'); default: - return moment(time).format(withSeconds ? 'L LTS' : format); + return formatDate(time, withSeconds ? 'L LTS' : format); } }, [clockMode, format, withSeconds], diff --git a/apps/meteor/client/hooks/useFormatTime.ts b/apps/meteor/client/hooks/useFormatTime.ts index 38b3cf236b703..fcb1c445e03fc 100644 --- a/apps/meteor/client/hooks/useFormatTime.ts +++ b/apps/meteor/client/hooks/useFormatTime.ts @@ -1,8 +1,8 @@ import { useUserPreference, useSetting } from '@rocket.chat/ui-contexts'; -import type { MomentInput } from 'moment'; -import moment from 'moment'; import { useCallback } from 'react'; +import { formatDate } from '../lib/utils/dateFormat'; + const dayFormat = ['h:mm A', 'H:mm'] as const; export const useFormatTime = () => { @@ -11,14 +11,14 @@ export const useFormatTime = () => { const sameDay = clockMode !== undefined ? dayFormat[clockMode - 1] : format; return useCallback( - (time: MomentInput) => { + (time: string | Date | number) => { switch (clockMode) { case 1: case 2: - return moment(time).format(sameDay); + return formatDate(time, sameDay); default: - return moment(time).format(format); + return formatDate(time, format); } }, [clockMode, format, sameDay], diff --git a/apps/meteor/client/hooks/useFormattedRelativeTime.ts b/apps/meteor/client/hooks/useFormattedRelativeTime.ts index b2003c3825b77..555b02d0d9b69 100644 --- a/apps/meteor/client/hooks/useFormattedRelativeTime.ts +++ b/apps/meteor/client/hooks/useFormattedRelativeTime.ts @@ -1,14 +1,5 @@ -import moment from 'moment'; import { useMemo } from 'react'; -export const useFormattedRelativeTime = (timeMs: number): string => - useMemo(() => { - moment.relativeTimeThreshold('s', 60); - moment.relativeTimeThreshold('ss', 0); - moment.relativeTimeThreshold('m', 60); - moment.relativeTimeThreshold('h', 24); - moment.relativeTimeThreshold('d', 31); - moment.relativeTimeThreshold('M', 12); +import { formatDurationMs } from '../lib/utils/dateFormat'; - return moment.duration(timeMs).humanize(); - }, [timeMs]); +export const useFormattedRelativeTime = (timeMs: number): string => useMemo(() => formatDurationMs(timeMs), [timeMs]); diff --git a/apps/meteor/client/hooks/usePruneWarningMessage.spec.ts b/apps/meteor/client/hooks/usePruneWarningMessage.spec.ts index a1982f6b81f9d..77d44e6ece876 100644 --- a/apps/meteor/client/hooks/usePruneWarningMessage.spec.ts +++ b/apps/meteor/client/hooks/usePruneWarningMessage.spec.ts @@ -38,9 +38,9 @@ describe('usePruneWarningMessage hook', () => { TTLChannels: 60000, }), }); - expect(result.current).toEqual('a minute June 1, 2024 at 12:30 AM'); + expect(result.current).toEqual('1 minute June 1, 2024 at 12:30 AM'); await jest.advanceTimersByTimeAsync(31 * 60 * 1000); - await waitFor(() => expect(result.current).toEqual('a minute June 1, 2024 at 1:00 AM')); + await waitFor(() => expect(result.current).toEqual('1 minute June 1, 2024 at 1:00 AM')); }); it('Should return the default warning with precision set to every_hour', () => { @@ -52,7 +52,7 @@ describe('usePruneWarningMessage hook', () => { precision: '1', }), }); - expect(result.current).toEqual('a minute June 1, 2024 at 1:00 AM'); + expect(result.current).toEqual('1 minute June 1, 2024 at 1:00 AM'); }); it('Should return the default warning with precision set to every_six_hours', () => { @@ -64,7 +64,7 @@ describe('usePruneWarningMessage hook', () => { precision: '2', }), }); - expect(result.current).toEqual('a minute June 1, 2024 at 6:00 AM'); + expect(result.current).toEqual('1 minute June 1, 2024 at 6:00 AM'); }); it('Should return the default warning with precision set to every_day', () => { @@ -76,7 +76,7 @@ describe('usePruneWarningMessage hook', () => { precision: '3', }), }); - expect(result.current).toEqual('a minute June 2, 2024 at 12:00 AM'); + expect(result.current).toEqual('1 minute June 2, 2024 at 12:00 AM'); }); it('Should return the default warning with advanced precision', () => { @@ -89,7 +89,7 @@ describe('usePruneWarningMessage hook', () => { advancedPrecisionCron: '0 0 1 */1 *', }), }); - expect(result.current).toEqual('a minute July 1, 2024 at 12:00 AM'); + expect(result.current).toEqual('1 minute July 1, 2024 at 12:00 AM'); }); }); @@ -102,7 +102,7 @@ describe('usePruneWarningMessage hook', () => { TTLChannels: 60000, }), }); - expect(result.current).toEqual('a minute June 1, 2024 at 12:30 AM'); + expect(result.current).toEqual('1 minute June 1, 2024 at 12:30 AM'); }); it('Should return the unpinned messages warning', () => { @@ -114,7 +114,7 @@ describe('usePruneWarningMessage hook', () => { doNotPrunePinned: true, }), }); - expect(result.current).toEqual('Unpinned a minute June 1, 2024 at 12:30 AM'); + expect(result.current).toEqual('Unpinned 1 minute June 1, 2024 at 12:30 AM'); }); it('Should return the files only warning', () => { @@ -127,7 +127,7 @@ describe('usePruneWarningMessage hook', () => { filesOnly: true, }), }); - expect(result.current).toEqual('FilesOnly a minute June 1, 2024 at 12:30 AM'); + expect(result.current).toEqual('FilesOnly 1 minute June 1, 2024 at 12:30 AM'); }); it('Should return the unpinned files only warning', () => { @@ -141,7 +141,7 @@ describe('usePruneWarningMessage hook', () => { doNotPrunePinned: true, }), }); - expect(result.current).toEqual('UnpinnedFilesOnly a minute June 1, 2024 at 12:30 AM'); + expect(result.current).toEqual('UnpinnedFilesOnly 1 minute June 1, 2024 at 12:30 AM'); }); }); diff --git a/apps/meteor/client/hooks/useTimeAgo.ts b/apps/meteor/client/hooks/useTimeAgo.ts index 4d4b7d12b7b7a..c159963ede1f8 100644 --- a/apps/meteor/client/hooks/useTimeAgo.ts +++ b/apps/meteor/client/hooks/useTimeAgo.ts @@ -1,9 +1,8 @@ import { useUserPreference, useSetting } from '@rocket.chat/ui-contexts'; -import type { MomentInput } from 'moment'; -import moment from 'moment'; import { useCallback } from 'react'; import { t } from '../../app/utils/lib/i18n'; +import { formatTimeAgo } from '../lib/utils/dateFormat'; const dayFormat = ['h:mm A', 'H:mm'] as const; @@ -11,13 +10,16 @@ export const useTimeAgo = () => { const clockMode = useUserPreference<1 | 2>('clockMode'); const timeFormat = useSetting('Message_TimeFormat', 'LT'); const format = clockMode !== undefined ? dayFormat[clockMode - 1] : timeFormat; + return useCallback( - (time: MomentInput) => { - return moment(time).calendar(null, { - sameDay: format, - lastDay: moment(time).calendar('lastDay').replace('LT', format), - lastWeek: `dddd ${format}`, - sameElse: 'LL', + (time: string | Date | number) => { + return formatTimeAgo(time, { + sameDayFormat: format, + yesterdayLabel: t('Yesterday_at'), + lastDayFormat: format, + lastWeekFormat: `dddd ${format}`, + otherFormat: 'LL', + otherYearFormat: 'LL', }); }, [format], @@ -28,27 +30,15 @@ export const useShortTimeAgo = () => { const clockMode = useUserPreference<1 | 2>('clockMode'); const timeFormat = useSetting('Message_TimeFormat', 'LT'); const format = clockMode !== undefined ? dayFormat[clockMode - 1] : timeFormat; - return useCallback( - (time: MomentInput) => - moment(time).calendar(null, { - sameDay: format, - lastDay: `[${t('Yesterday')}]`, - lastWeek: 'dddd', - sameElse(this: moment.Moment, now) { - /* - Using only this.isBefore(): - ERRORS: - Cannot invoke an object which is possibly 'undefined'. - This expression is not callable. - Not all constituents of type 'CalendarSpecVal' are callable. - Type 'string' has no call signatures. - */ - if (this.isBefore(now, 'year')) { - return 'LL'; - } - return 'MMM Do'; - }, + return useCallback( + (time: string | Date | number) => + formatTimeAgo(time, { + sameDayFormat: format, + yesterdayLabel: t('Yesterday'), + lastWeekFormat: 'dddd', + otherFormat: 'MMM Do', + otherYearFormat: 'LL', }), [format], ); diff --git a/apps/meteor/client/hooks/useTimeFromNow.ts b/apps/meteor/client/hooks/useTimeFromNow.ts index 3cda1e37c2713..6d8af9aa265e1 100644 --- a/apps/meteor/client/hooks/useTimeFromNow.ts +++ b/apps/meteor/client/hooks/useTimeFromNow.ts @@ -1,5 +1,6 @@ -import moment from 'moment'; import { useCallback } from 'react'; +import { formatFromNow } from '../lib/utils/dateFormat'; + export const useTimeFromNow = (withSuffix: boolean) => - useCallback((date?: Date | string) => moment(date).fromNow(!withSuffix), [withSuffix]); + useCallback((date?: Date | string) => formatFromNow(date ?? new Date(), withSuffix), [withSuffix]); diff --git a/apps/meteor/client/hooks/useTimezoneNameList.ts b/apps/meteor/client/hooks/useTimezoneNameList.ts index 6c8547e037a7c..e51d8812ac2c9 100644 --- a/apps/meteor/client/hooks/useTimezoneNameList.ts +++ b/apps/meteor/client/hooks/useTimezoneNameList.ts @@ -1,4 +1,8 @@ -import moment from 'moment-timezone'; import { useMemo } from 'react'; -export const useTimezoneNameList = (): string[] => useMemo(() => moment.tz.names(), []); +const getTimeZoneNames = (): string[] => { + const intl = Intl as typeof Intl & { supportedValuesOf?(key: 'timeZone'): string[] }; + return typeof intl.supportedValuesOf === 'function' ? intl.supportedValuesOf('timeZone') : []; +}; + +export const useTimezoneNameList = (): string[] => useMemo(() => getTimeZoneNames(), []); diff --git a/apps/meteor/client/hooks/useTimezoneTime.ts b/apps/meteor/client/hooks/useTimezoneTime.ts index d6ce1a7929280..9907606320170 100644 --- a/apps/meteor/client/hooks/useTimezoneTime.ts +++ b/apps/meteor/client/hooks/useTimezoneTime.ts @@ -1,29 +1,21 @@ -import moment from 'moment'; +import { guessTimezoneFromOffset } from '@rocket.chat/tools'; import { useState, useEffect } from 'react'; -import { useFormatTime } from './useFormatTime'; - export const useTimezoneTime = (offset: number, interval = 1000): string => { - const [time, setTime] = useState(() => moment().utcOffset(offset)); - - const format = useFormatTime(); + const [now, setNow] = useState(() => new Date()); useEffect(() => { if (offset === undefined) { return; } - const update = (): void => { - setTime(moment().utcOffset(offset)); - }; - - const timer = setInterval(update, interval); - update(); - - return (): void => { - clearInterval(timer); - }; + const timer = setInterval(() => setNow(new Date()), interval); + return () => clearInterval(timer); }, [offset, interval]); - return format(time); + const zone = guessTimezoneFromOffset(offset); + return new Intl.DateTimeFormat(undefined, { + timeZone: zone, + timeStyle: 'short', + }).format(now); }; diff --git a/apps/meteor/client/lib/chats/data.ts b/apps/meteor/client/lib/chats/data.ts index 5206e802e7d0c..bd02100bb9e87 100644 --- a/apps/meteor/client/lib/chats/data.ts +++ b/apps/meteor/client/lib/chats/data.ts @@ -1,7 +1,7 @@ import { isEncryptedMessageContent, type IEditedMessage, type IMessage, type IRoom, type ISubscription } from '@rocket.chat/core-typings'; import { MessageTypes } from '@rocket.chat/message-types'; import { Random } from '@rocket.chat/random'; -import moment from 'moment'; +import { differenceInMinutes } from 'date-fns'; import type { DataAPI } from './ChatAPI'; import { hasAtLeastOnePermission, hasPermission } from '../../../app/authorization/client'; @@ -77,7 +77,7 @@ export const createDataAPI = ({ rid, tmid }: { rid: IRoom['_id']; tmid: IMessage const blockEditInMinutes = settings.peek('Message_AllowEditing_BlockEditInMinutes') as number | undefined; const bypassBlockTimeLimit = hasPermission('bypass-time-limit-edit-and-delete', message.rid); - const elapsedMinutes = moment().diff(message.ts, 'minutes'); + const elapsedMinutes = differenceInMinutes(new Date(), message.ts); if (!bypassBlockTimeLimit && elapsedMinutes && blockEditInMinutes && elapsedMinutes > blockEditInMinutes) { return false; } @@ -215,7 +215,7 @@ export const createDataAPI = ({ rid, tmid }: { rid: IRoom['_id']; tmid: IMessage const blockDeleteInMinutes = settings.peek('Message_AllowDeleting_BlockDeleteInMinutes') as number | undefined; const bypassBlockTimeLimit = hasPermission('bypass-time-limit-edit-and-delete', message.rid); - const elapsedMinutes = moment().diff(message.ts, 'minutes'); + const elapsedMinutes = differenceInMinutes(new Date(), message.ts); const onTimeForDelete = bypassBlockTimeLimit || !blockDeleteInMinutes || !elapsedMinutes || elapsedMinutes <= blockDeleteInMinutes; return deleteAllowed && onTimeForDelete; diff --git a/apps/meteor/client/lib/utils/dateFormat.ts b/apps/meteor/client/lib/utils/dateFormat.ts new file mode 100644 index 0000000000000..f09bea095a887 --- /dev/null +++ b/apps/meteor/client/lib/utils/dateFormat.ts @@ -0,0 +1,97 @@ +import { format, formatDistanceToNow, formatDuration, intervalToDuration, differenceInCalendarDays } from 'date-fns'; +import type { Locale } from 'date-fns'; + +export type DateInput = string | Date | number; + +/** + * Map moment-style locale format tokens to date-fns format string. + * Used for Message_DateFormat and Message_TimeFormat settings (defaults: LL, LT). + */ +export const momentFormatToDateFns = (momentFormat: string): string => { + const tokenMap: Record = { + L: 'P', // 09/04/1986 + LT: 'p', // 8:30 PM + LTS: 'pp', // 8:30:00 PM + LL: 'PPP', // September 4, 1986 + LLL: 'PPP p', // September 4, 1986 8:30 PM + LLLL: 'EEEE, PPP p', + // Common tokens + YYYY: 'yyyy', + YY: 'yy', + Y: 'yyyy', + MMMM: 'MMMM', + MMM: 'MMM', + MM: 'MM', + M: 'M', + Do: 'do', // 4th + DD: 'dd', + D: 'd', + dddd: 'EEEE', + ddd: 'EEE', + HH: 'HH', + H: 'H', + hh: 'hh', + h: 'h', + mm: 'mm', + m: 'm', + ss: 'ss', + s: 's', + A: 'a', + a: 'a', + }; + let out = momentFormat; + const entries = Object.entries(tokenMap).sort(([a], [b]) => b.length - a.length); + for (const [mom, df] of entries) { + out = out.replace(new RegExp(mom.replace(/([.*+?^${}()|[\]\\])/g, '\\$1'), 'g'), df); + } + return out; +}; + +export const formatDate = (date: DateInput, formatStr: string, locale?: Locale): string => { + const d = typeof date === 'object' && date instanceof Date ? date : new Date(date); + const dfFormat = momentFormatToDateFns(formatStr); + return format(d, dfFormat, locale ? { locale } : undefined); +}; + +export const formatTimeAgo = ( + date: DateInput, + options: { + yesterdayLabel: string; + sameDayFormat: string; + lastDayFormat?: string; // if set, show "Yesterday" + format(time, lastDayFormat) + lastWeekFormat: string; + otherFormat: string; + otherYearFormat: string; + }, + locale?: Locale, +): string => { + const d = typeof date === 'object' && date instanceof Date ? date : new Date(date); + const now = new Date(); + const diffDays = differenceInCalendarDays(now, d); + + if (diffDays === 0) { + return format(d, momentFormatToDateFns(options.sameDayFormat), locale ? { locale } : undefined); + } + if (diffDays === 1) { + if (options.lastDayFormat) { + return `${options.yesterdayLabel} ${format(d, momentFormatToDateFns(options.lastDayFormat), locale ? { locale } : undefined)}`; + } + return options.yesterdayLabel; + } + if (diffDays > 1 && diffDays < 7) { + return format(d, momentFormatToDateFns(options.lastWeekFormat), locale ? { locale } : undefined); + } + const diffYears = now.getFullYear() - d.getFullYear(); + const fmt = diffYears !== 0 ? options.otherYearFormat : options.otherFormat; + return format(d, momentFormatToDateFns(fmt), locale ? { locale } : undefined); +}; + +export const formatFromNow = (date: DateInput, addSuffix: boolean, locale?: Locale): string => { + const d = typeof date === 'object' && date instanceof Date ? date : new Date(date); + return formatDistanceToNow(d, { addSuffix, locale }); +}; + +export const formatDurationMs = (timeMs: number, locale?: Locale): string => { + const duration = intervalToDuration({ start: 0, end: timeMs }); + return formatDuration(duration, { locale }); +}; diff --git a/apps/meteor/client/lib/utils/getDateRange.ts b/apps/meteor/client/lib/utils/getDateRange.ts index 6a7cf3b296ceb..2cf3e9148c181 100644 --- a/apps/meteor/client/lib/utils/getDateRange.ts +++ b/apps/meteor/client/lib/utils/getDateRange.ts @@ -1,15 +1,12 @@ -import moment from 'moment'; +import { startOfDay, endOfDay } from 'date-fns'; export const getDateRange = (): { start: string; end: string; } => { - const today = moment(new Date()); - const start = moment(new Date(today.year(), today.month(), today.date(), 0, 0, 0)); - const end = moment(new Date(today.year(), today.month(), today.date(), 23, 59, 59)); - + const now = new Date(); return { - start: start.toISOString(), - end: end.toISOString(), + start: startOfDay(now).toISOString(), + end: endOfDay(now).toISOString(), }; }; diff --git a/apps/meteor/client/lib/utils/timeAgo.ts b/apps/meteor/client/lib/utils/timeAgo.ts index 98e5d936c2d6b..2826a218d98f8 100644 --- a/apps/meteor/client/lib/utils/timeAgo.ts +++ b/apps/meteor/client/lib/utils/timeAgo.ts @@ -1,26 +1,23 @@ import { Tracker } from 'meteor/tracker'; -import type { Moment, MomentInput } from 'moment'; -import moment from 'moment'; import { getUserPreference } from '../../../app/utils/client'; import { t } from '../../../app/utils/lib/i18n'; import { settings } from '../settings'; import { getUserId } from '../user'; +import { formatTimeAgo } from './dateFormat'; const dayFormat = ['h:mm A', 'H:mm']; -export const timeAgo = (date: MomentInput) => { +export const timeAgo = (date: string | Date | number) => { const clockMode = Tracker.nonreactive(() => getUserPreference(getUserId(), 'clockMode', false) as number | boolean); const messageTimeFormat = settings.peek('Message_TimeFormat'); const sameDay = (typeof clockMode === 'number' ? dayFormat[clockMode - 1] : undefined) || messageTimeFormat; - return moment(date).calendar(null, { - lastDay: `[${t('yesterday')}]`, - sameDay, - lastWeek: 'dddd', - sameElse(this: Moment, now) { - const diff = Math.ceil(this.diff(now, 'years', true)); - return diff < 0 ? 'MMM D YYYY' : 'MMM D'; - }, + return formatTimeAgo(date, { + yesterdayLabel: t('yesterday'), + sameDayFormat: sameDay, + lastWeekFormat: 'dddd', + otherFormat: 'MMM d', + otherYearFormat: 'MMM d yyyy', }); }; diff --git a/apps/meteor/client/providers/TranslationProvider.tsx b/apps/meteor/client/providers/TranslationProvider.tsx index c8aaabbf8470c..b9a53c7b78a6f 100644 --- a/apps/meteor/client/providers/TranslationProvider.tsx +++ b/apps/meteor/client/providers/TranslationProvider.tsx @@ -12,10 +12,9 @@ import en from '@rocket.chat/i18n/dist/resources/en.i18n.json'; import { capitalize } from '@rocket.chat/string-helpers'; import { normalizeLanguage } from '@rocket.chat/tools'; import type { TranslationContextValue } from '@rocket.chat/ui-contexts'; -import { useMethod, useSetting, TranslationContext } from '@rocket.chat/ui-contexts'; +import { useSetting, TranslationContext } from '@rocket.chat/ui-contexts'; import type i18next from 'i18next'; import I18NextHttpBackend from 'i18next-http-backend'; -import moment from 'moment'; import type { ReactElement, ReactNode } from 'react'; import { useEffect, useMemo } from 'react'; import { I18nextProvider, initReactI18next, useTranslation } from 'react-i18next'; @@ -189,8 +188,6 @@ type TranslationProviderProps = { }; const TranslationProvider = ({ children }: TranslationProviderProps): ReactElement => { - const loadLocale = useMethod('loadLocale'); - const language = useAutoLanguage(); const i18nextInstance = useI18next(language); useCustomTranslations(i18nextInstance); @@ -215,25 +212,6 @@ const TranslationProvider = ({ children }: TranslationProviderProps): ReactEleme [language, i18nextInstance], ); - useEffect(() => { - if (moment.locales().includes(language.toLowerCase())) { - moment.locale(language); - return; - } - - const locale = !availableLanguages.find((lng) => lng.key === language) ? language.split('-').shift() : language; - - loadLocale(locale ?? language) - .then((localeSrc) => { - localeSrc && Function(localeSrc).call({ moment }); - moment.locale(language); - }) - .catch((error) => { - moment.locale('en'); - console.error('Error loading moment locale:', error); - }); - }, [language, loadLocale, availableLanguages]); - useEffect( () => onLoggedIn(() => { diff --git a/apps/meteor/client/sidebar/badges/SidebarItemBadges.spec.tsx b/apps/meteor/client/sidebar/badges/SidebarItemBadges.spec.tsx index 9866febc2dcaa..d742456b67f2a 100644 --- a/apps/meteor/client/sidebar/badges/SidebarItemBadges.spec.tsx +++ b/apps/meteor/client/sidebar/badges/SidebarItemBadges.spec.tsx @@ -65,7 +65,7 @@ describe('SidebarItemBadges', () => { }, ); - expect(screen.getByRole('status', { name: 'Invited January 1, 2025' })).toBeInTheDocument(); + expect(screen.getByRole('status', { name: 'Invited January 1st, 2025' })).toBeInTheDocument(); }); it('should not render InvitationBadge when subscription does not have status INVITED', () => { diff --git a/apps/meteor/client/startup/startup.ts b/apps/meteor/client/startup/startup.ts index 45fa6c12b1bbb..e9568ae7e2dea 100644 --- a/apps/meteor/client/startup/startup.ts +++ b/apps/meteor/client/startup/startup.ts @@ -1,7 +1,6 @@ import type { UserStatus } from '@rocket.chat/core-typings'; import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; -import moment from 'moment'; import 'highlight.js/styles/github.css'; import { sdk } from '../../app/utils/client/lib/SDKClient'; @@ -31,7 +30,7 @@ Meteor.startup(() => { return; } - const utcOffset = moment().utcOffset() / 60; + const utcOffset = -new Date().getTimezoneOffset() / 60; if (user.utcOffset !== utcOffset) { sdk.call('userSetUtcOffset', utcOffset); } diff --git a/apps/meteor/client/views/admin/engagementDashboard/channels/ChannelsOverview.tsx b/apps/meteor/client/views/admin/engagementDashboard/channels/ChannelsOverview.tsx index bbbb48583658e..24e400998b3c5 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/channels/ChannelsOverview.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/channels/ChannelsOverview.tsx @@ -1,15 +1,15 @@ import { Icon, Margins, Pagination, Skeleton, Table, TableBody, TableCell, TableHead, TableRow, Tile } from '@rocket.chat/fuselage'; -import moment from 'moment'; +import { format } from 'date-fns'; import type { ReactElement } from 'react'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { useChannelsList } from './useChannelsList'; import DownloadDataButton from '../../../../components/dashboards/DownloadDataButton'; import PeriodSelector from '../../../../components/dashboards/PeriodSelector'; import { usePeriodSelectorState } from '../../../../components/dashboards/usePeriodSelectorState'; import Growth from '../../../../components/dataView/Growth'; import EngagementDashboardCardFilter from '../EngagementDashboardCardFilter'; -import { useChannelsList } from './useChannelsList'; const ChannelsOverview = (): ReactElement => { const [period, periodSelectorProps] = usePeriodSelectorState('last 7 days', 'last 30 days', 'last 90 days'); @@ -86,8 +86,8 @@ const ChannelsOverview = (): ReactElement => { {name} - {moment(createdAt).format('L')} - {moment(updatedAt).format('L')} + {format(new Date(createdAt ?? new Date()), 'P')} + {format(new Date(updatedAt ?? new Date()), 'P')} {messagesCount} {messagesVariation} diff --git a/apps/meteor/client/views/admin/engagementDashboard/messages/MessagesSentSection.tsx b/apps/meteor/client/views/admin/engagementDashboard/messages/MessagesSentSection.tsx index 2d4b63227eb4b..c88dc9f909367 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/messages/MessagesSentSection.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/messages/MessagesSentSection.tsx @@ -1,7 +1,7 @@ import { ResponsiveBar } from '@nivo/bar'; import { Box, Flex, Skeleton, Palette, Tooltip } from '@rocket.chat/fuselage'; import colors from '@rocket.chat/fuselage-tokens/colors.json'; -import moment from 'moment'; +import { differenceInDays, addDays, format } from 'date-fns'; import type { ReactElement } from 'react'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; @@ -34,13 +34,16 @@ const MessagesSentSection = ({ timezone }: MessagesSentSectionProps): ReactEleme return []; } - const values = Array.from({ length: moment(data.end).diff(data.start, 'days') + 1 }, (_, i) => ({ - date: moment(data.start).add(i, 'days').toISOString(), + const startDate = new Date(data.start); + const endDate = new Date(data.end); + const daysCount = differenceInDays(endDate, startDate) + 1; + const values = Array.from({ length: daysCount }, (_, i) => ({ + date: addDays(startDate, i).toISOString(), newMessages: 0, })); for (const { day, messages } of data.days ?? []) { - const i = moment(day).diff(data.start, 'days'); + const i = differenceInDays(new Date(day), startDate); if (i >= 0) { values[i].newMessages += messages; } @@ -114,7 +117,7 @@ const MessagesSentSection = ({ timezone }: MessagesSentSectionProps): ReactEleme tickPadding: 8, tickRotation: values.length > 31 ? 90 : 0, truncateTickAt: 0, - format: (date): string => moment(date).format('DD/MM'), + format: (date): string => format(new Date(date), 'dd/MM'), }} axisLeft={{ tickSize: 0, diff --git a/apps/meteor/client/views/admin/engagementDashboard/users/ActiveUsersSection.tsx b/apps/meteor/client/views/admin/engagementDashboard/users/ActiveUsersSection.tsx index abbd31f2c3e8e..9a2ee626cd20b 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/users/ActiveUsersSection.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/users/ActiveUsersSection.tsx @@ -1,7 +1,7 @@ import { ResponsiveLine } from '@nivo/line'; import { Box, Flex, Skeleton, Tile } from '@rocket.chat/fuselage'; import colors from '@rocket.chat/fuselage-tokens/colors.json'; -import moment from 'moment'; +import { addDays, startOfDay, differenceInDays, endOfDay, subDays, format } from 'date-fns'; import type { ReactElement } from 'react'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; @@ -36,13 +36,14 @@ const ActiveUsersSection = ({ timezone }: ActiveUsersSectionProps): ReactElement return []; } + const startDate = new Date(data.start); const createPoint = (i: number): { x: Date; y: number } => ({ - x: moment(data.start).add(i, 'days').startOf('day').toDate(), + x: startOfDay(addDays(startDate, i)), y: 0, }); - const createPoints = (): { x: Date; y: number }[] => - Array.from({ length: moment(data.end).diff(data.start, 'days') }, (_, i) => createPoint(i)); + const daysCount = differenceInDays(new Date(data.end), startDate); + const createPoints = (): { x: Date; y: number }[] => Array.from({ length: daysCount }, (_, i) => createPoint(i)); const dauValuesLocal = createPoints(); const prevDauValue = createPoint(-1); @@ -52,10 +53,11 @@ const ActiveUsersSection = ({ timezone }: ActiveUsersSectionProps): ReactElement const prevMauValue = createPoint(-1); const usersListsMap = data.month.reduce<{ [x: number]: string[] }>((map, dayData) => { - const date = utc - ? moment.utc({ year: dayData.year, month: dayData.month - 1, day: dayData.day }).endOf('day') - : moment({ year: dayData.year, month: dayData.month - 1, day: dayData.day }).endOf('day'); - const dateOffset = date.diff(data.start, 'days'); + const d = utc + ? new Date(Date.UTC(dayData.year, dayData.month - 1, dayData.day)) + : new Date(dayData.year, dayData.month - 1, dayData.day); + const date = utc ? new Date(Date.UTC(dayData.year, dayData.month - 1, dayData.day, 23, 59, 59, 999)) : endOfDay(d); + const dateOffset = differenceInDays(date, startDate); if (dateOffset >= 0 && dauValuesLocal[dateOffset]) { map[dateOffset] = dayData.usersList; dauValuesLocal[dateOffset].y = dayData.users; @@ -107,7 +109,7 @@ const ActiveUsersSection = ({ timezone }: ActiveUsersSectionProps): ReactElement <> { @@ -218,7 +220,7 @@ const ActiveUsersSection = ({ timezone }: ActiveUsersSectionProps): ReactElement tickPadding: 4, tickRotation: 0, tickValues: 'every 3 days', - format: (date): string => moment(date).format('DD/MM'), + format: (date): string => format(new Date(date), 'dd/MM'), }} animate={true} motionConfig='stiff' diff --git a/apps/meteor/client/views/admin/engagementDashboard/users/ContentForDays.tsx b/apps/meteor/client/views/admin/engagementDashboard/users/ContentForDays.tsx index 01c622829e6be..1df3f19f1eeb8 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/users/ContentForDays.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/users/ContentForDays.tsx @@ -1,11 +1,12 @@ import { ResponsiveBar } from '@nivo/bar'; import { Box, Flex, IconButton, Margins, Skeleton } from '@rocket.chat/fuselage'; import colors from '@rocket.chat/fuselage-tokens/colors.json'; -import moment from 'moment'; +import { format, subDays } from 'date-fns'; import type { ReactElement } from 'react'; import { useMemo } from 'react'; import { useWeeklyChatActivity } from './useWeeklyChatActivity'; +import { formatDate } from '../../../../lib/utils/dateFormat'; type ContentForDaysProps = { displacement: number; @@ -23,9 +24,10 @@ const ContentForDays = ({ displacement, onPreviousDateClick, onNextDateClick, ti return null; } - const endOfWeek = moment(data.day); - const startOfWeek = moment(data.day).subtract(6, 'days'); - return `${startOfWeek.format('L')} - ${endOfWeek.format('L')}`; + const dayDate = new Date(data.day); + const endOfWeek = dayDate; + const startOfWeek = subDays(dayDate, 6); + return `${format(startOfWeek, 'P')} - ${format(endOfWeek, 'P')}`; }, [data]); const values = useMemo( @@ -33,10 +35,10 @@ const ContentForDays = ({ displacement, onPreviousDateClick, onNextDateClick, ti data?.month ?.map(({ users, day, month, year }) => ({ users, - day: moment({ year, month: month - 1, day }), + day: new Date(year, month - 1, day).getTime(), })) - ?.sort(({ day: a }, { day: b }) => a.diff(b)) - ?.map(({ users, day }) => ({ users, day: String(day.valueOf()) })) ?? [], + ?.sort((a, b) => a.day - b.day) + ?.map(({ users, day }) => ({ users, day: String(day) })) ?? [], [data], ); @@ -85,7 +87,7 @@ const ContentForDays = ({ displacement, onPreviousDateClick, onNextDateClick, ti tickPadding: 4, tickRotation: 0, tickValues: 'every 3 days', - format: (timestamp): string => moment(parseInt(timestamp, 10)).format('L'), + format: (timestamp): string => formatDate(parseInt(timestamp, 10), 'L'), }} axisLeft={null} animate={true} @@ -98,11 +100,6 @@ const ContentForDays = ({ displacement, onPreviousDateClick, onNextDateClick, ti fill: colors.n600, fontFamily: 'Inter, -apple-system, system-ui, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Meiryo UI", Arial, sans-serif', - fontSize: '10px', - fontStyle: 'normal', - fontWeight: 600, - letterSpacing: '0.2px', - lineHeight: '12px', }, }, }, diff --git a/apps/meteor/client/views/admin/engagementDashboard/users/ContentForHours.tsx b/apps/meteor/client/views/admin/engagementDashboard/users/ContentForHours.tsx index 52772d503e708..000f52e057cc8 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/users/ContentForHours.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/users/ContentForHours.tsx @@ -2,7 +2,7 @@ import { ResponsiveBar } from '@nivo/bar'; import { Box, Button, Chevron, Skeleton, Tooltip } from '@rocket.chat/fuselage'; import { useBreakpoints } from '@rocket.chat/fuselage-hooks'; import colors from '@rocket.chat/fuselage-tokens/colors.json'; -import moment from 'moment'; +import { format } from 'date-fns'; import type { ReactElement } from 'react'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; @@ -50,7 +50,7 @@ const ContentForHours = ({ displacement, onPreviousDateClick, onNextDateClick, t - {data ? moment(data.day).format(displacement < 7 ? 'dddd' : 'L') : null} + {data ? format(new Date(data.day), displacement < 7 ? 'EEEE' : 'P') : null} -
- - + + {t('Use_url_for_avatar')} + + + } + value={avatarFromUrl} + onChange={handleAvatarFromUrlChange} + error={avatarUrlError} + onKeyDown={(event): void => { + if (event.key === 'Enter') { + handleAddUrl(); + } + }} + /> + + {avatarUrlError && {avatarUrlError}} +
diff --git a/apps/meteor/client/lib/utils/isSafeAvatarUrl.spec.ts b/apps/meteor/client/lib/utils/isSafeAvatarUrl.spec.ts new file mode 100644 index 0000000000000..cacffaa460c2c --- /dev/null +++ b/apps/meteor/client/lib/utils/isSafeAvatarUrl.spec.ts @@ -0,0 +1,84 @@ +import { isSafeAvatarUrl } from './isSafeAvatarUrl'; + +describe('valid URLs', () => { + it('should accept HTTPS URLs', () => { + expect(isSafeAvatarUrl('https://example.com/avatar.png')).toBe(true); + expect(isSafeAvatarUrl('https://cdn.example.com/user/123/avatar.jpg')).toBe(true); + }); + + it('should accept HTTP URLs', () => { + expect(isSafeAvatarUrl('http://example.com/avatar.png')).toBe(true); + expect(isSafeAvatarUrl('http://localhost:3000/avatar.png')).toBe(true); + }); + + it('should accept data URLs with image MIME types', () => { + expect(isSafeAvatarUrl('data:image/png;base64,iVBORw0KGgoAAAANSUhEUg')).toBe(true); + expect(isSafeAvatarUrl('data:image/jpeg;base64,/9j/4AAQSkZJRg')).toBe(true); + expect(isSafeAvatarUrl('data:image/gif;base64,R0lGODlh')).toBe(true); + expect(isSafeAvatarUrl('data:image/webp;base64,UklGRiQA')).toBe(true); + expect(isSafeAvatarUrl('data:image/svg+xml;base64,PHN2Zw')).toBe(true); + }); + + it('should be case-insensitive for protocols', () => { + expect(isSafeAvatarUrl('HTTPS://example.com/avatar.png')).toBe(true); + expect(isSafeAvatarUrl('HTTP://example.com/avatar.png')).toBe(true); + expect(isSafeAvatarUrl('DATA:IMAGE/PNG;base64,iVBORw0KGgoAAAANSUhEUg')).toBe(true); + }); +}); + +describe('invalid URLs', () => { + it('should reject javascript: protocol', () => { + expect(isSafeAvatarUrl('javascript:alert(1)')).toBe(false); + expect(isSafeAvatarUrl('javascript:void(0)')).toBe(false); + }); + + it('should reject file: protocol', () => { + expect(isSafeAvatarUrl('file:///etc/passwd')).toBe(false); + expect(isSafeAvatarUrl('file:///C:/Windows/System32')).toBe(false); + }); + + it('should reject data: URLs with non-image MIME types', () => { + expect(isSafeAvatarUrl('data:text/html;base64,PHNjcmlwdD4')).toBe(false); + expect(isSafeAvatarUrl('data:text/javascript;base64,YWxlcnQoMSk')).toBe(false); + expect(isSafeAvatarUrl('data:application/javascript;base64,YWxlcnQoMSk')).toBe(false); + expect(isSafeAvatarUrl('data:text/plain;base64,SGVsbG8=')).toBe(false); + }); + + it('should reject ftp: protocol', () => { + expect(isSafeAvatarUrl('ftp://example.com/avatar.png')).toBe(false); + }); + + it('should reject malformed URLs', () => { + expect(isSafeAvatarUrl('not a url')).toBe(false); + expect(isSafeAvatarUrl('htp://missing-t.com')).toBe(false); + expect(isSafeAvatarUrl('://example.com')).toBe(false); + }); + + it('should reject empty strings', () => { + expect(isSafeAvatarUrl('')).toBe(false); + }); + + it('should reject other dangerous protocols', () => { + expect(isSafeAvatarUrl('vbscript:msgbox(1)')).toBe(false); + expect(isSafeAvatarUrl('data:text/html,')).toBe(false); + }); +}); + +describe('URL edge cases', () => { + it('should handle URLs with query parameters', () => { + expect(isSafeAvatarUrl('https://example.com/avatar.png?size=large&format=webp')).toBe(true); + }); + + it('should handle URLs with fragments', () => { + expect(isSafeAvatarUrl('https://example.com/avatar.png#profile')).toBe(true); + }); + + it('should handle URLs with authentication', () => { + expect(isSafeAvatarUrl('https://user:pass@example.com/avatar.png')).toBe(true); + }); + + it('should handle URLs with non-standard ports', () => { + expect(isSafeAvatarUrl('http://example.com:8080/avatar.png')).toBe(true); + expect(isSafeAvatarUrl('https://example.com:443/avatar.png')).toBe(true); + }); +}); diff --git a/apps/meteor/client/lib/utils/isSafeAvatarUrl.ts b/apps/meteor/client/lib/utils/isSafeAvatarUrl.ts new file mode 100644 index 0000000000000..8c57473a67207 --- /dev/null +++ b/apps/meteor/client/lib/utils/isSafeAvatarUrl.ts @@ -0,0 +1,17 @@ +export function isSafeAvatarUrl(urlString: string): boolean { + try { + const url = new URL(urlString); + const protocol = url.protocol.toLowerCase(); + + if (protocol === 'http:' || protocol === 'https:') { + return true; + } + if (protocol === 'data:') { + return urlString.toLowerCase().startsWith('data:image/'); + } + + return false; + } catch { + return false; + } +} diff --git a/apps/meteor/tests/e2e/account-profile.spec.ts b/apps/meteor/tests/e2e/account-profile.spec.ts index 6e3c1e33073db..7ee63abe1cdd2 100644 --- a/apps/meteor/tests/e2e/account-profile.spec.ts +++ b/apps/meteor/tests/e2e/account-profile.spec.ts @@ -58,12 +58,18 @@ test.describe.serial('settings-account-profile', () => { await expect(poAccountProfile.userAvatarEditor).toHaveAttribute('src'); }); - test('should display a skeleton if the image url is not valid', async () => { + test('should show inline error if the image url is not valid', async () => { await poAccountProfile.inputAvatarLink.fill('https://invalidUrl'); await poAccountProfile.btnSetAvatarLink.click(); - await poAccountProfile.btnSubmit.click(); - await expect(poAccountProfile.userAvatarEditor).not.toHaveAttribute('src'); + await expect(poAccountProfile.errorInvalidUrl).toBeVisible(); + }); + + test('should show inline error if url does not point to an image', async () => { + await poAccountProfile.inputAvatarLink.fill('https://google.com'); + await poAccountProfile.btnSetAvatarLink.click(); + + await expect(poAccountProfile.errorInvalidUrl).toBeVisible(); }); }); }); diff --git a/apps/meteor/tests/e2e/page-objects/account-profile.ts b/apps/meteor/tests/e2e/page-objects/account-profile.ts index 9a672ec34d835..0c1b9924ba45e 100644 --- a/apps/meteor/tests/e2e/page-objects/account-profile.ts +++ b/apps/meteor/tests/e2e/page-objects/account-profile.ts @@ -119,4 +119,12 @@ export class AccountProfile extends Account { get btnDeleteMyAccount(): Locator { return this.page.getByRole('button', { name: 'Delete my account' }); } + + private getErrorAlertByText(text: string): Locator { + return this.page.getByRole('alert').filter({ hasText: text }); + } + + get errorInvalidUrl(): Locator { + return this.getErrorAlertByText('Invalid image URL'); + } } diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index b20b4c33207d9..4def1e5f87154 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -7162,5 +7162,6 @@ "message_body": "message body", "message_attachment": "message attachment", "system_message_body": "system message body", - "No_changes_to_save": "No changes to save" + "No_changes_to_save": "No changes to save", + "Avatar_preview_updated": "Avatar preview updated" } \ No newline at end of file From dd56c9818e99ba555f38769d346f2fe3bf235023 Mon Sep 17 00:00:00 2001 From: Douglas Fabris Date: Fri, 10 Apr 2026 00:46:52 -0300 Subject: [PATCH 46/51] test: Enforce exact match for button locators in team modal (#40104) --- .../e2e/page-objects/fragments/flextabs/channels-flextab.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/meteor/tests/e2e/page-objects/fragments/flextabs/channels-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/channels-flextab.ts index d40cecdd489ea..f3f8dc7d9db4d 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/flextabs/channels-flextab.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/flextabs/channels-flextab.ts @@ -15,7 +15,7 @@ class AddExistingChannelModal extends Modal { } get btnAdd(): Locator { - return this.root.getByRole('button', { name: 'Add' }); + return this.root.getByRole('button', { name: 'Add', exact: true }); } async confirmAdd() { @@ -42,11 +42,11 @@ export class ChannelsFlexTab extends FlexTab { } get btnAddExisting(): Locator { - return this.root.getByRole('button', { name: 'Add Existing' }); + return this.root.getByRole('button', { name: 'Add Existing', exact: true }); } get btnCreateNew(): Locator { - return this.root.getByRole('button', { name: 'Create new' }); + return this.root.getByRole('button', { name: 'Create new', exact: true }); } get channelsList(): Locator { From 18a26c805da1640c1558c144f66605d978173e7b Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 10 Apr 2026 09:57:18 -0300 Subject: [PATCH 47/51] regression: fix multiple compounding keys in sequence (#40108) --- .../composer/messageBox/wrapSelection.spec.ts | 191 ++++++++++++++++++ .../room/composer/messageBox/wrapSelection.ts | 8 + 2 files changed, 199 insertions(+) create mode 100644 apps/meteor/client/views/room/composer/messageBox/wrapSelection.spec.ts diff --git a/apps/meteor/client/views/room/composer/messageBox/wrapSelection.spec.ts b/apps/meteor/client/views/room/composer/messageBox/wrapSelection.spec.ts new file mode 100644 index 0000000000000..6686148393508 --- /dev/null +++ b/apps/meteor/client/views/room/composer/messageBox/wrapSelection.spec.ts @@ -0,0 +1,191 @@ +import { handleSelectionWrapping } from './wrapSelection'; +import type { ChatAPI, ComposerAPI } from '../../../../lib/chats/ChatAPI'; + +const createTextarea = (value: string, selectionStart: number, selectionEnd: number): HTMLTextAreaElement => { + const textarea = document.createElement('textarea'); + textarea.value = value; + textarea.selectionStart = selectionStart; + textarea.selectionEnd = selectionEnd; + return textarea; +}; + +const createMockComposer = (text: string): Pick => ({ + text, + wrapSelection: jest.fn(() => ({ selectionStart: 0, selectionEnd: 0, value: '' })), +}); + +const createInputEvent = (textarea: HTMLTextAreaElement, data: string, isComposing = false): InputEvent => { + const event = new InputEvent('input', { + data, + inputType: 'insertText', + isComposing, + bubbles: true, + cancelable: true, + }); + + Object.defineProperty(event, 'target', { value: textarea, writable: false }); + + return event; +}; + +describe('handleSelectionWrapping', () => { + describe('dead key / IME composition scenarios', () => { + it('should NOT wrap when the selected text is the same character just typed (dead key double-press)', () => { + // Simulates: user presses ' twice on a Brazilian/international keyboard + // After composition ends, the browser has: + // - inserted the character ' into the textarea + // - selected it (selectionStart=0, selectionEnd=1) + // - fired an InputEvent with data="'" + const textarea = createTextarea("'", 0, 1); + const composer = createMockComposer("'"); + const chat = { composer } as unknown as ChatAPI; + + const event = createInputEvent(textarea, "'"); + + const result = handleSelectionWrapping(event, chat); + + expect(result).toBe(false); + expect(composer.wrapSelection).not.toHaveBeenCalled(); + }); + + it('should NOT wrap when dead key composition produces a character mid-text', () => { + // User is typing "hello'" — the dead key inserts ' and selects it + const textarea = createTextarea("hello'", 5, 6); + const composer = createMockComposer("hello'"); + const chat = { composer } as unknown as ChatAPI; + + const event = createInputEvent(textarea, "'"); + + const result = handleSelectionWrapping(event, chat); + + expect(result).toBe(false); + expect(composer.wrapSelection).not.toHaveBeenCalled(); + }); + + it('should NOT wrap when backtick dead key is pressed twice', () => { + const textarea = createTextarea('`', 0, 1); + const composer = createMockComposer('`'); + const chat = { composer } as unknown as ChatAPI; + + const event = createInputEvent(textarea, '`'); + + const result = handleSelectionWrapping(event, chat); + + expect(result).toBe(false); + expect(composer.wrapSelection).not.toHaveBeenCalled(); + }); + + it('should NOT wrap when tilde dead key is pressed twice', () => { + const textarea = createTextarea('˜', 0, 1); + const composer = createMockComposer('˜'); + const chat = { composer } as unknown as ChatAPI; + + const event = createInputEvent(textarea, '˜'); + + const result = handleSelectionWrapping(event, chat); + + expect(result).toBe(false); + expect(composer.wrapSelection).not.toHaveBeenCalled(); + }); + }); + + describe('legitimate wrapping scenarios', () => { + it('should wrap when user selects text and types a wrapping character', () => { + // User selects "hello" and types ' + const textarea = createTextarea('hello', 0, 5); + const composer = createMockComposer('hello'); + const chat = { composer } as unknown as ChatAPI; + + const event = createInputEvent(textarea, "'"); + + const result = handleSelectionWrapping(event, chat); + + expect(result).toBe(true); + expect(composer.wrapSelection).toHaveBeenCalledWith("'{{text}}'"); + }); + + it('should wrap when user selects partial text and types a wrapping character', () => { + // User selects "world" in "hello world" and types * + const textarea = createTextarea('hello world', 6, 11); + const composer = createMockComposer('hello world'); + const chat = { composer } as unknown as ChatAPI; + + const event = createInputEvent(textarea, '*'); + + const result = handleSelectionWrapping(event, chat); + + expect(result).toBe(true); + expect(composer.wrapSelection).toHaveBeenCalledWith('*{{text}}*'); + }); + + it('should wrap with backtick when text is selected', () => { + const textarea = createTextarea('some code here', 5, 9); + const composer = createMockComposer('some code here'); + const chat = { composer } as unknown as ChatAPI; + + const event = createInputEvent(textarea, '`'); + + const result = handleSelectionWrapping(event, chat); + + expect(result).toBe(true); + expect(composer.wrapSelection).toHaveBeenCalledWith('`{{text}}`'); + }); + }); + + describe('no-op scenarios', () => { + it('should return false when there is no selection (cursor only)', () => { + const textarea = createTextarea('hello', 3, 3); + const composer = createMockComposer('hello'); + const chat = { composer } as unknown as ChatAPI; + + const event = createInputEvent(textarea, "'"); + + const result = handleSelectionWrapping(event, chat); + + expect(result).toBe(false); + expect(composer.wrapSelection).not.toHaveBeenCalled(); + }); + + it('should return false when there is no composer', () => { + const textarea = createTextarea('hello', 0, 5); + const chat = {} as unknown as ChatAPI; + + const event = createInputEvent(textarea, "'"); + + const result = handleSelectionWrapping(event, chat); + + expect(result).toBe(false); + }); + + it('should return false for non-wrapping characters', () => { + const textarea = createTextarea('hello', 0, 5); + const composer = createMockComposer('hello'); + const chat = { composer } as unknown as ChatAPI; + + const event = createInputEvent(textarea, 'a'); + + const result = handleSelectionWrapping(event, chat); + + expect(result).toBe(false); + expect(composer.wrapSelection).not.toHaveBeenCalled(); + }); + + it('should return false when event.data is null', () => { + const textarea = createTextarea('hello', 0, 5); + const composer = createMockComposer('hello'); + const chat = { composer } as unknown as ChatAPI; + + const event = new InputEvent('input', { + data: null, + inputType: 'deleteContentBackward', + bubbles: true, + }); + Object.defineProperty(event, 'target', { value: textarea, writable: false }); + + const result = handleSelectionWrapping(event, chat); + + expect(result).toBe(false); + expect(composer.wrapSelection).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/apps/meteor/client/views/room/composer/messageBox/wrapSelection.ts b/apps/meteor/client/views/room/composer/messageBox/wrapSelection.ts index f888af94ae3f0..6ac9f35455151 100644 --- a/apps/meteor/client/views/room/composer/messageBox/wrapSelection.ts +++ b/apps/meteor/client/views/room/composer/messageBox/wrapSelection.ts @@ -30,6 +30,14 @@ export const handleSelectionWrapping = (event: InputEvent, chat: ChatAPI): boole const input = event.target as HTMLTextAreaElement; const { selectionStart, selectionEnd } = input; + const testSelection = input.value.slice(selectionStart, selectionEnd); + // if the selection is the same of the data, return false + if (testSelection === event.data) { + return false; + } + if (event.data === chat.composer?.text) { + return false; + } if (selectionStart === selectionEnd) { return false; } From 619ec70e2666261da8fe3ff09e7bfc7a669fe07a Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 10 Apr 2026 13:05:08 -0300 Subject: [PATCH 48/51] perf: slim react-aria and react-stately barrel imports (-489 KB) - Add yarn patches for react-aria and react-stately that slim their barrel entry points to only re-export the sub-packages actually used - Replace barrel imports with direct sub-package imports across apps/meteor and workspace packages (gazzodown, ui-client, ui-contexts, ui-voip) --- .../react-aria-npm-3.37.0-83959bd2fa.patch | 316 ++++++++++++++++++ .../react-stately-npm-3.17.0-264cc7a43c.patch | 149 +++++++++ .../components/ImageGallery/ImageGallery.tsx | 2 +- .../client/components/ResultsLiveRegion.tsx | 2 +- .../components/UserCard/UserCardDialog.tsx | 4 +- .../meteor/client/navbar/NavBarNavigation.tsx | 2 +- .../navbar/NavBarSearch/NavBarSearch.tsx | 5 +- .../NavBarSearch/NavBarSearchListbox.tsx | 4 +- .../NavBarSearch/hooks/useSearchClick.ts | 2 +- .../NavBarSearch/hooks/useSearchFocus.ts | 2 +- .../NavBarSearch/hooks/useSearchNavigation.ts | 4 +- .../RoomList/useSidebarListNavigation.ts | 2 +- apps/meteor/client/sidebar/SidebarRegion.tsx | 2 +- .../accessibility/AccessibilityPage.tsx | 2 +- .../account/profile/AccountProfileForm.tsx | 2 +- .../client/views/modal/uikit/ModalBlock.tsx | 2 +- .../views/navigation/NavigationRegion.tsx | 2 +- .../RoomList/useSidebarListNavigation.ts | 2 +- apps/meteor/client/views/room/Room.tsx | 2 +- .../VideoConfPopup/TimedVideoConfPopup.tsx | 2 +- .../VideoConfPopups/VideoConfPopups.tsx | 2 +- .../room/hooks/useMessageListNavigation.ts | 3 +- .../views/room/providers/UserCardProvider.tsx | 4 +- docs/bundle-optimization-react-aria.md | 118 +++++++ package.json | 4 +- .../gazzodown/src/MarkupInteractionContext.ts | 2 +- .../Contextualbar/ContextualbarDialog.tsx | 5 +- .../src/components/Modal/ModalRegion.tsx | 2 +- packages/ui-contexts/src/UserCardContext.ts | 4 +- .../ui-voip/src/components/Keypad/Key.tsx | 3 +- .../ui-voip/src/components/Keypad/Keypad.tsx | 2 +- .../ui-voip/src/components/Widget/Widget.tsx | 2 +- yarn.lock | 135 +++++--- 33 files changed, 721 insertions(+), 75 deletions(-) create mode 100644 .yarn/patches/react-aria-npm-3.37.0-83959bd2fa.patch create mode 100644 .yarn/patches/react-stately-npm-3.17.0-264cc7a43c.patch create mode 100644 docs/bundle-optimization-react-aria.md diff --git a/.yarn/patches/react-aria-npm-3.37.0-83959bd2fa.patch b/.yarn/patches/react-aria-npm-3.37.0-83959bd2fa.patch new file mode 100644 index 0000000000000..4cceb4611139a --- /dev/null +++ b/.yarn/patches/react-aria-npm-3.37.0-83959bd2fa.patch @@ -0,0 +1,316 @@ +diff --git a/dist/import.mjs b/dist/import.mjs +index a13ba8b37e27230ec01d4c31140127912208666c..97d6aa506f273263c2a99a9bc80731ac2c38eea6 100644 +--- a/dist/import.mjs ++++ b/dist/import.mjs +@@ -1,50 +1,14 @@ +-/* +- * Copyright 2020 Adobe. All rights reserved. +- * This file is licensed to you under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. You may obtain a copy +- * of the License at http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software distributed under +- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +- * OF ANY KIND, either express or implied. See the License for the specific language +- * governing permissions and limitations under the License. +- */ +- +-export {useBreadcrumbItem, useBreadcrumbs} from '@react-aria/breadcrumbs'; +-export {useButton, useToggleButton, useToggleButtonGroup, useToggleButtonGroupItem} from '@react-aria/button'; +-export {useCalendar, useCalendarCell, useCalendarGrid, useRangeCalendar} from '@react-aria/calendar'; +-export {useCheckbox, useCheckboxGroup, useCheckboxGroupItem} from '@react-aria/checkbox'; +-export {useColorArea, useColorChannelField, useColorField, useColorSlider, useColorSwatch, useColorWheel} from '@react-aria/color'; +-export {useComboBox} from '@react-aria/combobox'; +-export {useDateField, useDatePicker, useDateRangePicker, useDateSegment, useTimeField} from '@react-aria/datepicker'; +-export {useDialog} from '@react-aria/dialog'; +-export {useDisclosure} from '@react-aria/disclosure'; +-export {useDrag, useDrop, useDraggableCollection, useDroppableCollection, useDroppableItem, useDropIndicator, useDraggableItem, useClipboard, DragPreview, ListDropTargetDelegate, DIRECTORY_DRAG_TYPE, isDirectoryDropItem, isFileDropItem, isTextDropItem} from '@react-aria/dnd'; ++// Slim barrel: only exports actually used ++export {useButton} from '@react-aria/button'; + export {FocusRing, FocusScope, useFocusManager, useFocusRing, useFocusable} from '@react-aria/focus'; +-export {I18nProvider, useCollator, useDateFormatter, useFilter, useLocale, useLocalizedStringFormatter, useMessageFormatter, useNumberFormatter} from '@react-aria/i18n'; ++export {useNumberFormatter} from '@react-aria/i18n'; + export {useFocus, useFocusVisible, useFocusWithin, useHover, useInteractOutside, useKeyboard, useMove, usePress, useLongPress} from '@react-aria/interactions'; +-export {useField, useLabel} from '@react-aria/label'; +-export {useGridList, useGridListItem, useGridListSelectionCheckbox} from '@react-aria/gridlist'; +-export {useLink} from '@react-aria/link'; + export {useListBox, useListBoxSection, useOption} from '@react-aria/listbox'; +-export {useMenu, useMenuItem, useMenuSection, useMenuTrigger, useSubmenuTrigger} from '@react-aria/menu'; +-export {useMeter} from '@react-aria/meter'; +-export {useNumberField} from '@react-aria/numberfield'; +-export {DismissButton, ModalProvider, Overlay, OverlayContainer, OverlayProvider, useModal, useModalOverlay, useModalProvider, useOverlay, useOverlayPosition, useOverlayTrigger, usePopover, usePreventScroll} from '@react-aria/overlays'; +-export {useProgressBar} from '@react-aria/progress'; +-export {useRadio, useRadioGroup} from '@react-aria/radio'; +-export {useSearchField} from '@react-aria/searchfield'; +-export {HiddenSelect, useHiddenSelect, useSelect} from '@react-aria/select'; +-export {ListKeyboardDelegate} from '@react-aria/selection'; ++export {useMenu, useMenuItem, useMenuSection, useMenuTrigger} from '@react-aria/menu'; ++export {DismissButton, Overlay, useOverlayTrigger, usePopover} from '@react-aria/overlays'; ++export {HiddenSelect, useSelect} from '@react-aria/select'; + export {useSeparator} from '@react-aria/separator'; +-export {SSRProvider, useIsSSR} from '@react-aria/ssr'; + export {useSlider, useSliderThumb} from '@react-aria/slider'; +-export {useSwitch} from '@react-aria/switch'; +-export {useTable, useTableCell, useTableColumnHeader, useTableColumnResize, useTableHeaderRow, useTableRow, useTableRowGroup, useTableSelectAllCheckbox, useTableSelectionCheckbox} from '@react-aria/table'; +-export {useTab, useTabList, useTabPanel} from '@react-aria/tabs'; +-export {useTag, useTagGroup} from '@react-aria/tag'; +-export {useTextField} from '@react-aria/textfield'; +-export {useTooltip, useTooltipTrigger} from '@react-aria/tooltip'; +-export {chain, mergeProps, useId, useObjectRef, RouterProvider} from '@react-aria/utils'; ++export {chain, mergeProps, useId, useObjectRef} from '@react-aria/utils'; + export {VisuallyHidden, useVisuallyHidden} from '@react-aria/visually-hidden'; +- ++export {useDialog} from '@react-aria/dialog'; +diff --git a/dist/main.js b/dist/main.js +index b6a2ce3a780a09aeb416d7330ffcf6fd0b36b218..98e720a4660bdcd0384509786d04681a8ba98886 100644 +--- a/dist/main.js ++++ b/dist/main.js +@@ -1,172 +1,15 @@ + "use strict"; +- + exports.__esModule = true; +-exports.useRadioGroup = exports.useRadio = exports.useProgressBar = exports.usePreventScroll = exports.usePress = exports.usePopover = exports.useOverlayTrigger = exports.useOverlayPosition = exports.useOverlay = exports.useOption = exports.useObjectRef = exports.useNumberFormatter = exports.useNumberField = exports.useMove = exports.useModalProvider = exports.useModalOverlay = exports.useModal = exports.useMeter = exports.useMessageFormatter = exports.useMenuTrigger = exports.useMenuSection = exports.useMenuItem = exports.useMenu = exports.useLongPress = exports.useLocalizedStringFormatter = exports.useLocale = exports.useListBoxSection = exports.useListBox = exports.useLink = exports.useLabel = exports.useKeyboard = exports.useIsSSR = exports.useInteractOutside = exports.useId = exports.useHover = exports.useHiddenSelect = exports.useGridListSelectionCheckbox = exports.useGridListItem = exports.useGridList = exports.useFocusable = exports.useFocusWithin = exports.useFocusVisible = exports.useFocusRing = exports.useFocusManager = exports.useFocus = exports.useFilter = exports.useField = exports.useDroppableItem = exports.useDroppableCollection = exports.useDropIndicator = exports.useDrop = exports.useDraggableItem = exports.useDraggableCollection = exports.useDrag = exports.useDisclosure = exports.useDialog = exports.useDateSegment = exports.useDateRangePicker = exports.useDatePicker = exports.useDateFormatter = exports.useDateField = exports.useComboBox = exports.useColorWheel = exports.useColorSwatch = exports.useColorSlider = exports.useColorField = exports.useColorChannelField = exports.useColorArea = exports.useCollator = exports.useClipboard = exports.useCheckboxGroupItem = exports.useCheckboxGroup = exports.useCheckbox = exports.useCalendarGrid = exports.useCalendarCell = exports.useCalendar = exports.useButton = exports.useBreadcrumbs = exports.useBreadcrumbItem = exports.mergeProps = exports.isTextDropItem = exports.isFileDropItem = exports.isDirectoryDropItem = exports.chain = exports.VisuallyHidden = exports.SSRProvider = exports.RouterProvider = exports.OverlayProvider = exports.OverlayContainer = exports.Overlay = exports.ModalProvider = exports.ListKeyboardDelegate = exports.ListDropTargetDelegate = exports.I18nProvider = exports.HiddenSelect = exports.FocusScope = exports.FocusRing = exports.DragPreview = exports.DismissButton = exports.DIRECTORY_DRAG_TYPE = void 0; +-exports.useVisuallyHidden = exports.useTooltipTrigger = exports.useTooltip = exports.useToggleButtonGroupItem = exports.useToggleButtonGroup = exports.useToggleButton = exports.useTimeField = exports.useTextField = exports.useTagGroup = exports.useTag = exports.useTableSelectionCheckbox = exports.useTableSelectAllCheckbox = exports.useTableRowGroup = exports.useTableRow = exports.useTableHeaderRow = exports.useTableColumnResize = exports.useTableColumnHeader = exports.useTableCell = exports.useTable = exports.useTabPanel = exports.useTabList = exports.useTab = exports.useSwitch = exports.useSubmenuTrigger = exports.useSliderThumb = exports.useSlider = exports.useSeparator = exports.useSelect = exports.useSearchField = exports.useRangeCalendar = void 0; +-var _breadcrumbs = require("@react-aria/breadcrumbs"); +-exports.useBreadcrumbItem = _breadcrumbs.useBreadcrumbItem; +-exports.useBreadcrumbs = _breadcrumbs.useBreadcrumbs; +-var _button = require("@react-aria/button"); +-exports.useButton = _button.useButton; +-exports.useToggleButton = _button.useToggleButton; +-exports.useToggleButtonGroup = _button.useToggleButtonGroup; +-exports.useToggleButtonGroupItem = _button.useToggleButtonGroupItem; +-var _calendar = require("@react-aria/calendar"); +-exports.useCalendar = _calendar.useCalendar; +-exports.useCalendarCell = _calendar.useCalendarCell; +-exports.useCalendarGrid = _calendar.useCalendarGrid; +-exports.useRangeCalendar = _calendar.useRangeCalendar; +-var _checkbox = require("@react-aria/checkbox"); +-exports.useCheckbox = _checkbox.useCheckbox; +-exports.useCheckboxGroup = _checkbox.useCheckboxGroup; +-exports.useCheckboxGroupItem = _checkbox.useCheckboxGroupItem; +-var _color = require("@react-aria/color"); +-exports.useColorArea = _color.useColorArea; +-exports.useColorChannelField = _color.useColorChannelField; +-exports.useColorField = _color.useColorField; +-exports.useColorSlider = _color.useColorSlider; +-exports.useColorSwatch = _color.useColorSwatch; +-exports.useColorWheel = _color.useColorWheel; +-var _combobox = require("@react-aria/combobox"); +-exports.useComboBox = _combobox.useComboBox; +-var _datepicker = require("@react-aria/datepicker"); +-exports.useDateField = _datepicker.useDateField; +-exports.useDatePicker = _datepicker.useDatePicker; +-exports.useDateRangePicker = _datepicker.useDateRangePicker; +-exports.useDateSegment = _datepicker.useDateSegment; +-exports.useTimeField = _datepicker.useTimeField; +-var _dialog = require("@react-aria/dialog"); +-exports.useDialog = _dialog.useDialog; +-var _disclosure = require("@react-aria/disclosure"); +-exports.useDisclosure = _disclosure.useDisclosure; +-var _dnd = require("@react-aria/dnd"); +-exports.useDrag = _dnd.useDrag; +-exports.useDrop = _dnd.useDrop; +-exports.useDraggableCollection = _dnd.useDraggableCollection; +-exports.useDroppableCollection = _dnd.useDroppableCollection; +-exports.useDroppableItem = _dnd.useDroppableItem; +-exports.useDropIndicator = _dnd.useDropIndicator; +-exports.useDraggableItem = _dnd.useDraggableItem; +-exports.useClipboard = _dnd.useClipboard; +-exports.DragPreview = _dnd.DragPreview; +-exports.ListDropTargetDelegate = _dnd.ListDropTargetDelegate; +-exports.DIRECTORY_DRAG_TYPE = _dnd.DIRECTORY_DRAG_TYPE; +-exports.isDirectoryDropItem = _dnd.isDirectoryDropItem; +-exports.isFileDropItem = _dnd.isFileDropItem; +-exports.isTextDropItem = _dnd.isTextDropItem; +-var _focus = require("@react-aria/focus"); +-exports.FocusRing = _focus.FocusRing; +-exports.FocusScope = _focus.FocusScope; +-exports.useFocusManager = _focus.useFocusManager; +-exports.useFocusRing = _focus.useFocusRing; +-exports.useFocusable = _focus.useFocusable; +-var _i18n = require("@react-aria/i18n"); +-exports.I18nProvider = _i18n.I18nProvider; +-exports.useCollator = _i18n.useCollator; +-exports.useDateFormatter = _i18n.useDateFormatter; +-exports.useFilter = _i18n.useFilter; +-exports.useLocale = _i18n.useLocale; +-exports.useLocalizedStringFormatter = _i18n.useLocalizedStringFormatter; +-exports.useMessageFormatter = _i18n.useMessageFormatter; +-exports.useNumberFormatter = _i18n.useNumberFormatter; +-var _interactions = require("@react-aria/interactions"); +-exports.useFocus = _interactions.useFocus; +-exports.useFocusVisible = _interactions.useFocusVisible; +-exports.useFocusWithin = _interactions.useFocusWithin; +-exports.useHover = _interactions.useHover; +-exports.useInteractOutside = _interactions.useInteractOutside; +-exports.useKeyboard = _interactions.useKeyboard; +-exports.useMove = _interactions.useMove; +-exports.usePress = _interactions.usePress; +-exports.useLongPress = _interactions.useLongPress; +-var _label = require("@react-aria/label"); +-exports.useField = _label.useField; +-exports.useLabel = _label.useLabel; +-var _gridlist = require("@react-aria/gridlist"); +-exports.useGridList = _gridlist.useGridList; +-exports.useGridListItem = _gridlist.useGridListItem; +-exports.useGridListSelectionCheckbox = _gridlist.useGridListSelectionCheckbox; +-var _link = require("@react-aria/link"); +-exports.useLink = _link.useLink; +-var _listbox = require("@react-aria/listbox"); +-exports.useListBox = _listbox.useListBox; +-exports.useListBoxSection = _listbox.useListBoxSection; +-exports.useOption = _listbox.useOption; +-var _menu = require("@react-aria/menu"); +-exports.useMenu = _menu.useMenu; +-exports.useMenuItem = _menu.useMenuItem; +-exports.useMenuSection = _menu.useMenuSection; +-exports.useMenuTrigger = _menu.useMenuTrigger; +-exports.useSubmenuTrigger = _menu.useSubmenuTrigger; +-var _meter = require("@react-aria/meter"); +-exports.useMeter = _meter.useMeter; +-var _numberfield = require("@react-aria/numberfield"); +-exports.useNumberField = _numberfield.useNumberField; +-var _overlays = require("@react-aria/overlays"); +-exports.DismissButton = _overlays.DismissButton; +-exports.ModalProvider = _overlays.ModalProvider; +-exports.Overlay = _overlays.Overlay; +-exports.OverlayContainer = _overlays.OverlayContainer; +-exports.OverlayProvider = _overlays.OverlayProvider; +-exports.useModal = _overlays.useModal; +-exports.useModalOverlay = _overlays.useModalOverlay; +-exports.useModalProvider = _overlays.useModalProvider; +-exports.useOverlay = _overlays.useOverlay; +-exports.useOverlayPosition = _overlays.useOverlayPosition; +-exports.useOverlayTrigger = _overlays.useOverlayTrigger; +-exports.usePopover = _overlays.usePopover; +-exports.usePreventScroll = _overlays.usePreventScroll; +-var _progress = require("@react-aria/progress"); +-exports.useProgressBar = _progress.useProgressBar; +-var _radio = require("@react-aria/radio"); +-exports.useRadio = _radio.useRadio; +-exports.useRadioGroup = _radio.useRadioGroup; +-var _searchfield = require("@react-aria/searchfield"); +-exports.useSearchField = _searchfield.useSearchField; +-var _select = require("@react-aria/select"); +-exports.HiddenSelect = _select.HiddenSelect; +-exports.useHiddenSelect = _select.useHiddenSelect; +-exports.useSelect = _select.useSelect; +-var _selection = require("@react-aria/selection"); +-exports.ListKeyboardDelegate = _selection.ListKeyboardDelegate; +-var _separator = require("@react-aria/separator"); +-exports.useSeparator = _separator.useSeparator; +-var _ssr = require("@react-aria/ssr"); +-exports.SSRProvider = _ssr.SSRProvider; +-exports.useIsSSR = _ssr.useIsSSR; +-var _slider = require("@react-aria/slider"); +-exports.useSlider = _slider.useSlider; +-exports.useSliderThumb = _slider.useSliderThumb; +-var _switch = require("@react-aria/switch"); +-exports.useSwitch = _switch.useSwitch; +-var _table = require("@react-aria/table"); +-exports.useTable = _table.useTable; +-exports.useTableCell = _table.useTableCell; +-exports.useTableColumnHeader = _table.useTableColumnHeader; +-exports.useTableColumnResize = _table.useTableColumnResize; +-exports.useTableHeaderRow = _table.useTableHeaderRow; +-exports.useTableRow = _table.useTableRow; +-exports.useTableRowGroup = _table.useTableRowGroup; +-exports.useTableSelectAllCheckbox = _table.useTableSelectAllCheckbox; +-exports.useTableSelectionCheckbox = _table.useTableSelectionCheckbox; +-var _tabs = require("@react-aria/tabs"); +-exports.useTab = _tabs.useTab; +-exports.useTabList = _tabs.useTabList; +-exports.useTabPanel = _tabs.useTabPanel; +-var _tag = require("@react-aria/tag"); +-exports.useTag = _tag.useTag; +-exports.useTagGroup = _tag.useTagGroup; +-var _textfield = require("@react-aria/textfield"); +-exports.useTextField = _textfield.useTextField; +-var _tooltip = require("@react-aria/tooltip"); +-exports.useTooltip = _tooltip.useTooltip; +-exports.useTooltipTrigger = _tooltip.useTooltipTrigger; +-var _utils = require("@react-aria/utils"); +-exports.chain = _utils.chain; +-exports.mergeProps = _utils.mergeProps; +-exports.useId = _utils.useId; +-exports.useObjectRef = _utils.useObjectRef; +-exports.RouterProvider = _utils.RouterProvider; +-var _visuallyHidden = require("@react-aria/visually-hidden"); +-exports.VisuallyHidden = _visuallyHidden.VisuallyHidden; +-exports.useVisuallyHidden = _visuallyHidden.useVisuallyHidden; ++var _button = require("@react-aria/button"); exports.useButton = _button.useButton; ++var _focus = require("@react-aria/focus"); exports.FocusRing = _focus.FocusRing; exports.FocusScope = _focus.FocusScope; exports.useFocusManager = _focus.useFocusManager; exports.useFocusRing = _focus.useFocusRing; exports.useFocusable = _focus.useFocusable; ++var _i18n = require("@react-aria/i18n"); exports.useNumberFormatter = _i18n.useNumberFormatter; ++var _interactions = require("@react-aria/interactions"); exports.useFocus = _interactions.useFocus; exports.useFocusVisible = _interactions.useFocusVisible; exports.useFocusWithin = _interactions.useFocusWithin; exports.useHover = _interactions.useHover; exports.useInteractOutside = _interactions.useInteractOutside; exports.useKeyboard = _interactions.useKeyboard; exports.useMove = _interactions.useMove; exports.usePress = _interactions.usePress; exports.useLongPress = _interactions.useLongPress; ++var _listbox = require("@react-aria/listbox"); exports.useListBox = _listbox.useListBox; exports.useListBoxSection = _listbox.useListBoxSection; exports.useOption = _listbox.useOption; ++var _menu = require("@react-aria/menu"); exports.useMenu = _menu.useMenu; exports.useMenuItem = _menu.useMenuItem; exports.useMenuSection = _menu.useMenuSection; exports.useMenuTrigger = _menu.useMenuTrigger; ++var _overlays = require("@react-aria/overlays"); exports.DismissButton = _overlays.DismissButton; exports.Overlay = _overlays.Overlay; exports.useOverlayTrigger = _overlays.useOverlayTrigger; exports.usePopover = _overlays.usePopover; ++var _select = require("@react-aria/select"); exports.HiddenSelect = _select.HiddenSelect; exports.useSelect = _select.useSelect; ++var _separator = require("@react-aria/separator"); exports.useSeparator = _separator.useSeparator; ++var _slider = require("@react-aria/slider"); exports.useSlider = _slider.useSlider; exports.useSliderThumb = _slider.useSliderThumb; ++var _utils = require("@react-aria/utils"); exports.chain = _utils.chain; exports.mergeProps = _utils.mergeProps; exports.useId = _utils.useId; exports.useObjectRef = _utils.useObjectRef; ++var _visuallyHidden = require("@react-aria/visually-hidden"); exports.VisuallyHidden = _visuallyHidden.VisuallyHidden; exports.useVisuallyHidden = _visuallyHidden.useVisuallyHidden; ++var _dialog = require("@react-aria/dialog"); exports.useDialog = _dialog.useDialog; +diff --git a/dist/module.js b/dist/module.js +index a13ba8b37e27230ec01d4c31140127912208666c..97d6aa506f273263c2a99a9bc80731ac2c38eea6 100644 +--- a/dist/module.js ++++ b/dist/module.js +@@ -1,50 +1,14 @@ +-/* +- * Copyright 2020 Adobe. All rights reserved. +- * This file is licensed to you under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. You may obtain a copy +- * of the License at http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software distributed under +- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +- * OF ANY KIND, either express or implied. See the License for the specific language +- * governing permissions and limitations under the License. +- */ +- +-export {useBreadcrumbItem, useBreadcrumbs} from '@react-aria/breadcrumbs'; +-export {useButton, useToggleButton, useToggleButtonGroup, useToggleButtonGroupItem} from '@react-aria/button'; +-export {useCalendar, useCalendarCell, useCalendarGrid, useRangeCalendar} from '@react-aria/calendar'; +-export {useCheckbox, useCheckboxGroup, useCheckboxGroupItem} from '@react-aria/checkbox'; +-export {useColorArea, useColorChannelField, useColorField, useColorSlider, useColorSwatch, useColorWheel} from '@react-aria/color'; +-export {useComboBox} from '@react-aria/combobox'; +-export {useDateField, useDatePicker, useDateRangePicker, useDateSegment, useTimeField} from '@react-aria/datepicker'; +-export {useDialog} from '@react-aria/dialog'; +-export {useDisclosure} from '@react-aria/disclosure'; +-export {useDrag, useDrop, useDraggableCollection, useDroppableCollection, useDroppableItem, useDropIndicator, useDraggableItem, useClipboard, DragPreview, ListDropTargetDelegate, DIRECTORY_DRAG_TYPE, isDirectoryDropItem, isFileDropItem, isTextDropItem} from '@react-aria/dnd'; ++// Slim barrel: only exports actually used ++export {useButton} from '@react-aria/button'; + export {FocusRing, FocusScope, useFocusManager, useFocusRing, useFocusable} from '@react-aria/focus'; +-export {I18nProvider, useCollator, useDateFormatter, useFilter, useLocale, useLocalizedStringFormatter, useMessageFormatter, useNumberFormatter} from '@react-aria/i18n'; ++export {useNumberFormatter} from '@react-aria/i18n'; + export {useFocus, useFocusVisible, useFocusWithin, useHover, useInteractOutside, useKeyboard, useMove, usePress, useLongPress} from '@react-aria/interactions'; +-export {useField, useLabel} from '@react-aria/label'; +-export {useGridList, useGridListItem, useGridListSelectionCheckbox} from '@react-aria/gridlist'; +-export {useLink} from '@react-aria/link'; + export {useListBox, useListBoxSection, useOption} from '@react-aria/listbox'; +-export {useMenu, useMenuItem, useMenuSection, useMenuTrigger, useSubmenuTrigger} from '@react-aria/menu'; +-export {useMeter} from '@react-aria/meter'; +-export {useNumberField} from '@react-aria/numberfield'; +-export {DismissButton, ModalProvider, Overlay, OverlayContainer, OverlayProvider, useModal, useModalOverlay, useModalProvider, useOverlay, useOverlayPosition, useOverlayTrigger, usePopover, usePreventScroll} from '@react-aria/overlays'; +-export {useProgressBar} from '@react-aria/progress'; +-export {useRadio, useRadioGroup} from '@react-aria/radio'; +-export {useSearchField} from '@react-aria/searchfield'; +-export {HiddenSelect, useHiddenSelect, useSelect} from '@react-aria/select'; +-export {ListKeyboardDelegate} from '@react-aria/selection'; ++export {useMenu, useMenuItem, useMenuSection, useMenuTrigger} from '@react-aria/menu'; ++export {DismissButton, Overlay, useOverlayTrigger, usePopover} from '@react-aria/overlays'; ++export {HiddenSelect, useSelect} from '@react-aria/select'; + export {useSeparator} from '@react-aria/separator'; +-export {SSRProvider, useIsSSR} from '@react-aria/ssr'; + export {useSlider, useSliderThumb} from '@react-aria/slider'; +-export {useSwitch} from '@react-aria/switch'; +-export {useTable, useTableCell, useTableColumnHeader, useTableColumnResize, useTableHeaderRow, useTableRow, useTableRowGroup, useTableSelectAllCheckbox, useTableSelectionCheckbox} from '@react-aria/table'; +-export {useTab, useTabList, useTabPanel} from '@react-aria/tabs'; +-export {useTag, useTagGroup} from '@react-aria/tag'; +-export {useTextField} from '@react-aria/textfield'; +-export {useTooltip, useTooltipTrigger} from '@react-aria/tooltip'; +-export {chain, mergeProps, useId, useObjectRef, RouterProvider} from '@react-aria/utils'; ++export {chain, mergeProps, useId, useObjectRef} from '@react-aria/utils'; + export {VisuallyHidden, useVisuallyHidden} from '@react-aria/visually-hidden'; +- ++export {useDialog} from '@react-aria/dialog'; diff --git a/.yarn/patches/react-stately-npm-3.17.0-264cc7a43c.patch b/.yarn/patches/react-stately-npm-3.17.0-264cc7a43c.patch new file mode 100644 index 0000000000000..53c82149f04aa --- /dev/null +++ b/.yarn/patches/react-stately-npm-3.17.0-264cc7a43c.patch @@ -0,0 +1,149 @@ +diff --git a/dist/main.js b/dist/main.js +index 8e3aafa76ccbbc4491666e9593220378c3e79c18..2ed9b74c20b63fb1f9e8552d61343b26540f78d9 100644 +--- a/dist/main.js ++++ b/dist/main.js +@@ -1,98 +1,8 @@ + "use strict"; +- + exports.__esModule = true; +-exports.useTreeState = exports.useTooltipTriggerState = exports.useToggleState = exports.useTabListState = exports.Cell = exports.Row = exports.Column = exports.TableBody = exports.TableHeader = exports.useTableState = exports.useMultipleSelectionState = exports.useSliderState = exports.useSelectState = exports.useSearchFieldState = exports.useRadioGroupState = exports.useOverlayTriggerState = exports.useNumberFieldState = exports.useMenuTriggerState = exports.useSingleSelectListState = exports.useListState = exports.useTreeData = exports.useListData = exports.useAsyncList = exports.useCollection = exports.Section = exports.Item = exports.useTimeFieldState = exports.useDateRangePickerState = exports.useDatePickerState = exports.useDateFieldState = exports.useComboBoxState = exports.useCheckboxGroupState = exports.useRangeCalendarState = exports.useCalendarState = void 0; +- +-var _calendar = require("@react-stately/calendar"); +- +-exports.useCalendarState = _calendar.useCalendarState; +-exports.useRangeCalendarState = _calendar.useRangeCalendarState; +- +-var _checkbox = require("@react-stately/checkbox"); +- +-exports.useCheckboxGroupState = _checkbox.useCheckboxGroupState; +- +-var _combobox = require("@react-stately/combobox"); +- +-exports.useComboBoxState = _combobox.useComboBoxState; +- +-var _datepicker = require("@react-stately/datepicker"); +- +-exports.useDateFieldState = _datepicker.useDateFieldState; +-exports.useDatePickerState = _datepicker.useDatePickerState; +-exports.useDateRangePickerState = _datepicker.useDateRangePickerState; +-exports.useTimeFieldState = _datepicker.useTimeFieldState; +- +-var _collections = require("@react-stately/collections"); +- +-exports.Item = _collections.Item; +-exports.Section = _collections.Section; +-exports.useCollection = _collections.useCollection; +- +-var _data = require("@react-stately/data"); +- +-exports.useAsyncList = _data.useAsyncList; +-exports.useListData = _data.useListData; +-exports.useTreeData = _data.useTreeData; +- +-var _list = require("@react-stately/list"); +- +-exports.useListState = _list.useListState; +-exports.useSingleSelectListState = _list.useSingleSelectListState; +- +-var _menu = require("@react-stately/menu"); +- +-exports.useMenuTriggerState = _menu.useMenuTriggerState; +- +-var _numberfield = require("@react-stately/numberfield"); +- +-exports.useNumberFieldState = _numberfield.useNumberFieldState; +- +-var _overlays = require("@react-stately/overlays"); +- +-exports.useOverlayTriggerState = _overlays.useOverlayTriggerState; +- +-var _radio = require("@react-stately/radio"); +- +-exports.useRadioGroupState = _radio.useRadioGroupState; +- +-var _searchfield = require("@react-stately/searchfield"); +- +-exports.useSearchFieldState = _searchfield.useSearchFieldState; +- +-var _select = require("@react-stately/select"); +- +-exports.useSelectState = _select.useSelectState; +- +-var _slider = require("@react-stately/slider"); +- +-exports.useSliderState = _slider.useSliderState; +- +-var _selection = require("@react-stately/selection"); +- +-exports.useMultipleSelectionState = _selection.useMultipleSelectionState; +- +-var _table = require("@react-stately/table"); +- +-exports.useTableState = _table.useTableState; +-exports.TableHeader = _table.TableHeader; +-exports.TableBody = _table.TableBody; +-exports.Column = _table.Column; +-exports.Row = _table.Row; +-exports.Cell = _table.Cell; +- +-var _tabs = require("@react-stately/tabs"); +- +-exports.useTabListState = _tabs.useTabListState; +- +-var _toggle = require("@react-stately/toggle"); +- +-exports.useToggleState = _toggle.useToggleState; +- +-var _tooltip = require("@react-stately/tooltip"); +- +-exports.useTooltipTriggerState = _tooltip.useTooltipTriggerState; +- +-var _tree = require("@react-stately/tree"); +- +-exports.useTreeState = _tree.useTreeState; ++var _collections = require("@react-stately/collections"); exports.Item = _collections.Item; exports.Section = _collections.Section; ++var _menu = require("@react-stately/menu"); exports.useMenuTriggerState = _menu.useMenuTriggerState; ++var _overlays = require("@react-stately/overlays"); exports.useOverlayTriggerState = _overlays.useOverlayTriggerState; ++var _select = require("@react-stately/select"); exports.useSelectState = _select.useSelectState; ++var _slider = require("@react-stately/slider"); exports.useSliderState = _slider.useSliderState; ++var _tree = require("@react-stately/tree"); exports.useTreeState = _tree.useTreeState; +diff --git a/dist/module.js b/dist/module.js +index 37bdb24af4a8310cc702b2d9c1effe6aac261424..c098533fc2bbeb6b203d4350c2dcdd6e6663afd3 100644 +--- a/dist/module.js ++++ b/dist/module.js +@@ -1,33 +1,7 @@ +-/* +- * Copyright 2020 Adobe. All rights reserved. +- * This file is licensed to you under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. You may obtain a copy +- * of the License at http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software distributed under +- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +- * OF ANY KIND, either express or implied. See the License for the specific language +- * governing permissions and limitations under the License. +- */ +- +- +-export {useCalendarState, useRangeCalendarState} from '@react-stately/calendar'; +-export {useCheckboxGroupState} from '@react-stately/checkbox'; +-export {useComboBoxState} from '@react-stately/combobox'; +-export {useDateFieldState, useDatePickerState, useDateRangePickerState, useTimeFieldState} from '@react-stately/datepicker'; +-export {Item, Section, useCollection} from '@react-stately/collections'; +-export {useAsyncList, useListData, useTreeData} from '@react-stately/data'; +-export {useListState, useSingleSelectListState} from '@react-stately/list'; ++// Slim barrel: only exports actually used ++export {Item, Section} from '@react-stately/collections'; + export {useMenuTriggerState} from '@react-stately/menu'; +-export {useNumberFieldState} from '@react-stately/numberfield'; + export {useOverlayTriggerState} from '@react-stately/overlays'; +-export {useRadioGroupState} from '@react-stately/radio'; +-export {useSearchFieldState} from '@react-stately/searchfield'; + export {useSelectState} from '@react-stately/select'; + export {useSliderState} from '@react-stately/slider'; +-export {useMultipleSelectionState} from '@react-stately/selection'; +-export {useTableState, TableHeader, TableBody, Column, Row, Cell} from '@react-stately/table'; +-export {useTabListState} from '@react-stately/tabs'; +-export {useToggleState} from '@react-stately/toggle'; +-export {useTooltipTriggerState} from '@react-stately/tooltip'; + export {useTreeState} from '@react-stately/tree'; diff --git a/apps/meteor/client/components/ImageGallery/ImageGallery.tsx b/apps/meteor/client/components/ImageGallery/ImageGallery.tsx index 19f9aa1fb0106..f1220e0dc7892 100644 --- a/apps/meteor/client/components/ImageGallery/ImageGallery.tsx +++ b/apps/meteor/client/components/ImageGallery/ImageGallery.tsx @@ -1,8 +1,8 @@ +import { FocusScope } from '@react-aria/focus'; import type { IUpload } from '@rocket.chat/core-typings'; import { css } from '@rocket.chat/css-in-js'; import { Box, ButtonGroup, IconButton, Palette, PaletteStyleTag, Throbber, spacing } from '@rocket.chat/fuselage'; import { useRef, useState } from 'react'; -import { FocusScope } from 'react-aria'; import { createPortal } from 'react-dom'; import { useTranslation } from 'react-i18next'; import { Navigation, Zoom, Keyboard, A11y } from 'swiper/modules/index.mjs'; diff --git a/apps/meteor/client/components/ResultsLiveRegion.tsx b/apps/meteor/client/components/ResultsLiveRegion.tsx index 2697575b76494..3df599c66a509 100644 --- a/apps/meteor/client/components/ResultsLiveRegion.tsx +++ b/apps/meteor/client/components/ResultsLiveRegion.tsx @@ -1,4 +1,4 @@ -import { VisuallyHidden } from 'react-aria'; +import { VisuallyHidden } from '@react-aria/visually-hidden'; import { useTranslation } from 'react-i18next'; const ResultsLiveRegion = ({ shouldAnnounce, itemCount }: { shouldAnnounce: boolean; itemCount: number }) => { diff --git a/apps/meteor/client/components/UserCard/UserCardDialog.tsx b/apps/meteor/client/components/UserCard/UserCardDialog.tsx index daf138ef3dd60..8fbaee04aa7c0 100644 --- a/apps/meteor/client/components/UserCard/UserCardDialog.tsx +++ b/apps/meteor/client/components/UserCard/UserCardDialog.tsx @@ -1,8 +1,8 @@ +import type { AriaDialogProps } from '@react-aria/dialog'; +import { useDialog } from '@react-aria/dialog'; import { Box } from '@rocket.chat/fuselage'; import type { ComponentProps } from 'react'; import { useRef } from 'react'; -import type { AriaDialogProps } from 'react-aria'; -import { useDialog } from 'react-aria'; type UserCardDialogProps = AriaDialogProps & ComponentProps; diff --git a/apps/meteor/client/navbar/NavBarNavigation.tsx b/apps/meteor/client/navbar/NavBarNavigation.tsx index 836fe7c453877..f9582e5a59043 100644 --- a/apps/meteor/client/navbar/NavBarNavigation.tsx +++ b/apps/meteor/client/navbar/NavBarNavigation.tsx @@ -1,6 +1,6 @@ +import { FocusScope } from '@react-aria/focus'; import { NavBarGroup, NavBarItem, Box } from '@rocket.chat/fuselage'; import { useLayout, useRouter } from '@rocket.chat/ui-contexts'; -import { FocusScope } from 'react-aria'; import { useTranslation } from 'react-i18next'; import NavBarSearch from './NavBarSearch'; diff --git a/apps/meteor/client/navbar/NavBarSearch/NavBarSearch.tsx b/apps/meteor/client/navbar/NavBarSearch/NavBarSearch.tsx index 13cf7882b890c..b23d0c45a7fde 100644 --- a/apps/meteor/client/navbar/NavBarSearch/NavBarSearch.tsx +++ b/apps/meteor/client/navbar/NavBarSearch/NavBarSearch.tsx @@ -1,10 +1,11 @@ +import { useFocusManager } from '@react-aria/focus'; +import { useOverlayTrigger } from '@react-aria/overlays'; +import { useOverlayTriggerState } from '@react-stately/overlays'; import { Box, Icon, IconButton, TextInput } from '@rocket.chat/fuselage'; import { useEffectEvent, useMergedRefs } from '@rocket.chat/fuselage-hooks'; import { useCallback, useEffect, useRef } from 'react'; -import { useFocusManager, useOverlayTrigger } from 'react-aria'; import { FormProvider, useForm } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import { useOverlayTriggerState } from 'react-stately'; import tinykeys from 'tinykeys'; import NavBarSearchListBox from './NavBarSearchListbox'; diff --git a/apps/meteor/client/navbar/NavBarSearch/NavBarSearchListbox.tsx b/apps/meteor/client/navbar/NavBarSearch/NavBarSearchListbox.tsx index 1c00b564f3455..481081a82e14a 100644 --- a/apps/meteor/client/navbar/NavBarSearch/NavBarSearchListbox.tsx +++ b/apps/meteor/client/navbar/NavBarSearch/NavBarSearchListbox.tsx @@ -1,11 +1,11 @@ +import type { OverlayTriggerAria } from '@react-aria/overlays'; +import type { OverlayTriggerState } from '@react-stately/overlays'; import { Box, Tile } from '@rocket.chat/fuselage'; import { useDebouncedValue, useEffectEvent, useOutsideClick } from '@rocket.chat/fuselage-hooks'; import { CustomScrollbars } from '@rocket.chat/ui-client'; import { useRef } from 'react'; -import type { OverlayTriggerAria } from 'react-aria'; import { useFormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import type { OverlayTriggerState } from 'react-stately'; import NavBarSearchNoResults from './NavBarSearchNoResults'; import NavBarSearchRow from './NavBarSearchRow'; diff --git a/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchClick.ts b/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchClick.ts index 887d41bf27294..a80aff09f263c 100644 --- a/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchClick.ts +++ b/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchClick.ts @@ -1,5 +1,5 @@ +import type { OverlayTriggerState } from '@react-stately/overlays'; import { useCallback } from 'react'; -import type { OverlayTriggerState } from 'react-stately'; export const useSearchClick = (state: OverlayTriggerState) => { const handleClick = useCallback(() => { diff --git a/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchFocus.ts b/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchFocus.ts index c4d348e252a0c..a1688d6115cb3 100644 --- a/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchFocus.ts +++ b/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchFocus.ts @@ -1,6 +1,6 @@ +import type { OverlayTriggerState } from '@react-stately/overlays'; import { useLayout } from '@rocket.chat/ui-contexts'; import { useCallback, useEffect } from 'react'; -import type { OverlayTriggerState } from 'react-stately'; export const useSearchFocus = (state: OverlayTriggerState) => { const { navbar } = useLayout(); diff --git a/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchNavigation.ts b/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchNavigation.ts index b1ee47279e68a..66cd078b25e74 100644 --- a/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchNavigation.ts +++ b/apps/meteor/client/navbar/NavBarSearch/hooks/useSearchNavigation.ts @@ -1,7 +1,7 @@ +import { useFocusManager } from '@react-aria/focus'; +import type { OverlayTriggerState } from '@react-stately/overlays'; import type { KeyboardEvent } from 'react'; import { useCallback } from 'react'; -import { useFocusManager } from 'react-aria'; -import type { OverlayTriggerState } from 'react-stately'; export const isOption = (node: Element) => node.getAttribute('role') === 'option'; diff --git a/apps/meteor/client/sidebar/RoomList/useSidebarListNavigation.ts b/apps/meteor/client/sidebar/RoomList/useSidebarListNavigation.ts index 3f6ee5062a26d..156d006c0a15f 100644 --- a/apps/meteor/client/sidebar/RoomList/useSidebarListNavigation.ts +++ b/apps/meteor/client/sidebar/RoomList/useSidebarListNavigation.ts @@ -1,5 +1,5 @@ +import { useFocusManager } from '@react-aria/focus'; import { useCallback } from 'react'; -import { useFocusManager } from 'react-aria'; const isListItem = (node: EventTarget) => (node as HTMLElement).classList.contains('rcx-sidebar-v2-item'); const isCollapseGroup = (node: EventTarget) => (node as HTMLElement).classList.contains('rcx-sidebar-v2-collapse-group__bar'); diff --git a/apps/meteor/client/sidebar/SidebarRegion.tsx b/apps/meteor/client/sidebar/SidebarRegion.tsx index 1541c900d7a5d..98bd455f03cdc 100644 --- a/apps/meteor/client/sidebar/SidebarRegion.tsx +++ b/apps/meteor/client/sidebar/SidebarRegion.tsx @@ -1,8 +1,8 @@ +import { FocusScope } from '@react-aria/focus'; import { css } from '@rocket.chat/css-in-js'; import { Box } from '@rocket.chat/fuselage'; import { useLayout } from '@rocket.chat/ui-contexts'; import { memo } from 'react'; -import { FocusScope } from 'react-aria'; import Sidebar from './Sidebar'; diff --git a/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx b/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx index 2719d0204cbe0..892ff739d04ff 100644 --- a/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx +++ b/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx @@ -1,3 +1,4 @@ +import { VisuallyHidden } from '@react-aria/visually-hidden'; import { css } from '@rocket.chat/css-in-js'; import type { SelectOption } from '@rocket.chat/fuselage'; import { Accordion, AccordionItem, Box, Button, ButtonGroup } from '@rocket.chat/fuselage'; @@ -16,7 +17,6 @@ import { ExternalLink, Page, PageHeader, PageScrollableContentWithShadow, PageFo import { useTranslation, useToastMessageDispatch, useEndpoint, useSetting } from '@rocket.chat/ui-contexts'; import { useMutation } from '@tanstack/react-query'; import { useId, useMemo } from 'react'; -import { VisuallyHidden } from 'react-aria'; import { Controller, useForm } from 'react-hook-form'; import { fontSizes } from './fontSizes'; diff --git a/apps/meteor/client/views/account/profile/AccountProfileForm.tsx b/apps/meteor/client/views/account/profile/AccountProfileForm.tsx index ece7fa71aa819..032bd545ec563 100644 --- a/apps/meteor/client/views/account/profile/AccountProfileForm.tsx +++ b/apps/meteor/client/views/account/profile/AccountProfileForm.tsx @@ -1,3 +1,4 @@ +import { VisuallyHidden } from '@react-aria/visually-hidden'; import type { IUser } from '@rocket.chat/core-typings'; import { css } from '@rocket.chat/css-in-js'; import { Box, Button, Icon } from '@rocket.chat/fuselage'; @@ -15,7 +16,6 @@ import { import { useMutation } from '@tanstack/react-query'; import type { AllHTMLAttributes, ReactElement } from 'react'; import { useCallback } from 'react'; -import { VisuallyHidden } from 'react-aria'; import { Controller, useFormContext } from 'react-hook-form'; import type { AccountProfileFormValues } from './getProfileInitialValues'; diff --git a/apps/meteor/client/views/modal/uikit/ModalBlock.tsx b/apps/meteor/client/views/modal/uikit/ModalBlock.tsx index 2e1171686ffbb..abaaebe20b330 100644 --- a/apps/meteor/client/views/modal/uikit/ModalBlock.tsx +++ b/apps/meteor/client/views/modal/uikit/ModalBlock.tsx @@ -1,3 +1,4 @@ +import { FocusScope } from '@react-aria/focus'; import { Modal, AnimatedVisibility, @@ -15,7 +16,6 @@ import { UiKitComponent, UiKitModal, modalParser } from '@rocket.chat/fuselage-u import type * as UiKit from '@rocket.chat/ui-kit'; import type { FormEvent, FormEventHandler, ReactElement } from 'react'; import { useId, useCallback, useEffect, useMemo, useRef } from 'react'; -import { FocusScope } from 'react-aria'; import { getButtonStyle } from './getButtonStyle'; import { getURL } from '../../../../app/utils/client/getURL'; diff --git a/apps/meteor/client/views/navigation/NavigationRegion.tsx b/apps/meteor/client/views/navigation/NavigationRegion.tsx index b15d9a678ff6e..8ef76a97bd16f 100644 --- a/apps/meteor/client/views/navigation/NavigationRegion.tsx +++ b/apps/meteor/client/views/navigation/NavigationRegion.tsx @@ -1,8 +1,8 @@ +import { FocusScope } from '@react-aria/focus'; import { css } from '@rocket.chat/css-in-js'; import { Box } from '@rocket.chat/fuselage'; import { useLayout, useLayoutSizes } from '@rocket.chat/ui-contexts'; import { memo } from 'react'; -import { FocusScope } from 'react-aria'; import Sidebar from './sidebar'; import SidePanel from './sidepanel'; diff --git a/apps/meteor/client/views/navigation/sidebar/RoomList/useSidebarListNavigation.ts b/apps/meteor/client/views/navigation/sidebar/RoomList/useSidebarListNavigation.ts index ad345bd95a427..9ae261cb6c283 100644 --- a/apps/meteor/client/views/navigation/sidebar/RoomList/useSidebarListNavigation.ts +++ b/apps/meteor/client/views/navigation/sidebar/RoomList/useSidebarListNavigation.ts @@ -1,5 +1,5 @@ +import { useFocusManager } from '@react-aria/focus'; import { useCallback } from 'react'; -import { useFocusManager } from 'react-aria'; const isListItem = (node: EventTarget) => (node as HTMLElement).classList.contains('rcx-sidebar-v2-item') && (node as HTMLElement).parentElement?.role === 'listitem'; diff --git a/apps/meteor/client/views/room/Room.tsx b/apps/meteor/client/views/room/Room.tsx index 6b9af593eaf76..9079eba20033c 100644 --- a/apps/meteor/client/views/room/Room.tsx +++ b/apps/meteor/client/views/room/Room.tsx @@ -1,10 +1,10 @@ +import { FocusScope } from '@react-aria/focus'; import { isInviteSubscription } from '@rocket.chat/core-typings'; import { ContextualbarSkeleton } from '@rocket.chat/ui-client'; import { useSetting, useRoomToolbox, useUserId } from '@rocket.chat/ui-contexts'; import { useMediaCallOpenRoomTracker } from '@rocket.chat/ui-voip'; import type { ReactElement } from 'react'; import { createElement, lazy, memo, Suspense } from 'react'; -import { FocusScope } from 'react-aria'; import { ErrorBoundary } from 'react-error-boundary'; import { useTranslation } from 'react-i18next'; diff --git a/apps/meteor/client/views/room/contextualBar/VideoConference/VideoConfPopups/VideoConfPopup/TimedVideoConfPopup.tsx b/apps/meteor/client/views/room/contextualBar/VideoConference/VideoConfPopups/VideoConfPopup/TimedVideoConfPopup.tsx index 1094bb1821d03..f1bfb28445b8a 100644 --- a/apps/meteor/client/views/room/contextualBar/VideoConference/VideoConfPopups/VideoConfPopup/TimedVideoConfPopup.tsx +++ b/apps/meteor/client/views/room/contextualBar/VideoConference/VideoConfPopups/VideoConfPopup/TimedVideoConfPopup.tsx @@ -1,3 +1,4 @@ +import { useFocusManager } from '@react-aria/focus'; import type { IRoom } from '@rocket.chat/core-typings'; import { useUserRoom } from '@rocket.chat/ui-contexts'; import { @@ -10,7 +11,6 @@ import { } from '@rocket.chat/ui-video-conf'; import type { ReactElement } from 'react'; import { useEffect, useState } from 'react'; -import { useFocusManager } from 'react-aria'; import IncomingPopup from './IncomingPopup'; import OutgoingPopup from './OutgoingPopup'; diff --git a/apps/meteor/client/views/room/contextualBar/VideoConference/VideoConfPopups/VideoConfPopups.tsx b/apps/meteor/client/views/room/contextualBar/VideoConference/VideoConfPopups/VideoConfPopups.tsx index 8840b15cd8728..c54289fac2d5f 100644 --- a/apps/meteor/client/views/room/contextualBar/VideoConference/VideoConfPopups/VideoConfPopups.tsx +++ b/apps/meteor/client/views/room/contextualBar/VideoConference/VideoConfPopups/VideoConfPopups.tsx @@ -1,3 +1,4 @@ +import { FocusScope } from '@react-aria/focus'; import { useCustomSound } from '@rocket.chat/ui-contexts'; import type { VideoConfPopupPayload } from '@rocket.chat/ui-video-conf'; import { @@ -9,7 +10,6 @@ import { } from '@rocket.chat/ui-video-conf'; import type { ReactElement } from 'react'; import { lazy, Suspense, useEffect, useMemo } from 'react'; -import { FocusScope } from 'react-aria'; import VideoConfPopupPortal from '../../../../../portals/VideoConfPopupPortal'; diff --git a/apps/meteor/client/views/room/hooks/useMessageListNavigation.ts b/apps/meteor/client/views/room/hooks/useMessageListNavigation.ts index 6dc77e6f94c94..7c883252bf37a 100644 --- a/apps/meteor/client/views/room/hooks/useMessageListNavigation.ts +++ b/apps/meteor/client/views/room/hooks/useMessageListNavigation.ts @@ -1,7 +1,6 @@ -import { createFocusManager } from '@react-aria/focus'; +import { createFocusManager, useFocusManager } from '@react-aria/focus'; import type { RefCallback } from 'react'; import { useCallback } from 'react'; -import { useFocusManager } from 'react-aria'; const isListItem = (node: EventTarget) => (node as HTMLElement).getAttribute('role') === 'listitem' || (node as HTMLElement).getAttribute('role') === 'link'; diff --git a/apps/meteor/client/views/room/providers/UserCardProvider.tsx b/apps/meteor/client/views/room/providers/UserCardProvider.tsx index 7907fe5f93cdc..0b6df8f3e6f4a 100644 --- a/apps/meteor/client/views/room/providers/UserCardProvider.tsx +++ b/apps/meteor/client/views/room/providers/UserCardProvider.tsx @@ -1,10 +1,10 @@ +import { useOverlayTrigger } from '@react-aria/overlays'; +import { useOverlayTriggerState } from '@react-stately/overlays'; import { Popover } from '@rocket.chat/fuselage'; import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; import { useRoomToolbox, UserCardContext } from '@rocket.chat/ui-contexts'; import type { ComponentProps, ReactNode, UIEvent } from 'react'; import { Suspense, lazy, useCallback, useMemo, useRef, useState } from 'react'; -import { useOverlayTrigger } from 'react-aria'; -import { useOverlayTriggerState } from 'react-stately'; import { useRoom } from '../contexts/RoomContext'; diff --git a/docs/bundle-optimization-react-aria.md b/docs/bundle-optimization-react-aria.md new file mode 100644 index 0000000000000..dd5d63068498a --- /dev/null +++ b/docs/bundle-optimization-react-aria.md @@ -0,0 +1,118 @@ +# Bundle Optimization: barrel import patches (react-aria, react-stately) + +## The Problem + +Meteor's bundler (`standard-minifier-js`) does **not** perform tree-shaking. When any code imports from the `react-aria` barrel package: + +```typescript +import { FocusScope } from 'react-aria'; +``` + +Meteor resolves the barrel's entry point, which re-exports **all 43 sub-packages** (`@react-aria/dnd`, `@react-aria/calendar`, `@react-aria/table`, etc.). Since there is no dead-code elimination, every sub-package ends up in the main JS bundle — even if only `FocusScope` is used. + +The same applies to `react-stately` (20 sub-packages). + +**Measured impact before the fix:** 832 KB of react-aria + react-stately in the main bundle, of which ~700 KB was unused code. + +## The Solution + +Two complementary changes: + +### 1. Yarn patches on the barrel packages + +`yarn patch` replaces the barrel entry points (`dist/main.js`, `dist/module.js`, `dist/import.mjs`) with slim versions that only re-export the sub-packages actually used. + +The patches live in `.yarn/patches/` and are referenced in `package.json` resolutions. They are applied automatically on every `yarn install`. + +**react-aria** — retained sub-packages: +`button`, `focus`, `i18n`, `interactions`, `listbox`, `menu`, `overlays`, `select`, `separator`, `slider`, `utils`, `visually-hidden`, `dialog` + +**react-stately** — retained sub-packages: +`collections`, `menu`, `overlays`, `select`, `slider`, `tree` + +### 2. Direct sub-package imports in source code + +All imports across `apps/meteor` and workspace packages (`gazzodown`, `ui-client`, `ui-contexts`, `ui-voip`) were changed from barrel to direct sub-package imports: + +```typescript +// Before +import { FocusScope } from 'react-aria'; +import { useOverlayTriggerState } from 'react-stately'; + +// After +import { FocusScope } from '@react-aria/focus'; +import { useOverlayTriggerState } from '@react-stately/overlays'; +``` + +This is the correct long-term fix, but alone it was not enough because `@rocket.chat/fuselage` (published npm package) still uses `require("react-aria")` internally via its UMD build. The yarn patch covers that case. + +## Results (react-aria + react-stately) + +| Metric | Before | After | Delta | +|---|---|---|---| +| Main JS (minified) | 3688 KB | 3199 KB | **-489 KB (-13%)** | +| Main JS (gzip) | 939 KB | 841 KB | **-98 KB (-10%)** | + +## What requires attention + +### Adding new react-aria hooks or components + +If you need to use a react-aria hook or component that is **not** in the slim barrel (e.g., `useCalendar`, `useTable`, `useDrag`), you must: + +1. **Import from the sub-package directly** (preferred): + ```typescript + import { useCalendar } from '@react-aria/calendar'; + ``` + +2. **Or update the yarn patch** if the import comes from a dependency you don't control (like `@rocket.chat/fuselage`): + ```bash + yarn patch react-aria@npm:3.37.0 + # Add the missing export to dist/import.mjs, dist/module.js, and dist/main.js + yarn patch-commit -s + ``` + +### Upgrading react-aria / react-stately versions + +When upgrading these packages, the yarn patches must be re-created for the new version: + +1. Remove the old patch references from `package.json` resolutions +2. Delete the old `.yarn/patches/react-aria-*.patch` and `react-stately-*.patch` files +3. Run `yarn install` to get the unpatched version +4. Run `yarn patch react-aria@npm:` and re-apply the slim barrel +5. Run `yarn patch react-stately@npm:` and re-apply the slim barrel +6. Verify no new exports are needed by running the app and checking for runtime errors + +### Upgrading @rocket.chat/fuselage + +When the fuselage package is updated, check if it uses any new react-aria exports. You can verify with: + +```bash +grep -oE 'react_aria_1\.[a-zA-Z]+' node_modules/@rocket.chat/fuselage/dist/fuselage.development.js | sort -u +grep -oE 'react_stately_1\.[a-zA-Z]+' node_modules/@rocket.chat/fuselage/dist/fuselage.development.js | sort -u +``` + +If there are new exports, add them to the yarn patch. + +### The long-term fix + +The react-aria/react-stately yarn patches are a workaround. The proper fix is for `@rocket.chat/fuselage` to import from sub-packages directly instead of the barrel, which eliminates the need for those patches entirely. Once that is done, only the direct sub-package imports in source code are needed. + +## How to analyze the bundle + +Meteor generates a `.stats.json` file alongside each build. To inspect it: + +```bash +# Find the latest stats file +ls -t .meteor/local/build/programs/web.browser/*.stats.json | head -1 + +# Quick summary +python3 -c " +import json +with open('') as f: + data = json.load(f) +print(f'Total: {data[\"totalMinifiedBytes\"]/1024:.0f} KB') +print(f'Gzip: {data[\"totalMinifiedGzipBytes\"]/1024:.0f} KB') +" +``` + +The stats file contains a per-package breakdown in `minifiedBytesByPackage`, with `packages/modules.js` containing a nested tree of every npm module included in the main bundle. diff --git a/package.json b/package.json index 775f478431ea5..160e99f1d3e4a 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,9 @@ "mongodb": "6.10.0", "underscore": "1.13.7", "yoga-layout@npm:^3.2.1": "patch:yoga-layout@npm%3A3.2.1#~/.yarn/patches/yoga-layout-npm-3.2.1-51ec934670.patch", - "@react-pdf/layout@npm:^4.4.2": "patch:@react-pdf/layout@npm%3A4.4.2#~/.yarn/patches/@react-pdf-layout-npm-4.4.2-6c2e3312fa.patch" + "@react-pdf/layout@npm:^4.4.2": "patch:@react-pdf/layout@npm%3A4.4.2#~/.yarn/patches/@react-pdf-layout-npm-4.4.2-6c2e3312fa.patch", + "react-aria@npm:~3.37.0": "patch:react-aria@npm%3A3.37.0#~/.yarn/patches/react-aria-npm-3.37.0-83959bd2fa.patch", + "react-stately@npm:~3.35.0": "patch:react-stately@npm%3A3.17.0#~/.yarn/patches/react-stately-npm-3.17.0-264cc7a43c.patch" }, "dependencies": { "@types/stream-buffers": "^3.0.8", diff --git a/packages/gazzodown/src/MarkupInteractionContext.ts b/packages/gazzodown/src/MarkupInteractionContext.ts index 544693832b5e3..9e8133f1fb673 100644 --- a/packages/gazzodown/src/MarkupInteractionContext.ts +++ b/packages/gazzodown/src/MarkupInteractionContext.ts @@ -1,8 +1,8 @@ +import type { AriaButtonProps } from '@react-aria/button'; import type { MessageMention } from '@rocket.chat/core-typings'; import type * as MessageParser from '@rocket.chat/message-parser'; import type { FormEvent, UIEvent } from 'react'; import { createContext } from 'react'; -import type { AriaButtonProps } from 'react-aria'; export type UserMention = MessageMention; export type ChannelMention = MessageMention; diff --git a/packages/ui-client/src/components/Contextualbar/ContextualbarDialog.tsx b/packages/ui-client/src/components/Contextualbar/ContextualbarDialog.tsx index 1b730f9c0f759..36909e788be3e 100644 --- a/packages/ui-client/src/components/Contextualbar/ContextualbarDialog.tsx +++ b/packages/ui-client/src/components/Contextualbar/ContextualbarDialog.tsx @@ -1,8 +1,9 @@ +import type { AriaDialogProps } from '@react-aria/dialog'; +import { useDialog } from '@react-aria/dialog'; +import { FocusScope } from '@react-aria/focus'; import { useLayoutSizes, useLayoutContextualBarPosition, useRoomToolbox } from '@rocket.chat/ui-contexts'; import type { ComponentProps } from 'react'; import { useCallback, useRef } from 'react'; -import type { AriaDialogProps } from 'react-aria'; -import { FocusScope, useDialog } from 'react-aria'; import Contextualbar from './Contextualbar'; import ContextualbarResizable from './ContextualbarResizable'; diff --git a/packages/ui-client/src/components/Modal/ModalRegion.tsx b/packages/ui-client/src/components/Modal/ModalRegion.tsx index 3cafd84ca0157..1619e57cfaee7 100644 --- a/packages/ui-client/src/components/Modal/ModalRegion.tsx +++ b/packages/ui-client/src/components/Modal/ModalRegion.tsx @@ -5,7 +5,7 @@ import { lazy, Suspense } from 'react'; import ModalBackdrop from './ModalBackdrop'; import ModalPortal from './ModalPortal'; -const FocusScope = lazy(() => import('react-aria').then((module) => ({ default: module.FocusScope }))); +const FocusScope = lazy(() => import('@react-aria/focus').then((module) => ({ default: module.FocusScope }))); const ModalRegion = () => { const currentModal = useCurrentModal(); diff --git a/packages/ui-contexts/src/UserCardContext.ts b/packages/ui-contexts/src/UserCardContext.ts index f93ceb66fa41d..c2c39c6ff106e 100644 --- a/packages/ui-contexts/src/UserCardContext.ts +++ b/packages/ui-contexts/src/UserCardContext.ts @@ -1,7 +1,7 @@ +import type { AriaButtonProps } from '@react-aria/button'; +import type { OverlayTriggerState } from '@react-stately/overlays'; import type { MutableRefObject, UIEvent } from 'react'; import { createContext } from 'react'; -import type { AriaButtonProps } from 'react-aria'; -import type { OverlayTriggerState } from 'react-stately'; export type UserCardContextValue = { openUserCard: (e: UIEvent, username: string) => void; diff --git a/packages/ui-voip/src/components/Keypad/Key.tsx b/packages/ui-voip/src/components/Keypad/Key.tsx index e35b6f6a732e4..3fec795bc4339 100644 --- a/packages/ui-voip/src/components/Keypad/Key.tsx +++ b/packages/ui-voip/src/components/Keypad/Key.tsx @@ -1,6 +1,7 @@ +import { useLongPress, usePress } from '@react-aria/interactions'; +import { mergeProps } from '@react-aria/utils'; import { css } from '@rocket.chat/css-in-js'; import { Box, Button } from '@rocket.chat/fuselage'; -import { mergeProps, useLongPress, usePress } from 'react-aria'; import { useTranslation } from 'react-i18next'; type KeyProps = { diff --git a/packages/ui-voip/src/components/Keypad/Keypad.tsx b/packages/ui-voip/src/components/Keypad/Keypad.tsx index 86e8a5e7c6ae9..072b101ba30db 100644 --- a/packages/ui-voip/src/components/Keypad/Keypad.tsx +++ b/packages/ui-voip/src/components/Keypad/Keypad.tsx @@ -1,5 +1,5 @@ +import { FocusScope } from '@react-aria/focus'; import { Box } from '@rocket.chat/fuselage'; -import { FocusScope } from 'react-aria'; import Key from './Key'; diff --git a/packages/ui-voip/src/components/Widget/Widget.tsx b/packages/ui-voip/src/components/Widget/Widget.tsx index 9b189300db8e2..d199f0ef0ac81 100644 --- a/packages/ui-voip/src/components/Widget/Widget.tsx +++ b/packages/ui-voip/src/components/Widget/Widget.tsx @@ -1,8 +1,8 @@ +import { FocusScope } from '@react-aria/focus'; import { Palette } from '@rocket.chat/fuselage'; import styled from '@rocket.chat/styled'; import type { ComponentProps, ReactNode } from 'react'; import { useLayoutEffect } from 'react'; -import { FocusScope } from 'react-aria'; import { DragContext } from './WidgetDraggableContext'; import { useDraggable } from '../../hooks'; diff --git a/yarn.lock b/yarn.lock index a46ba00f1d120..abf7cfad19d35 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3378,6 +3378,13 @@ __metadata: languageName: node linkType: hard +"@date-fns/tz@npm:^1.4.1": + version: 1.4.1 + resolution: "@date-fns/tz@npm:1.4.1" + checksum: 10/062097590005cce3da4c7d9880f9c77d386cff5b4dd58fa3dde3c346a8b2e4f4a8025a613306351a7cad8eb71178a0f67b4840d5884f73aa4c759085fac92063 + languageName: node + linkType: hard + "@discoveryjs/json-ext@npm:^0.5.0": version: 0.5.7 resolution: "@discoveryjs/json-ext@npm:0.5.7" @@ -8218,7 +8225,7 @@ __metadata: languageName: node linkType: hard -"@react-stately/data@npm:^3.12.1, @react-stately/data@npm:^3.6.1": +"@react-stately/data@npm:^3.6.1": version: 3.12.1 resolution: "@react-stately/data@npm:3.12.1" dependencies: @@ -9174,7 +9181,7 @@ __metadata: ts-patch: "npm:^3.3.0" typescript: "npm:~5.9.3" typia: "patch:typia@npm%3A9.7.2#~/.yarn/patches/typia-npm-9.7.2-5c5d9c80b4.patch" - zod: "npm:~4.3.6" + zod: "patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch" languageName: unknown linkType: soft @@ -9968,6 +9975,7 @@ __metadata: "@bugsnag/js": "npm:~7.20.2" "@bugsnag/plugin-react": "npm:~7.19.0" "@datastructures-js/priority-queue": "npm:^6.3.5" + "@date-fns/tz": "npm:^1.4.1" "@faker-js/faker": "npm:~8.0.2" "@google-cloud/storage": "npm:^7.15.0" "@kaciras/deasync": "npm:^1.1.0" @@ -10338,7 +10346,7 @@ __metadata: xml2js: "npm:~0.6.2" yaqrcode: "npm:^0.2.1" yoga-layout: "patch:yoga-layout@npm%3A3.2.1#~/.yarn/patches/yoga-layout-npm-3.2.1-51ec934670.patch" - zod: "npm:~4.3.6" + zod: "patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch" zustand: "npm:~5.0.10" languageName: unknown linkType: soft @@ -10949,7 +10957,6 @@ __metadata: "@types/jest": "npm:~30.0.0" eslint: "npm:~9.39.3" jest: "npm:~30.2.0" - moment-timezone: "npm:^0.5.48" typescript: "npm:~5.9.3" languageName: unknown linkType: soft @@ -11309,7 +11316,6 @@ __metadata: codemirror: "npm:^6.0.2" eslint: "npm:~9.39.3" eslint4b-prebuilt: "npm:^6.7.2" - moment: "npm:^2.30.1" prettier: "npm:~3.3.3" rc-scrollbars: "npm:^1.1.6" react: "npm:~18.3.1" @@ -32348,7 +32354,7 @@ __metadata: languageName: node linkType: hard -"react-aria@npm:~3.37.0": +"react-aria@npm:3.37.0": version: 3.37.0 resolution: "react-aria@npm:3.37.0" dependencies: @@ -32398,6 +32404,56 @@ __metadata: languageName: node linkType: hard +"react-aria@patch:react-aria@npm%3A3.37.0#~/.yarn/patches/react-aria-npm-3.37.0-83959bd2fa.patch": + version: 3.37.0 + resolution: "react-aria@patch:react-aria@npm%3A3.37.0#~/.yarn/patches/react-aria-npm-3.37.0-83959bd2fa.patch::version=3.37.0&hash=e69ffb" + dependencies: + "@internationalized/string": "npm:^3.2.5" + "@react-aria/breadcrumbs": "npm:^3.5.20" + "@react-aria/button": "npm:^3.11.1" + "@react-aria/calendar": "npm:^3.7.0" + "@react-aria/checkbox": "npm:^3.15.1" + "@react-aria/color": "npm:^3.0.3" + "@react-aria/combobox": "npm:^3.11.1" + "@react-aria/datepicker": "npm:^3.13.0" + "@react-aria/dialog": "npm:^3.5.21" + "@react-aria/disclosure": "npm:^3.0.1" + "@react-aria/dnd": "npm:^3.8.1" + "@react-aria/focus": "npm:^3.19.1" + "@react-aria/gridlist": "npm:^3.10.1" + "@react-aria/i18n": "npm:^3.12.5" + "@react-aria/interactions": "npm:^3.23.0" + "@react-aria/label": "npm:^3.7.14" + "@react-aria/link": "npm:^3.7.8" + "@react-aria/listbox": "npm:^3.14.0" + "@react-aria/menu": "npm:^3.17.0" + "@react-aria/meter": "npm:^3.4.19" + "@react-aria/numberfield": "npm:^3.11.10" + "@react-aria/overlays": "npm:^3.25.0" + "@react-aria/progress": "npm:^3.4.19" + "@react-aria/radio": "npm:^3.10.11" + "@react-aria/searchfield": "npm:^3.8.0" + "@react-aria/select": "npm:^3.15.1" + "@react-aria/selection": "npm:^3.22.0" + "@react-aria/separator": "npm:^3.4.5" + "@react-aria/slider": "npm:^3.7.15" + "@react-aria/ssr": "npm:^3.9.7" + "@react-aria/switch": "npm:^3.6.11" + "@react-aria/table": "npm:^3.16.1" + "@react-aria/tabs": "npm:^3.9.9" + "@react-aria/tag": "npm:^3.4.9" + "@react-aria/textfield": "npm:^3.16.0" + "@react-aria/tooltip": "npm:^3.7.11" + "@react-aria/utils": "npm:^3.27.0" + "@react-aria/visually-hidden": "npm:^3.8.19" + "@react-types/shared": "npm:^3.27.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/cd2092e40b2f8f74cdd4c9d090755075559174d3a1fcbdab0ffb68ddaeb2a7f57c257e75c308314f1bb2ca143439eec6ecf1ec33b37d7abd25e673d465c1e411 + languageName: node + linkType: hard + "react-beautiful-dnd@npm:^13.1.1": version: 13.1.1 resolution: "react-beautiful-dnd@npm:13.1.1" @@ -32658,7 +32714,7 @@ __metadata: languageName: node linkType: hard -"react-stately@npm:~3.17.0": +"react-stately@npm:3.17.0, react-stately@npm:~3.17.0": version: 3.17.0 resolution: "react-stately@npm:3.17.0" dependencies: @@ -32689,38 +32745,34 @@ __metadata: languageName: node linkType: hard -"react-stately@npm:~3.35.0": - version: 3.35.0 - resolution: "react-stately@npm:3.35.0" +"react-stately@patch:react-stately@npm%3A3.17.0#~/.yarn/patches/react-stately-npm-3.17.0-264cc7a43c.patch": + version: 3.17.0 + resolution: "react-stately@patch:react-stately@npm%3A3.17.0#~/.yarn/patches/react-stately-npm-3.17.0-264cc7a43c.patch::version=3.17.0&hash=e13f63" dependencies: - "@react-stately/calendar": "npm:^3.7.0" - "@react-stately/checkbox": "npm:^3.6.11" - "@react-stately/collections": "npm:^3.12.1" - "@react-stately/color": "npm:^3.8.2" - "@react-stately/combobox": "npm:^3.10.2" - "@react-stately/data": "npm:^3.12.1" - "@react-stately/datepicker": "npm:^3.12.0" - "@react-stately/disclosure": "npm:^3.0.1" - "@react-stately/dnd": "npm:^3.5.1" - "@react-stately/form": "npm:^3.1.1" - "@react-stately/list": "npm:^3.11.2" - "@react-stately/menu": "npm:^3.9.1" - "@react-stately/numberfield": "npm:^3.9.9" - "@react-stately/overlays": "npm:^3.6.13" - "@react-stately/radio": "npm:^3.10.10" - "@react-stately/searchfield": "npm:^3.5.9" - "@react-stately/select": "npm:^3.6.10" - "@react-stately/selection": "npm:^3.19.0" - "@react-stately/slider": "npm:^3.6.1" - "@react-stately/table": "npm:^3.13.1" - "@react-stately/tabs": "npm:^3.7.1" - "@react-stately/toggle": "npm:^3.8.1" - "@react-stately/tooltip": "npm:^3.5.1" - "@react-stately/tree": "npm:^3.8.7" - "@react-types/shared": "npm:^3.27.0" + "@react-stately/calendar": "npm:^3.0.2" + "@react-stately/checkbox": "npm:^3.2.1" + "@react-stately/collections": "npm:^3.4.3" + "@react-stately/combobox": "npm:^3.2.1" + "@react-stately/data": "npm:^3.6.1" + "@react-stately/datepicker": "npm:^3.0.2" + "@react-stately/list": "npm:^3.5.3" + "@react-stately/menu": "npm:^3.4.1" + "@react-stately/numberfield": "npm:^3.2.1" + "@react-stately/overlays": "npm:^3.4.1" + "@react-stately/radio": "npm:^3.5.1" + "@react-stately/searchfield": "npm:^3.3.1" + "@react-stately/select": "npm:^3.3.1" + "@react-stately/selection": "npm:^3.10.3" + "@react-stately/slider": "npm:^3.2.1" + "@react-stately/table": "npm:^3.4.0" + "@react-stately/tabs": "npm:^3.2.1" + "@react-stately/toggle": "npm:^3.4.1" + "@react-stately/tooltip": "npm:^3.2.1" + "@react-stately/tree": "npm:^3.3.3" + "@react-types/shared": "npm:^3.14.1" peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/5977fab93e55d110dc3d009137b97ac9281c2539239958be7743466c16d10da4c7d2a98c65295621be411bbc5f3941fdd15ac3546363d01829ecc430bf3d2604 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + checksum: 10/0c34b5ca78d7a6407518a78f6b526d261661ab47ca204aea867d4e84e5e3f501316b3b234c7a2ad91e98f193d1df2babf92ec5bfca3ef8f2a18a627f0708631d languageName: node linkType: hard @@ -38669,13 +38721,20 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.25.0 || ^4.0.0, zod@npm:~4.3.6": +"zod@npm:4.3.6": version: 4.3.6 resolution: "zod@npm:4.3.6" checksum: 10/25fc0f62e01b557b4644bf0b393bbaf47542ab30877c37837ea8caf314a8713d220c7d7fe51f68ffa72f0e1018ddfa34d96f1973d23033f5a2a5a9b6b9d9da01 languageName: node linkType: hard +"zod@patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch": + version: 4.3.6 + resolution: "zod@patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch::version=4.3.6&hash=5b64de" + checksum: 10/7e9f9e3bef6a7aa9c859841837824b1bc95063c77afbe6dbb4bdb247b70c84aef505ddfc77a693e3dabe2e9182d2ccb497df6bd3f5b045a705e189c906dc8dfc + languageName: node + linkType: hard + "zustand@npm:^4.4.1": version: 4.5.5 resolution: "zustand@npm:4.5.5" From fee390264ad55f7944c35ac041aca47de9224077 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 10 Apr 2026 13:05:37 -0300 Subject: [PATCH 49/51] perf: patch zod barrel to remove unused locales (-144 KB) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add yarn patch for zod that removes `export * as locales` from all barrel entry points (classic, core, mini — ESM and CJS) - Only English locale is used; other 49 locale files were dead weight in the bundle --- .yarn/patches/zod-npm-4.3.6-a096e305e6.patch | 105 +++++++++++++++++++ docs/bundle-optimization-react-aria.md | 58 +++++++++- package.json | 4 +- 3 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 .yarn/patches/zod-npm-4.3.6-a096e305e6.patch diff --git a/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch b/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch new file mode 100644 index 0000000000000..f409b5b624039 --- /dev/null +++ b/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch @@ -0,0 +1,105 @@ +diff --git a/v4/classic/external.cjs b/v4/classic/external.cjs +index ee133825d44ab44b86dd8aef6bd985653ebde06c..ea74468d20c2371f9c4d8941467e3b7fe93a00ef 100644 +--- a/v4/classic/external.cjs ++++ b/v4/classic/external.cjs +@@ -29,7 +29,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + Object.defineProperty(exports, "__esModule", { value: true }); +-exports.coerce = exports.iso = exports.ZodISODuration = exports.ZodISOTime = exports.ZodISODate = exports.ZodISODateTime = exports.locales = exports.fromJSONSchema = exports.toJSONSchema = exports.NEVER = exports.util = exports.TimePrecision = exports.flattenError = exports.formatError = exports.prettifyError = exports.treeifyError = exports.regexes = exports.clone = exports.$brand = exports.$input = exports.$output = exports.config = exports.registry = exports.globalRegistry = exports.core = void 0; ++exports.coerce = exports.iso = exports.ZodISODuration = exports.ZodISOTime = exports.ZodISODate = exports.ZodISODateTime = exports.fromJSONSchema = exports.toJSONSchema = exports.NEVER = exports.util = exports.TimePrecision = exports.flattenError = exports.formatError = exports.prettifyError = exports.treeifyError = exports.regexes = exports.clone = exports.$brand = exports.$input = exports.$output = exports.config = exports.registry = exports.globalRegistry = exports.core = void 0; + exports.core = __importStar(require("../core/index.cjs")); + __exportStar(require("./schemas.cjs"), exports); + __exportStar(require("./checks.cjs"), exports); +@@ -60,7 +60,7 @@ var json_schema_processors_js_1 = require("../core/json-schema-processors.cjs"); + Object.defineProperty(exports, "toJSONSchema", { enumerable: true, get: function () { return json_schema_processors_js_1.toJSONSchema; } }); + var from_json_schema_js_1 = require("./from-json-schema.cjs"); + Object.defineProperty(exports, "fromJSONSchema", { enumerable: true, get: function () { return from_json_schema_js_1.fromJSONSchema; } }); +-exports.locales = __importStar(require("../locales/index.cjs")); ++// locales removed from barrel + // iso + // must be exported from top-level + // https://github.com/colinhacks/zod/issues/4491 +diff --git a/v4/classic/external.js b/v4/classic/external.js +index 9567900bbb57099481c0ea5864fbf697d62021a5..98ee2af29038deca6c38c46c24d5fb14725e40f0 100644 +--- a/v4/classic/external.js ++++ b/v4/classic/external.js +@@ -11,7 +11,7 @@ config(en()); + export { globalRegistry, registry, config, $output, $input, $brand, clone, regexes, treeifyError, prettifyError, formatError, flattenError, TimePrecision, util, NEVER, } from "../core/index.js"; + export { toJSONSchema } from "../core/json-schema-processors.js"; + export { fromJSONSchema } from "./from-json-schema.js"; +-export * as locales from "../locales/index.js"; ++// locales removed from barrel + // iso + // must be exported from top-level + // https://github.com/colinhacks/zod/issues/4491 +diff --git a/v4/core/index.cjs b/v4/core/index.cjs +index c3fa303104a191d142a5212f69e7954cba3606a7..44bdc3437c6a88971c1c85b63024213880fe0fff 100644 +--- a/v4/core/index.cjs ++++ b/v4/core/index.cjs +@@ -26,7 +26,7 @@ var __importStar = (this && this.__importStar) || function (mod) { + return result; + }; + Object.defineProperty(exports, "__esModule", { value: true }); +-exports.JSONSchema = exports.JSONSchemaGenerator = exports.toJSONSchema = exports.locales = exports.regexes = exports.util = void 0; ++exports.JSONSchema = exports.JSONSchemaGenerator = exports.toJSONSchema = exports.regexes = exports.util = void 0; + __exportStar(require("./core.cjs"), exports); + __exportStar(require("./parse.cjs"), exports); + __exportStar(require("./errors.cjs"), exports); +@@ -35,7 +35,7 @@ __exportStar(require("./checks.cjs"), exports); + __exportStar(require("./versions.cjs"), exports); + exports.util = __importStar(require("./util.cjs")); + exports.regexes = __importStar(require("./regexes.cjs")); +-exports.locales = __importStar(require("../locales/index.cjs")); ++// locales removed from barrel + __exportStar(require("./registries.cjs"), exports); + __exportStar(require("./doc.cjs"), exports); + __exportStar(require("./api.cjs"), exports); +diff --git a/v4/core/index.js b/v4/core/index.js +index d334515bf004600f2e55ff85e3730f1b2f2ff703..4ff979844ba18d012893064b01889bf70ec245c8 100644 +--- a/v4/core/index.js ++++ b/v4/core/index.js +@@ -6,7 +6,7 @@ export * from "./checks.js"; + export * from "./versions.js"; + export * as util from "./util.js"; + export * as regexes from "./regexes.js"; +-export * as locales from "../locales/index.js"; ++// locales removed from barrel + export * from "./registries.js"; + export * from "./doc.js"; + export * from "./api.js"; +diff --git a/v4/mini/external.cjs b/v4/mini/external.cjs +index 0d0079d94d94010b51abe23042418adbc6077b7f..fd3acb42a12dde65f383eb2c3f46a9108dd8c865 100644 +--- a/v4/mini/external.cjs ++++ b/v4/mini/external.cjs +@@ -26,7 +26,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); +-exports.coerce = exports.ZodMiniISODuration = exports.ZodMiniISOTime = exports.ZodMiniISODate = exports.ZodMiniISODateTime = exports.iso = exports.locales = exports.toJSONSchema = exports.NEVER = exports.util = exports.TimePrecision = exports.flattenError = exports.formatError = exports.prettifyError = exports.treeifyError = exports.regexes = exports.clone = exports.$brand = exports.$input = exports.$output = exports.config = exports.registry = exports.globalRegistry = exports.core = void 0; ++exports.coerce = exports.ZodMiniISODuration = exports.ZodMiniISOTime = exports.ZodMiniISODate = exports.ZodMiniISODateTime = exports.iso = exports.toJSONSchema = exports.NEVER = exports.util = exports.TimePrecision = exports.flattenError = exports.formatError = exports.prettifyError = exports.treeifyError = exports.regexes = exports.clone = exports.$brand = exports.$input = exports.$output = exports.config = exports.registry = exports.globalRegistry = exports.core = void 0; + exports.core = __importStar(require("../core/index.cjs")); + __exportStar(require("./parse.cjs"), exports); + __exportStar(require("./schemas.cjs"), exports); +@@ -49,7 +49,7 @@ Object.defineProperty(exports, "util", { enumerable: true, get: function () { re + Object.defineProperty(exports, "NEVER", { enumerable: true, get: function () { return index_js_1.NEVER; } }); + var json_schema_processors_js_1 = require("../core/json-schema-processors.cjs"); + Object.defineProperty(exports, "toJSONSchema", { enumerable: true, get: function () { return json_schema_processors_js_1.toJSONSchema; } }); +-exports.locales = __importStar(require("../locales/index.cjs")); ++// locales removed from barrel + /** A special constant with type `never` */ + // export const NEVER = {} as never; + // iso +diff --git a/v4/mini/external.js b/v4/mini/external.js +index d6523c153e213be110c21b370164b5eca1cdf744..7a1addf9ce6e331e56c943867bf04cf199745145 100644 +--- a/v4/mini/external.js ++++ b/v4/mini/external.js +@@ -4,7 +4,7 @@ export * from "./schemas.js"; + export * from "./checks.js"; + export { globalRegistry, registry, config, $output, $input, $brand, clone, regexes, treeifyError, prettifyError, formatError, flattenError, TimePrecision, util, NEVER, } from "../core/index.js"; + export { toJSONSchema } from "../core/json-schema-processors.js"; +-export * as locales from "../locales/index.js"; ++// locales removed from barrel + /** A special constant with type `never` */ + // export const NEVER = {} as never; + // iso diff --git a/docs/bundle-optimization-react-aria.md b/docs/bundle-optimization-react-aria.md index dd5d63068498a..dcd04f02ec8a0 100644 --- a/docs/bundle-optimization-react-aria.md +++ b/docs/bundle-optimization-react-aria.md @@ -1,4 +1,4 @@ -# Bundle Optimization: barrel import patches (react-aria, react-stately) +# Bundle Optimization: barrel import patches (react-aria, react-stately, zod) ## The Problem @@ -53,6 +53,60 @@ This is the correct long-term fix, but alone it was not enough because `@rocket. | Main JS (minified) | 3688 KB | 3199 KB | **-489 KB (-13%)** | | Main JS (gzip) | 939 KB | 841 KB | **-98 KB (-10%)** | +--- + +## Zod v4 locale barrel + +### The Problem + +Zod v4 re-exports all 50 locale files from its main entry point: + +```js +// zod/v4/classic/external.js +export * as locales from "../locales/index.js"; +``` + +This means `import { z } from 'zod'` pulls in error messages for Arabic, Hebrew, Thai, Russian, and 46 other languages — even though Rocket.Chat only uses the English locale (loaded by default via `config(en())`). + +**Measured impact:** 147 KB (50 locale files) out of 278 KB total for zod — **53% of the zod bundle was unused locale data**. + +### The Solution + +A `yarn patch` on `zod@4.3.6` removes the `export * as locales` line from the barrel. The English locale (`en.js`) remains loaded since it's imported separately by `config(en())`. All other locales remain available for explicit import if needed: + +```typescript +// Still works: +import pt from 'zod/v4/locales/pt'; +import { config } from 'zod'; +config(pt()); +``` + +### What requires attention + +#### Upgrading zod + +When upgrading zod, the patch must be re-created: + +1. Remove the old patch reference from `package.json` resolutions +2. Delete `.yarn/patches/zod-*.patch` +3. Run `yarn install` +4. Run `yarn patch zod@npm:` +5. Remove the `export * as locales` line from `v4/classic/external.js` +6. Remove the `exports.locales` require from `v4/classic/external.cjs` +7. Run `yarn patch-commit -s ` + +#### If zod locales are needed at runtime + +If a feature requires localized zod error messages (e.g., form validation in the user's language), import the specific locale directly instead of relying on the barrel: + +```typescript +import de from 'zod/v4/locales/de'; +import { config } from 'zod'; +config(de()); +``` + +This loads only the one locale needed (~3 KB) instead of all 50 (~147 KB). + ## What requires attention ### Adding new react-aria hooks or components @@ -97,6 +151,8 @@ If there are new exports, add them to the yarn patch. The react-aria/react-stately yarn patches are a workaround. The proper fix is for `@rocket.chat/fuselage` to import from sub-packages directly instead of the barrel, which eliminates the need for those patches entirely. Once that is done, only the direct sub-package imports in source code are needed. +The zod patch is a workaround for a design choice in zod v4 (`export * as locales` in the main barrel). This may be addressed upstream — track https://github.com/colinhacks/zod for changes to the locale export strategy. + ## How to analyze the bundle Meteor generates a `.stats.json` file alongside each build. To inspect it: diff --git a/package.json b/package.json index 160e99f1d3e4a..36dd27d672a60 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,9 @@ "yoga-layout@npm:^3.2.1": "patch:yoga-layout@npm%3A3.2.1#~/.yarn/patches/yoga-layout-npm-3.2.1-51ec934670.patch", "@react-pdf/layout@npm:^4.4.2": "patch:@react-pdf/layout@npm%3A4.4.2#~/.yarn/patches/@react-pdf-layout-npm-4.4.2-6c2e3312fa.patch", "react-aria@npm:~3.37.0": "patch:react-aria@npm%3A3.37.0#~/.yarn/patches/react-aria-npm-3.37.0-83959bd2fa.patch", - "react-stately@npm:~3.35.0": "patch:react-stately@npm%3A3.17.0#~/.yarn/patches/react-stately-npm-3.17.0-264cc7a43c.patch" + "react-stately@npm:~3.35.0": "patch:react-stately@npm%3A3.17.0#~/.yarn/patches/react-stately-npm-3.17.0-264cc7a43c.patch", + "zod@npm:^3.25.0 || ^4.0.0": "patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch", + "zod@npm:~4.3.6": "patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch" }, "dependencies": { "@types/stream-buffers": "^3.0.8", From 68927b843e5741f979267e5d22ba1af296738f43 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 10 Apr 2026 15:09:09 -0300 Subject: [PATCH 50/51] chore: slim @react-aria/i18n barrel and replace lodash import (-110 KB) (#40110) --- ...eact-aria-i18n-npm-3.12.5-435edff786.patch | 144 ++++++++++++++++++ apps/meteor/client/lib/e2ee/rocketchat.e2e.ts | 4 +- package.json | 4 +- yarn.lock | 25 ++- 4 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 .yarn/patches/@react-aria-i18n-npm-3.12.5-435edff786.patch diff --git a/.yarn/patches/@react-aria-i18n-npm-3.12.5-435edff786.patch b/.yarn/patches/@react-aria-i18n-npm-3.12.5-435edff786.patch new file mode 100644 index 0000000000000..476a2468aaab0 --- /dev/null +++ b/.yarn/patches/@react-aria-i18n-npm-3.12.5-435edff786.patch @@ -0,0 +1,144 @@ +diff --git a/dist/import.mjs b/dist/import.mjs +index 668b87f9fbf77162f4baa4b02fe3586c3a2c0b26..6b6dc85b39196597504df1a287495a24ce3c0831 100644 +--- a/dist/import.mjs ++++ b/dist/import.mjs +@@ -1,31 +1,7 @@ +-import {I18nProvider as $18f2051aff69b9bf$export$a54013f0d02a8f82, useLocale as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7} from "./context.mjs"; +-import {useMessageFormatter as $321bc95feeb923dd$export$ec23bf898b1eed85} from "./useMessageFormatter.mjs"; +-import {useLocalizedStringDictionary as $fca6afa0e843324b$export$87b761675e8eaa10, useLocalizedStringFormatter as $fca6afa0e843324b$export$f12b703ca79dfbb1} from "./useLocalizedStringFormatter.mjs"; +-import {useListFormatter as $33bf17300c498528$export$a2f47a3d2973640} from "./useListFormatter.mjs"; +-import {useDateFormatter as $896ba0a80a8f4d36$export$85fd5fdf27bacc79} from "./useDateFormatter.mjs"; +-import {useNumberFormatter as $a916eb452884faea$export$b7a616150fdb9f44} from "./useNumberFormatter.mjs"; +-import {useCollator as $325a3faab7a68acd$export$a16aca283550c30d} from "./useCollator.mjs"; +-import {useFilter as $bb77f239b46e8c72$export$3274cf84b703fff} from "./useFilter.mjs"; +- +-/* +- * Copyright 2020 Adobe. All rights reserved. +- * This file is licensed to you under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. You may obtain a copy +- * of the License at http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software distributed under +- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +- * OF ANY KIND, either express or implied. See the License for the specific language +- * governing permissions and limitations under the License. +- */ +- +- +- +- +- +- +- +- +- +-export {$18f2051aff69b9bf$export$a54013f0d02a8f82 as I18nProvider, $18f2051aff69b9bf$export$43bb16f9c6d9e3f7 as useLocale, $321bc95feeb923dd$export$ec23bf898b1eed85 as useMessageFormatter, $fca6afa0e843324b$export$f12b703ca79dfbb1 as useLocalizedStringFormatter, $fca6afa0e843324b$export$87b761675e8eaa10 as useLocalizedStringDictionary, $33bf17300c498528$export$a2f47a3d2973640 as useListFormatter, $896ba0a80a8f4d36$export$85fd5fdf27bacc79 as useDateFormatter, $a916eb452884faea$export$b7a616150fdb9f44 as useNumberFormatter, $325a3faab7a68acd$export$a16aca283550c30d as useCollator, $bb77f239b46e8c72$export$3274cf84b703fff as useFilter}; +-//# sourceMappingURL=module.js.map ++import {I18nProvider as $18f2051aff69b9bf$export$a54013f0d02a8f82, useLocale as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7} from "./context.module.js"; ++import {useLocalizedStringDictionary as $fca6afa0e843324b$export$87b761675e8eaa10, useLocalizedStringFormatter as $fca6afa0e843324b$export$f12b703ca79dfbb1} from "./useLocalizedStringFormatter.module.js"; ++import {useNumberFormatter as $a916eb452884faea$export$b7a616150fdb9f44} from "./useNumberFormatter.module.js"; ++import {useCollator as $325a3faab7a68acd$export$a16aca283550c30d} from "./useCollator.module.js"; ++import {useFilter as $bb77f239b46e8c72$export$3274cf84b703fff} from "./useFilter.module.js"; ++// Slim barrel: removed useDateFormatter (@internationalized/date ~40KB) and useMessageFormatter (@formatjs ~62KB) ++export {$18f2051aff69b9bf$export$a54013f0d02a8f82 as I18nProvider, $18f2051aff69b9bf$export$43bb16f9c6d9e3f7 as useLocale, $fca6afa0e843324b$export$f12b703ca79dfbb1 as useLocalizedStringFormatter, $fca6afa0e843324b$export$87b761675e8eaa10 as useLocalizedStringDictionary, $a916eb452884faea$export$b7a616150fdb9f44 as useNumberFormatter, $325a3faab7a68acd$export$a16aca283550c30d as useCollator, $bb77f239b46e8c72$export$3274cf84b703fff as useFilter}; +diff --git a/dist/main.js b/dist/main.js +index 62b1f5e2054df93a1f3e851f191c42441cf33699..820e10e6bf275b396a46e26a8e80f46b59bffb5c 100644 +--- a/dist/main.js ++++ b/dist/main.js +@@ -1,45 +1,13 @@ + var $47fa5ec5ff482271$exports = require("./context.main.js"); +-var $c376aa482226bf60$exports = require("./useMessageFormatter.main.js"); +-var $fc53663969a3d00a$exports = require("./useLocalizedStringFormatter.main.js"); +-var $cb6a3e7d490e97a4$exports = require("./useListFormatter.main.js"); +-var $b80c530ff2e20243$exports = require("./useDateFormatter.main.js"); +-var $fea93c5b7c90d9f4$exports = require("./useNumberFormatter.main.js"); +-var $27a5ce66022270ad$exports = require("./useCollator.main.js"); +-var $832d079b867c7223$exports = require("./useFilter.main.js"); +- +- +-function $parcel$export(e, n, v, s) { +- Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true}); +-} +- +-$parcel$export(module.exports, "I18nProvider", () => $47fa5ec5ff482271$exports.I18nProvider); +-$parcel$export(module.exports, "useLocale", () => $47fa5ec5ff482271$exports.useLocale); +-$parcel$export(module.exports, "useMessageFormatter", () => $c376aa482226bf60$exports.useMessageFormatter); +-$parcel$export(module.exports, "useLocalizedStringFormatter", () => $fc53663969a3d00a$exports.useLocalizedStringFormatter); +-$parcel$export(module.exports, "useLocalizedStringDictionary", () => $fc53663969a3d00a$exports.useLocalizedStringDictionary); +-$parcel$export(module.exports, "useListFormatter", () => $cb6a3e7d490e97a4$exports.useListFormatter); +-$parcel$export(module.exports, "useDateFormatter", () => $b80c530ff2e20243$exports.useDateFormatter); +-$parcel$export(module.exports, "useNumberFormatter", () => $fea93c5b7c90d9f4$exports.useNumberFormatter); +-$parcel$export(module.exports, "useCollator", () => $27a5ce66022270ad$exports.useCollator); +-$parcel$export(module.exports, "useFilter", () => $832d079b867c7223$exports.useFilter); +-/* +- * Copyright 2020 Adobe. All rights reserved. +- * This file is licensed to you under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. You may obtain a copy +- * of the License at http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software distributed under +- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +- * OF ANY KIND, either express or implied. See the License for the specific language +- * governing permissions and limitations under the License. +- */ +- +- +- +- +- +- +- +- +- +-//# sourceMappingURL=main.js.map ++var $fc53663969a3d00a$exports = require("./useLocalizedStringFormatter.main.js"); ++var $8c5e0e4c6ca34e89$exports = require("./useNumberFormatter.main.js"); ++var $22f23e74d8a5e30d$exports = require("./useCollator.main.js"); ++var $7d0e351af20babe4$exports = require("./useFilter.main.js"); ++// Slim barrel: removed useDateFormatter, useMessageFormatter, useListFormatter ++exports.I18nProvider = $47fa5ec5ff482271$exports.I18nProvider; ++exports.useLocale = $47fa5ec5ff482271$exports.useLocale; ++exports.useLocalizedStringFormatter = $fc53663969a3d00a$exports.useLocalizedStringFormatter; ++exports.useLocalizedStringDictionary = $fc53663969a3d00a$exports.useLocalizedStringDictionary; ++exports.useNumberFormatter = $8c5e0e4c6ca34e89$exports.useNumberFormatter; ++exports.useCollator = $22f23e74d8a5e30d$exports.useCollator; ++exports.useFilter = $7d0e351af20babe4$exports.useFilter; +diff --git a/dist/module.js b/dist/module.js +index fb8c9b0ce2c72d49866c95c3fd6e73cd26149775..6b6dc85b39196597504df1a287495a24ce3c0831 100644 +--- a/dist/module.js ++++ b/dist/module.js +@@ -1,31 +1,7 @@ + import {I18nProvider as $18f2051aff69b9bf$export$a54013f0d02a8f82, useLocale as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7} from "./context.module.js"; +-import {useMessageFormatter as $321bc95feeb923dd$export$ec23bf898b1eed85} from "./useMessageFormatter.module.js"; +-import {useLocalizedStringDictionary as $fca6afa0e843324b$export$87b761675e8eaa10, useLocalizedStringFormatter as $fca6afa0e843324b$export$f12b703ca79dfbb1} from "./useLocalizedStringFormatter.module.js"; +-import {useListFormatter as $33bf17300c498528$export$a2f47a3d2973640} from "./useListFormatter.module.js"; +-import {useDateFormatter as $896ba0a80a8f4d36$export$85fd5fdf27bacc79} from "./useDateFormatter.module.js"; ++import {useLocalizedStringDictionary as $fca6afa0e843324b$export$87b761675e8eaa10, useLocalizedStringFormatter as $fca6afa0e843324b$export$f12b703ca79dfbb1} from "./useLocalizedStringFormatter.module.js"; + import {useNumberFormatter as $a916eb452884faea$export$b7a616150fdb9f44} from "./useNumberFormatter.module.js"; + import {useCollator as $325a3faab7a68acd$export$a16aca283550c30d} from "./useCollator.module.js"; + import {useFilter as $bb77f239b46e8c72$export$3274cf84b703fff} from "./useFilter.module.js"; +- +-/* +- * Copyright 2020 Adobe. All rights reserved. +- * This file is licensed to you under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. You may obtain a copy +- * of the License at http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software distributed under +- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +- * OF ANY KIND, either express or implied. See the License for the specific language +- * governing permissions and limitations under the License. +- */ +- +- +- +- +- +- +- +- +- +-export {$18f2051aff69b9bf$export$a54013f0d02a8f82 as I18nProvider, $18f2051aff69b9bf$export$43bb16f9c6d9e3f7 as useLocale, $321bc95feeb923dd$export$ec23bf898b1eed85 as useMessageFormatter, $fca6afa0e843324b$export$f12b703ca79dfbb1 as useLocalizedStringFormatter, $fca6afa0e843324b$export$87b761675e8eaa10 as useLocalizedStringDictionary, $33bf17300c498528$export$a2f47a3d2973640 as useListFormatter, $896ba0a80a8f4d36$export$85fd5fdf27bacc79 as useDateFormatter, $a916eb452884faea$export$b7a616150fdb9f44 as useNumberFormatter, $325a3faab7a68acd$export$a16aca283550c30d as useCollator, $bb77f239b46e8c72$export$3274cf84b703fff as useFilter}; +-//# sourceMappingURL=module.js.map ++// Slim barrel: removed useDateFormatter (@internationalized/date ~40KB) and useMessageFormatter (@formatjs ~62KB) ++export {$18f2051aff69b9bf$export$a54013f0d02a8f82 as I18nProvider, $18f2051aff69b9bf$export$43bb16f9c6d9e3f7 as useLocale, $fca6afa0e843324b$export$f12b703ca79dfbb1 as useLocalizedStringFormatter, $fca6afa0e843324b$export$87b761675e8eaa10 as useLocalizedStringDictionary, $a916eb452884faea$export$b7a616150fdb9f44 as useNumberFormatter, $325a3faab7a68acd$export$a16aca283550c30d as useCollator, $bb77f239b46e8c72$export$3274cf84b703fff as useFilter}; diff --git a/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts b/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts index fa88249550726..c5418ef9967cc 100644 --- a/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts +++ b/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts @@ -7,7 +7,7 @@ import { Emitter } from '@rocket.chat/emitter'; import { isTruthy } from '@rocket.chat/tools'; import { imperativeModal } from '@rocket.chat/ui-client'; import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts'; -import _ from 'lodash'; +import sampleSize from 'lodash/sampleSize'; import { Accounts } from 'meteor/accounts-base'; import type { E2EEState } from './E2EEState'; @@ -793,7 +793,7 @@ class E2E extends Emitter { return []; } - const randomRoomIds = _.sampleSize(roomIds, ROOM_KEY_EXCHANGE_SIZE); + const randomRoomIds = sampleSize(roomIds, ROOM_KEY_EXCHANGE_SIZE); const sampleIds: string[] = []; for await (const roomId of randomRoomIds) { diff --git a/package.json b/package.json index 36dd27d672a60..d8b6652053706 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,9 @@ "react-aria@npm:~3.37.0": "patch:react-aria@npm%3A3.37.0#~/.yarn/patches/react-aria-npm-3.37.0-83959bd2fa.patch", "react-stately@npm:~3.35.0": "patch:react-stately@npm%3A3.17.0#~/.yarn/patches/react-stately-npm-3.17.0-264cc7a43c.patch", "zod@npm:^3.25.0 || ^4.0.0": "patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch", - "zod@npm:~4.3.6": "patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch" + "zod@npm:~4.3.6": "patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch", + "@react-aria/i18n@npm:^3.0.0-nightly-fb28ab3b4-241024": "patch:@react-aria/i18n@npm%3A3.12.5#~/.yarn/patches/@react-aria-i18n-npm-3.12.5-435edff786.patch", + "@react-aria/i18n@npm:^3.12.5": "patch:@react-aria/i18n@npm%3A3.12.5#~/.yarn/patches/@react-aria-i18n-npm-3.12.5-435edff786.patch" }, "dependencies": { "@types/stream-buffers": "^3.0.8", diff --git a/yarn.lock b/yarn.lock index abf7cfad19d35..5aeda2ff0e369 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7181,7 +7181,7 @@ __metadata: languageName: node linkType: hard -"@react-aria/i18n@npm:^3.0.0-nightly-fb28ab3b4-241024, @react-aria/i18n@npm:^3.12.5": +"@react-aria/i18n@npm:3.12.5": version: 3.12.5 resolution: "@react-aria/i18n@npm:3.12.5" dependencies: @@ -7200,6 +7200,25 @@ __metadata: languageName: node linkType: hard +"@react-aria/i18n@patch:@react-aria/i18n@npm%3A3.12.5#~/.yarn/patches/@react-aria-i18n-npm-3.12.5-435edff786.patch": + version: 3.12.5 + resolution: "@react-aria/i18n@patch:@react-aria/i18n@npm%3A3.12.5#~/.yarn/patches/@react-aria-i18n-npm-3.12.5-435edff786.patch::version=3.12.5&hash=6bfd1c" + dependencies: + "@internationalized/date": "npm:^3.7.0" + "@internationalized/message": "npm:^3.1.6" + "@internationalized/number": "npm:^3.6.0" + "@internationalized/string": "npm:^3.2.5" + "@react-aria/ssr": "npm:^3.9.7" + "@react-aria/utils": "npm:^3.27.0" + "@react-types/shared": "npm:^3.27.0" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/84664c647b2b6372536e7896a0c679727f668c2ca4b9b98d8d6be4928ec6c584efddb0e85c7d97a46ddfd97eedbbcfdd760c5b67026a31a2335629bd65a7b2d5 + languageName: node + linkType: hard + "@react-aria/interactions@npm:^3.23.0": version: 3.23.0 resolution: "@react-aria/interactions@npm:3.23.0" @@ -38730,8 +38749,8 @@ __metadata: "zod@patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch": version: 4.3.6 - resolution: "zod@patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch::version=4.3.6&hash=5b64de" - checksum: 10/7e9f9e3bef6a7aa9c859841837824b1bc95063c77afbe6dbb4bdb247b70c84aef505ddfc77a693e3dabe2e9182d2ccb497df6bd3f5b045a705e189c906dc8dfc + resolution: "zod@patch:zod@npm%3A4.3.6#~/.yarn/patches/zod-npm-4.3.6-a096e305e6.patch::version=4.3.6&hash=18f503" + checksum: 10/2b771f17a72ced59fa57b522693a352140eb193d7158ae75092683f568cf19015c53be5ae6b3fa52dad2335deaff0f7beccba677cc1890744d06776d90a4fc7c languageName: node linkType: hard From 9760d84629e966c53836ab4d0d2fa147f2829d64 Mon Sep 17 00:00:00 2001 From: Douglas Fabris Date: Fri, 10 Apr 2026 15:41:37 -0300 Subject: [PATCH 51/51] refactor: Remove unused `description` from attachments render (#40067) --- .../autotranslate/client/lib/autotranslate.ts | 10 -- .../app/autotranslate/server/autotranslate.ts | 2 +- .../autotranslate/server/deeplTranslate.ts | 2 +- .../autotranslate/server/googleTranslate.ts | 2 +- .../app/autotranslate/server/msTranslate.ts | 2 +- .../server/functions/notifications/email.js | 9 +- .../server/lib/sendNotificationsOnMessage.ts | 2 - .../app/lib/server/methods/updateMessage.ts | 9 +- .../app/livechat/server/lib/sendTranscript.ts | 5 +- .../app/slackbridge/server/RocketAdapter.ts | 5 +- apps/meteor/app/ui/client/lib/ChatMessages.ts | 2 +- .../attachments/file/AudioAttachment.tsx | 5 - .../file/GenericFileAttachment.tsx | 5 - .../attachments/file/ImageAttachment.tsx | 5 - .../attachments/file/VideoAttachment.tsx | 5 - .../message/toolbar/useCopyAction.ts | 4 +- .../toolbar/useReportMessageAction.tsx | 4 +- .../client/hooks/useDecryptedMessage.spec.ts | 3 +- .../client/hooks/useDecryptedMessage.ts | 9 +- .../client/lib/normalizeThreadMessage.tsx | 6 +- .../lib/parseMessageTextToAstMarkdown.spec.ts | 111 ++---------------- .../lib/parseMessageTextToAstMarkdown.ts | 19 +-- .../normalizeMessagePreview.spec.ts | 24 +--- .../normalizeMessagePreview.ts | 6 +- .../room/MessageList/hooks/useMessageBody.tsx | 6 +- .../useDownloadExportMutation.ts | 1 - .../useExportMessagesAsPDFMutation.tsx | 1 - .../hooks/useNormalizedThreadTitleHtml.ts | 6 +- .../EmailInbox/EmailInbox_Outgoing.ts | 6 +- .../hooks/BeforeSaveMarkdownParser.ts | 4 - .../hooks/BeforeSaveJumpToMessage.tests.ts | 11 -- .../hooks/BeforeSaveMarkdownParser.tests.ts | 25 ---- .../src/OmnichannelTranscript.ts | 4 +- .../MessageAttachmentBase.ts | 1 - 34 files changed, 38 insertions(+), 283 deletions(-) diff --git a/apps/meteor/app/autotranslate/client/lib/autotranslate.ts b/apps/meteor/app/autotranslate/client/lib/autotranslate.ts index 76b45d04e18fa..c7818db2b161d 100644 --- a/apps/meteor/app/autotranslate/client/lib/autotranslate.ts +++ b/apps/meteor/app/autotranslate/client/lib/autotranslate.ts @@ -70,16 +70,6 @@ export const AutoTranslate = { } } - if (attachment.description && attachment.translations && attachment.translations[language]) { - attachment.translations.original = attachment.description; - - if (autoTranslateShowInverse) { - attachment.description = attachment.translations.original; - } else { - attachment.description = attachment.translations[language]; - } - } - // @ts-expect-error - not sure what to do with this if (attachment.attachments && attachment.attachments.length > 0) { // @ts-expect-error - not sure what to do with this diff --git a/apps/meteor/app/autotranslate/server/autotranslate.ts b/apps/meteor/app/autotranslate/server/autotranslate.ts index 2f91e02463d58..3e04f6d39eb30 100644 --- a/apps/meteor/app/autotranslate/server/autotranslate.ts +++ b/apps/meteor/app/autotranslate/server/autotranslate.ts @@ -320,7 +320,7 @@ export abstract class AutoTranslate { if (message.attachments && message.attachments.length > 0) { setImmediate(async () => { for (const [index, attachment] of message.attachments?.entries() ?? []) { - if (attachment.description || attachment.text) { + if (attachment.text) { // Removes the initial link `[ ](quoterl)` from quote message before translation const translatedText = attachment?.text?.replace(/\[(.*?)\]\(.*?\)/g, '$1') || attachment?.text; const attachmentMessage = { ...attachment, text: translatedText }; diff --git a/apps/meteor/app/autotranslate/server/deeplTranslate.ts b/apps/meteor/app/autotranslate/server/deeplTranslate.ts index d76a7ea2e4901..35f73e1755da6 100644 --- a/apps/meteor/app/autotranslate/server/deeplTranslate.ts +++ b/apps/meteor/app/autotranslate/server/deeplTranslate.ts @@ -196,7 +196,7 @@ class DeeplAutoTranslate extends AutoTranslate { params: { auth_key: this.apiKey, target_lang: language, - text: attachment.description || attachment.text || '', + text: attachment.text || '', }, }); if (!result.ok) { diff --git a/apps/meteor/app/autotranslate/server/googleTranslate.ts b/apps/meteor/app/autotranslate/server/googleTranslate.ts index 9667ae53c967a..53b9bb7c1d5ea 100644 --- a/apps/meteor/app/autotranslate/server/googleTranslate.ts +++ b/apps/meteor/app/autotranslate/server/googleTranslate.ts @@ -195,7 +195,7 @@ class GoogleAutoTranslate extends AutoTranslate { key: this.apiKey, target: language, format: 'text', - q: attachment.description || attachment.text || '', + q: attachment.text || '', }, }); if (!result.ok) { diff --git a/apps/meteor/app/autotranslate/server/msTranslate.ts b/apps/meteor/app/autotranslate/server/msTranslate.ts index ddb345d3c895a..6508734a1c0da 100644 --- a/apps/meteor/app/autotranslate/server/msTranslate.ts +++ b/apps/meteor/app/autotranslate/server/msTranslate.ts @@ -192,7 +192,7 @@ class MsAutoTranslate extends AutoTranslate { return this._translate( [ { - Text: attachment.description || attachment.text || '', + Text: attachment.text || '', }, ], targetLanguages, diff --git a/apps/meteor/app/lib/server/functions/notifications/email.js b/apps/meteor/app/lib/server/functions/notifications/email.js index a27699bc1d111..7bdbd0d6e990a 100644 --- a/apps/meteor/app/lib/server/functions/notifications/email.js +++ b/apps/meteor/app/lib/server/functions/notifications/email.js @@ -77,13 +77,8 @@ export async function getEmailContent({ message, user, room }) { } if (hasFiles) { - const attachments = message.attachments || []; - const fileParts = files.map((file, index) => { - let part = escapeHTML(file.name); - if (attachments[index]?.description) { - part += `

${escapeHTML(attachments[index].description)}`; - } - return part; + const fileParts = files.map((file) => { + return escapeHTML(file.name); }); contentParts.push(fileParts.join('

')); } diff --git a/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts b/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts index 7a089abba0815..498cef1624624 100644 --- a/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts +++ b/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts @@ -195,8 +195,6 @@ export const sendNotification = async ({ const firstAttachment = message.attachments?.length && message.attachments.shift(); if (firstAttachment) { - firstAttachment.description = - typeof firstAttachment.description === 'string' ? emojione.shortnameToUnicode(firstAttachment.description) : undefined; firstAttachment.text = typeof firstAttachment.text === 'string' ? emojione.shortnameToUnicode(firstAttachment.text) : undefined; } diff --git a/apps/meteor/app/lib/server/methods/updateMessage.ts b/apps/meteor/app/lib/server/methods/updateMessage.ts index 45ba42f25f000..833b4403c0eca 100644 --- a/apps/meteor/app/lib/server/methods/updateMessage.ts +++ b/apps/meteor/app/lib/server/methods/updateMessage.ts @@ -34,7 +34,7 @@ export async function executeUpdateMessage( // IF the message has custom fields, always update // Ideally, we'll compare the custom fields to check for change, but since we don't know the shape of // custom fields, as it's user defined, we're gonna update - const msgText = originalMessage?.attachments?.[0]?.description ?? originalMessage.msg; + const msgText = originalMessage.msg; if (msgText === message.msg && !previewUrls && !message.customFields) { return; } @@ -86,13 +86,6 @@ export async function executeUpdateMessage( } await canSendMessageAsync(message.rid, { uid: user._id, username: user.username ?? undefined, ...user }); - // It is possible to have an empty array as the attachments property, so ensure both things exist - if (originalMessage.attachments && originalMessage.attachments.length > 0 && originalMessage.attachments[0].description !== undefined) { - originalMessage.attachments[0].description = message.msg; - message.attachments = originalMessage.attachments; - message.msg = originalMessage.msg; - } - message.u = originalMessage.u; return updateMessage(message, user, originalMessage, previewUrls); diff --git a/apps/meteor/app/livechat/server/lib/sendTranscript.ts b/apps/meteor/app/livechat/server/lib/sendTranscript.ts index 199275f6a516b..f52ac3f516710 100644 --- a/apps/meteor/app/livechat/server/lib/sendTranscript.ts +++ b/apps/meteor/app/livechat/server/lib/sendTranscript.ts @@ -108,7 +108,7 @@ export async function sendTranscript({ const messageType = MessageTypes.getType(message); - let messageContent = messageType?.system + const messageContent = messageType?.system ? DOMPurify.sanitize(` ${messageType.text(i18n.cloneInstance({ interpolation: { escapeValue: false } }).t, message)}}`) : escapeHtml(message.msg); @@ -116,9 +116,6 @@ export async function sendTranscript({ let filesHTML = ''; if (message.attachments && message.attachments?.length > 0) { - messageContent = message.attachments[0].description || ''; - escapeHtml(messageContent); - for await (const attachment of message.attachments) { if (!isFileAttachment(attachment)) { continue; diff --git a/apps/meteor/app/slackbridge/server/RocketAdapter.ts b/apps/meteor/app/slackbridge/server/RocketAdapter.ts index 925bb4ef2dc4d..cdf4cd8085af9 100644 --- a/apps/meteor/app/slackbridge/server/RocketAdapter.ts +++ b/apps/meteor/app/slackbridge/server/RocketAdapter.ts @@ -203,14 +203,11 @@ export default class RocketAdapter { if (rocketMessage.file.name) { let fileName = rocketMessage.file.name; - let text = rocketMessage.msg; + const text = rocketMessage.msg; const attachment = this.getMessageAttachment(rocketMessage); if (attachment) { fileName = Meteor.absoluteUrl(attachment.title_link); - if (!text) { - text = attachment.description; - } } await slack.postMessage(slack.getSlackChannel(rocketMessage.rid), { ...rocketMessage, msg: `${text} ${fileName}` }); diff --git a/apps/meteor/app/ui/client/lib/ChatMessages.ts b/apps/meteor/app/ui/client/lib/ChatMessages.ts index a6febf3fdfef9..70b64201979ba 100644 --- a/apps/meteor/app/ui/client/lib/ChatMessages.ts +++ b/apps/meteor/app/ui/client/lib/ChatMessages.ts @@ -120,7 +120,7 @@ export class ChatMessages implements ChatAPI { }, editMessage: async (message: IMessage, { cursorAtStart = false }: { cursorAtStart?: boolean } = {}) => { this.composer?.uploads.clear(); - const text = (await this.data.getDraft(message._id)) || message.attachments?.[0]?.description || message.msg; + const text = (await this.data.getDraft(message._id)) || message.msg; await this.currentEditingMessage.stop(); diff --git a/apps/meteor/client/components/message/content/attachments/file/AudioAttachment.tsx b/apps/meteor/client/components/message/content/attachments/file/AudioAttachment.tsx index 227874cfb8eaf..9fa94126127e8 100644 --- a/apps/meteor/client/components/message/content/attachments/file/AudioAttachment.tsx +++ b/apps/meteor/client/components/message/content/attachments/file/AudioAttachment.tsx @@ -4,17 +4,13 @@ import { useMediaUrl } from '@rocket.chat/ui-contexts'; import { useMemo } from 'react'; import { useReloadOnError } from './hooks/useReloadOnError'; -import MarkdownText from '../../../../MarkdownText'; import MessageCollapsible from '../../../MessageCollapsible'; -import MessageContentBody from '../../../MessageContentBody'; const AudioAttachment = ({ title, audio_url: url, audio_type: type, audio_size: size, - description, - descriptionMd, title_link: link, title_link_download: hasDownload, collapsed, @@ -25,7 +21,6 @@ const AudioAttachment = ({ return ( <> - {descriptionMd ? : } diff --git a/apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx b/apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx index d2dbd4f888257..2e0fb7107d983 100644 --- a/apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx +++ b/apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx @@ -13,9 +13,7 @@ import { useTranslation } from 'react-i18next'; import { getFileExtension } from '../../../../../../lib/utils/getFileExtension'; import { forAttachmentDownload, registerDownloadForUid } from '../../../../../hooks/useDownloadFromServiceWorker'; -import MarkdownText from '../../../../MarkdownText'; import MessageCollapsible from '../../../MessageCollapsible'; -import MessageContentBody from '../../../MessageContentBody'; import AttachmentSize from '../structure/AttachmentSize'; const openDocumentViewer = window.RocketChatDesktop?.openDocumentViewer; @@ -24,8 +22,6 @@ type GenericFileAttachmentProps = MessageAttachmentBase; const GenericFileAttachment = ({ title, - description, - descriptionMd, title_link: link, title_link_download: hasDownload, size, @@ -72,7 +68,6 @@ const GenericFileAttachment = ({ return ( <> - {descriptionMd ? : } - {descriptionMd ? : } - {descriptionMd ? : } diff --git a/apps/meteor/client/components/message/toolbar/useCopyAction.ts b/apps/meteor/client/components/message/toolbar/useCopyAction.ts index 1a03dac99936d..b8275144abca1 100644 --- a/apps/meteor/client/components/message/toolbar/useCopyAction.ts +++ b/apps/meteor/client/components/message/toolbar/useCopyAction.ts @@ -6,8 +6,8 @@ import type { MessageActionConfig } from '../../../../app/ui-utils/client/lib/Me const getMainMessageText = (message: IMessage): IMessage => { const newMessage = { ...message }; - newMessage.msg = newMessage.msg || newMessage.attachments?.[0]?.description || newMessage.attachments?.[0]?.title || ''; - newMessage.md = newMessage.md || newMessage.attachments?.[0]?.descriptionMd || undefined; + newMessage.msg = newMessage.msg || newMessage.attachments?.[0]?.title || ''; + newMessage.md = newMessage.md || undefined; return { ...newMessage }; }; diff --git a/apps/meteor/client/components/message/toolbar/useReportMessageAction.tsx b/apps/meteor/client/components/message/toolbar/useReportMessageAction.tsx index ba281c5a1f5a2..dbbb962032907 100644 --- a/apps/meteor/client/components/message/toolbar/useReportMessageAction.tsx +++ b/apps/meteor/client/components/message/toolbar/useReportMessageAction.tsx @@ -7,8 +7,8 @@ import ReportMessageModal from '../../../views/room/modals/ReportMessageModal'; const getMainMessageText = (message: IMessage): IMessage => { const newMessage = { ...message }; - newMessage.msg = newMessage.msg || newMessage.attachments?.[0]?.description || newMessage.attachments?.[0]?.title || ''; - newMessage.md = newMessage.md || newMessage.attachments?.[0]?.descriptionMd || undefined; + newMessage.msg = newMessage.msg || newMessage.attachments?.[0]?.title || ''; + newMessage.md = newMessage.md || undefined; return { ...newMessage }; }; diff --git a/apps/meteor/client/hooks/useDecryptedMessage.spec.ts b/apps/meteor/client/hooks/useDecryptedMessage.spec.ts index 5b35e8d6e3352..3103e708910f6 100644 --- a/apps/meteor/client/hooks/useDecryptedMessage.spec.ts +++ b/apps/meteor/client/hooks/useDecryptedMessage.spec.ts @@ -53,7 +53,7 @@ describe('useDecryptedMessage', () => { it('should handle E2EE messages with attachments', async () => { (isE2EEMessage as jest.MockedFunction).mockReturnValue(true); (e2e.decryptMessage as jest.Mock).mockResolvedValue({ - attachments: [{ description: 'Attachment description' }], + attachments: [{ title: 'Attachment title' }], }); const message = { msg: 'Encrypted message with attachment' }; @@ -63,7 +63,6 @@ describe('useDecryptedMessage', () => { expect(result.current).toBe('E2E_message_encrypted_placeholder'); }); - expect(result.current).toBe('Attachment description'); expect(e2e.decryptMessage).toHaveBeenCalledWith(message); }); diff --git a/apps/meteor/client/hooks/useDecryptedMessage.ts b/apps/meteor/client/hooks/useDecryptedMessage.ts index e560aacc5b111..771665dc0b631 100644 --- a/apps/meteor/client/hooks/useDecryptedMessage.ts +++ b/apps/meteor/client/hooks/useDecryptedMessage.ts @@ -18,14 +18,11 @@ export const useDecryptedMessage = (message: IMessage): string => { e2e.decryptMessage(message).then((decryptedMsg) => { if (decryptedMsg.msg) { setDecryptedMessage(decryptedMsg.msg); + return; } - if (decryptedMsg.attachments && decryptedMsg.attachments?.length > 0) { - if (decryptedMsg.attachments[0].description) { - setDecryptedMessage(decryptedMsg.attachments[0].description); - } else { - setDecryptedMessage(t('Message_with_attachment')); - } + if (decryptedMsg.attachments && decryptedMsg.attachments.length > 0) { + setDecryptedMessage(t('Message_with_attachment')); } }); }, [message, t, setDecryptedMessage]); diff --git a/apps/meteor/client/lib/normalizeThreadMessage.tsx b/apps/meteor/client/lib/normalizeThreadMessage.tsx index 1efa853f3679e..7f13803d2f80a 100644 --- a/apps/meteor/client/lib/normalizeThreadMessage.tsx +++ b/apps/meteor/client/lib/normalizeThreadMessage.tsx @@ -25,11 +25,7 @@ export function normalizeThreadMessage({ ...message }: Readonly attachment.title || attachment.description); - - if (attachment?.description) { - return <>{attachment.description}; - } + const attachment = message.attachments.find((attachment) => attachment.title); if (attachment?.title) { return <>{attachment.title}; diff --git a/apps/meteor/client/lib/parseMessageTextToAstMarkdown.spec.ts b/apps/meteor/client/lib/parseMessageTextToAstMarkdown.spec.ts index e48eb15f885cf..0105608949b7f 100644 --- a/apps/meteor/client/lib/parseMessageTextToAstMarkdown.spec.ts +++ b/apps/meteor/client/lib/parseMessageTextToAstMarkdown.spec.ts @@ -178,47 +178,6 @@ describe('parseMessageTextToAstMarkdown', () => { }); it('should return correct attachment translated parsed md when translate is active', () => { - const attachmentTranslatedMessage = { - ...translatedMessage, - attachments: [ - { - description: 'description', - translations: { - en: 'description translated', - }, - }, - ], - }; - const attachmentTranslatedMessageParsed = { - ...translatedMessage, - md: translatedMessageParsed, - attachments: [ - { - description: 'description', - translations: { - en: 'description translated', - }, - md: [ - { - type: 'PARAGRAPH', - value: [ - { - type: 'PLAIN_TEXT', - value: 'description translated', - }, - ], - }, - ], - }, - ], - }; - - expect(parseMessageTextToAstMarkdown(attachmentTranslatedMessage, parseOptions, enabledAutoTranslatedOptions)).toStrictEqual( - attachmentTranslatedMessageParsed, - ); - }); - - it('should return correct attachment quote translated parsed md when translate is active', () => { const attachmentTranslatedMessage = { ...translatedMessage, attachments: [ @@ -378,7 +337,7 @@ describe('parseMessageAttachments', () => { const attachmentMessage = [ { - description: 'message **bold** _italic_ and ~strike~', + text: 'message **bold** _italic_ and ~strike~', md: messageParserTokenMessage, }, ]; @@ -400,46 +359,18 @@ describe('parseMessageAttachments', () => { autoTranslateLanguage: 'en', }; - it('should return correct attachment description translated parsed md when translate is active', () => { - const descriptionAttachment = [ - { - ...attachmentMessage[0], - description: 'attachment not translated', - translationProvider: 'provider', - translations: { - en: 'attachment translated', - }, - }, - ]; - const descriptionAttachmentParsed: Root = [ - { - type: 'PARAGRAPH', - value: [ - { - type: 'PLAIN_TEXT', - value: 'attachment translated', - }, - ], - }, - ]; - - expect(parseMessageAttachments(descriptionAttachment, parseOptions, enabledAutoTranslatedOptions)[0].md).toStrictEqual( - descriptionAttachmentParsed, - ); - }); - - it('should return correct attachment description parsed md when translate is active and auto translate language is undefined', () => { - const descriptionAttachment = [ + it('should return correct attachment text parsed md when translate is active and auto translate language is undefined', () => { + const textAttachment = [ { ...attachmentMessage[0], - description: 'attachment not translated', + text: 'attachment not translated', translationProvider: 'provider', translations: { en: 'attachment translated', }, }, ]; - const descriptionAttachmentParsed: Root = [ + const textAttachmentParsed: Root = [ { type: 'PARAGRAPH', value: [ @@ -452,39 +383,11 @@ describe('parseMessageAttachments', () => { ]; expect( - parseMessageAttachments(descriptionAttachment, parseOptions, { + parseMessageAttachments(textAttachment, parseOptions, { ...enabledAutoTranslatedOptions, autoTranslateLanguage: undefined, })[0].md, - ).toStrictEqual(descriptionAttachmentParsed); - }); - - it('should return correct attachment text translated parsed md when translate is active', () => { - const textAttachment = [ - { - ...attachmentMessage[0], - text: 'attachment not translated', - translationProvider: 'provider', - translations: { - en: 'attachment translated', - }, - }, - ]; - const textAttachmentParsed: Root = [ - { - type: 'PARAGRAPH', - value: [ - { - type: 'PLAIN_TEXT', - value: 'attachment translated', - }, - ], - }, - ]; - - expect(parseMessageAttachments(textAttachment, parseOptions, enabledAutoTranslatedOptions)[0].md).toStrictEqual( - textAttachmentParsed, - ); + ).toStrictEqual(textAttachmentParsed); }); it('should return correct attachment text translated parsed md when translate is active and has multiple texts', () => { diff --git a/apps/meteor/client/lib/parseMessageTextToAstMarkdown.ts b/apps/meteor/client/lib/parseMessageTextToAstMarkdown.ts index df84785e26351..55d393cee38ed 100644 --- a/apps/meteor/client/lib/parseMessageTextToAstMarkdown.ts +++ b/apps/meteor/client/lib/parseMessageTextToAstMarkdown.ts @@ -1,12 +1,5 @@ import type { IMessage, ITranslatedMessage, MessageAttachment } from '@rocket.chat/core-typings'; -import { - isFileAttachment, - isE2EEMessage, - isQuoteAttachment, - isTranslatedAttachment, - isTranslatedMessage, - isEncryptedMessageAttachment, -} from '@rocket.chat/core-typings'; +import { isE2EEMessage, isQuoteAttachment, isTranslatedAttachment, isTranslatedMessage } from '@rocket.chat/core-typings'; import type { Options, Root } from '@rocket.chat/message-parser'; import { parse } from '@rocket.chat/message-parser'; @@ -58,7 +51,7 @@ export const parseMessageAttachment = ( autoTranslateOptions: { autoTranslateLanguage?: string; translated: boolean }, ): T => { const { translated, autoTranslateLanguage } = autoTranslateOptions; - if (!attachment.text && !attachment.description) { + if (!attachment.text) { return attachment; } @@ -69,16 +62,8 @@ export const parseMessageAttachment = ( const text = (isTranslatedAttachment(attachment) && autoTranslateLanguage && attachment?.translations?.[autoTranslateLanguage]) || attachment.text || - attachment.description || ''; - if (isFileAttachment(attachment) && attachment.description) { - attachment.descriptionMd = - translated || isEncryptedMessageAttachment(attachment) - ? textToMessageToken(text, parseOptions) - : (attachment.descriptionMd ?? textToMessageToken(text, parseOptions)); - } - return { ...attachment, md: translated ? textToMessageToken(text, parseOptions) : (attachment.md ?? textToMessageToken(text, parseOptions)), diff --git a/apps/meteor/client/lib/utils/normalizeMessagePreview/normalizeMessagePreview.spec.ts b/apps/meteor/client/lib/utils/normalizeMessagePreview/normalizeMessagePreview.spec.ts index 184145a6c4506..9584c13531439 100644 --- a/apps/meteor/client/lib/utils/normalizeMessagePreview/normalizeMessagePreview.spec.ts +++ b/apps/meteor/client/lib/utils/normalizeMessagePreview/normalizeMessagePreview.spec.ts @@ -48,7 +48,7 @@ describe('normalizeMessagePreview', () => { }); describe('when message has attachments', () => { - it('should return attachment description when available', () => { + it('should return attachment title when description is available', () => { const message = createFakeMessageWithAttachment({ msg: '', attachments: [ @@ -60,10 +60,10 @@ describe('normalizeMessagePreview', () => { }); const result = normalizeMessagePreview(message, mockT); - expect(result).toBe('Attachment description'); + expect(result).toBe('Attachment title'); }); - it('should return attachment title when description is not available', () => { + it('should return attachment title when message is not provided', () => { const message = createFakeMessageWithAttachment({ msg: '', attachments: [ @@ -112,7 +112,7 @@ describe('normalizeMessagePreview', () => { expect(result).toBe('Second attachment title'); }); - it('should find first attachment description', () => { + it('should find first attachment title', () => { const message = createFakeMessageWithAttachment({ msg: '', attachments: [ @@ -129,21 +129,7 @@ describe('normalizeMessagePreview', () => { }); const result = normalizeMessagePreview(message, mockT); - expect(result).toBe('Second attachment description'); - }); - - it('should escape HTML in attachment description', () => { - const message = createFakeMessageWithAttachment({ - msg: '', - attachments: [ - { - description: '', - }, - ], - }); - const result = normalizeMessagePreview(message, mockT); - - expect(result).toBe('<script>alert("xss")</script>'); + expect(result).toBe('Third attachment title'); }); it('should escape HTML in attachment title', () => { diff --git a/apps/meteor/client/lib/utils/normalizeMessagePreview/normalizeMessagePreview.ts b/apps/meteor/client/lib/utils/normalizeMessagePreview/normalizeMessagePreview.ts index 53bf5bf2d4056..0fbefea5fa48d 100644 --- a/apps/meteor/client/lib/utils/normalizeMessagePreview/normalizeMessagePreview.ts +++ b/apps/meteor/client/lib/utils/normalizeMessagePreview/normalizeMessagePreview.ts @@ -11,11 +11,7 @@ export const normalizeMessagePreview = (message: IMessage, t: TFunction): string } if (message.attachments) { - const attachment = message.attachments.find((attachment) => attachment.title || attachment.description); - - if (attachment?.description) { - return escapeHTML(attachment.description); - } + const attachment = message.attachments.find((attachment) => attachment.title); if (attachment?.title) { return escapeHTML(attachment.title); diff --git a/apps/meteor/client/views/room/MessageList/hooks/useMessageBody.tsx b/apps/meteor/client/views/room/MessageList/hooks/useMessageBody.tsx index 0bcbbccece740..94313e6925432 100644 --- a/apps/meteor/client/views/room/MessageList/hooks/useMessageBody.tsx +++ b/apps/meteor/client/views/room/MessageList/hooks/useMessageBody.tsx @@ -31,11 +31,7 @@ export const useMessageBody = (message: IMessage | undefined): string | Root => } if (message.attachments) { - const attachment = message.attachments.find((attachment) => attachment.title || attachment.description); - - if (attachment?.description) { - return attachment.description; - } + const attachment = message.attachments.find((attachment) => attachment.title); if (attachment?.title) { return attachment.title; diff --git a/apps/meteor/client/views/room/contextualBar/ExportMessages/useDownloadExportMutation.ts b/apps/meteor/client/views/room/contextualBar/ExportMessages/useDownloadExportMutation.ts index f7b53352df5a1..291475075f4e4 100644 --- a/apps/meteor/client/views/room/contextualBar/ExportMessages/useDownloadExportMutation.ts +++ b/apps/meteor/client/views/room/contextualBar/ExportMessages/useDownloadExportMutation.ts @@ -39,7 +39,6 @@ export const useDownloadExportMutation = () => { ...('image_type' in attachment && { image_type: attachment.image_type }), ...('image_size' in attachment && { image_size: attachment.image_size }), ...('type' in attachment && { type: attachment.type }), - description: attachment.description, })) ?? [], }), ); diff --git a/apps/meteor/client/views/room/contextualBar/ExportMessages/useExportMessagesAsPDFMutation.tsx b/apps/meteor/client/views/room/contextualBar/ExportMessages/useExportMessagesAsPDFMutation.tsx index 716f7f3c8bd19..383388f0c316f 100644 --- a/apps/meteor/client/views/room/contextualBar/ExportMessages/useExportMessagesAsPDFMutation.tsx +++ b/apps/meteor/client/views/room/contextualBar/ExportMessages/useExportMessagesAsPDFMutation.tsx @@ -116,7 +116,6 @@ export const useExportMessagesAsPDFMutation = () => { {parseMessage(message)} {message.attachments?.map((attachment: MessageAttachmentDefault, index) => ( - {attachment.description && {attachment.description}} {attachment.image_url && } {attachment.title} diff --git a/apps/meteor/client/views/room/contextualBar/Threads/hooks/useNormalizedThreadTitleHtml.ts b/apps/meteor/client/views/room/contextualBar/Threads/hooks/useNormalizedThreadTitleHtml.ts index f391e6ad7bc75..874a95bfa9c01 100644 --- a/apps/meteor/client/views/room/contextualBar/Threads/hooks/useNormalizedThreadTitleHtml.ts +++ b/apps/meteor/client/views/room/contextualBar/Threads/hooks/useNormalizedThreadTitleHtml.ts @@ -33,11 +33,7 @@ export const useNormalizedThreadTitleHtml = (mainMessage: IThreadMainMessage) => } if (message.attachments) { - const attachment = message.attachments.find((attachment) => attachment.title || attachment.description); - - if (attachment?.description) { - return escapeHTML(attachment.description); - } + const attachment = message.attachments.find((attachment) => attachment.title); if (attachment?.title) { return escapeHTML(attachment.title); diff --git a/apps/meteor/server/features/EmailInbox/EmailInbox_Outgoing.ts b/apps/meteor/server/features/EmailInbox/EmailInbox_Outgoing.ts index b2480acff247d..d15ac6dbbc909 100644 --- a/apps/meteor/server/features/EmailInbox/EmailInbox_Outgoing.ts +++ b/apps/meteor/server/features/EmailInbox/EmailInbox_Outgoing.ts @@ -142,11 +142,7 @@ slashCommands.add({ return; } - const emailText = - message?.attachments - ?.map((a) => a.description) - .filter(Boolean) - .join('\n\n') || ''; + const emailText = message?.msg || ''; void sendEmail( inbox, diff --git a/apps/meteor/server/services/messages/hooks/BeforeSaveMarkdownParser.ts b/apps/meteor/server/services/messages/hooks/BeforeSaveMarkdownParser.ts index d311c84a688df..f4e26cdb97ee5 100644 --- a/apps/meteor/server/services/messages/hooks/BeforeSaveMarkdownParser.ts +++ b/apps/meteor/server/services/messages/hooks/BeforeSaveMarkdownParser.ts @@ -30,10 +30,6 @@ export class BeforeSaveMarkdownParser { if (message.msg) { message.md = parse(message.msg, config); } - - if (message.attachments?.[0]?.description) { - message.attachments[0].descriptionMd = parse(message.attachments[0].description, config); - } } catch (e) { console.error(e); // errors logged while the parser is at experimental stage } diff --git a/apps/meteor/tests/unit/server/services/messages/hooks/BeforeSaveJumpToMessage.tests.ts b/apps/meteor/tests/unit/server/services/messages/hooks/BeforeSaveJumpToMessage.tests.ts index 0ce7279e89b39..791404e4f1d9f 100644 --- a/apps/meteor/tests/unit/server/services/messages/hooks/BeforeSaveJumpToMessage.tests.ts +++ b/apps/meteor/tests/unit/server/services/messages/hooks/BeforeSaveJumpToMessage.tests.ts @@ -500,17 +500,6 @@ describe('Create attachments for message URLs', () => { image_size: 68016, type: 'file', description: 'chained 3 - file', - descriptionMd: [ - { - type: 'PARAGRAPH', - value: [ - { - type: 'PLAIN_TEXT', - value: 'chained 3 - file', - }, - ], - }, - ], }, ], }, diff --git a/apps/meteor/tests/unit/server/services/messages/hooks/BeforeSaveMarkdownParser.tests.ts b/apps/meteor/tests/unit/server/services/messages/hooks/BeforeSaveMarkdownParser.tests.ts index b633e085c5645..ae0f3ed284a7a 100644 --- a/apps/meteor/tests/unit/server/services/messages/hooks/BeforeSaveMarkdownParser.tests.ts +++ b/apps/meteor/tests/unit/server/services/messages/hooks/BeforeSaveMarkdownParser.tests.ts @@ -48,29 +48,4 @@ describe('Markdown parser', () => { expect(message).to.have.property('md'); }); - - it('should parse markdown on the first attachment only', async () => { - const markdownParser = new BeforeSaveMarkdownParser(true); - - const message = await markdownParser.parseMarkdown({ - message: createMessage('hey', { - attachments: [ - { - description: 'hey ho', - }, - { - description: 'lets go', - }, - ], - }), - config: {}, - }); - - expect(message).to.have.property('md'); - - const [attachment1, attachment2] = message.attachments || []; - - expect(attachment1).to.have.property('descriptionMd'); - expect(attachment2).to.not.have.property('descriptionMd'); - }); }); diff --git a/ee/packages/omnichannel-services/src/OmnichannelTranscript.ts b/ee/packages/omnichannel-services/src/OmnichannelTranscript.ts index fd9394aad3416..6532b1f505724 100644 --- a/ee/packages/omnichannel-services/src/OmnichannelTranscript.ts +++ b/ee/packages/omnichannel-services/src/OmnichannelTranscript.ts @@ -312,9 +312,7 @@ export class OmnichannelTranscript extends ServiceClass implements IOmnichannelT } } - // When you send a file message, the things you type in the modal are not "msg", they're in "description" of the attachment - // So, we'll fetch the the msg, if empty, go for the first description on an attachment, if empty, empty string - const msg = message.msg || message.attachments.find((attachment) => attachment.description)?.description || ''; + const msg = message.msg || ''; // Remove nulls from final array messagesData.push({ msg, diff --git a/packages/core-typings/src/IMessage/MessageAttachment/MessageAttachmentBase.ts b/packages/core-typings/src/IMessage/MessageAttachment/MessageAttachmentBase.ts index f870f8cfc1ec7..4a151da95217c 100644 --- a/packages/core-typings/src/IMessage/MessageAttachment/MessageAttachmentBase.ts +++ b/packages/core-typings/src/IMessage/MessageAttachment/MessageAttachmentBase.ts @@ -6,7 +6,6 @@ export type MessageAttachmentBase = { ts?: Date; collapsed?: boolean; description?: string; - descriptionMd?: Root; text?: string; md?: Root; size?: number;