From d93cf7640ffce28e08a3f25b929e52480b0e08bb Mon Sep 17 00:00:00 2001 From: Ricardo Garim Date: Sun, 5 Apr 2026 23:22:39 -0300 Subject: [PATCH 1/2] fix: show disabled status when presence broadcast is disabled --- apps/meteor/client/lib/presence.spec.ts | 51 +++++++++++++++++++ apps/meteor/client/lib/presence.ts | 4 +- .../modules/listeners/listeners.module.ts | 4 ++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 apps/meteor/client/lib/presence.spec.ts diff --git a/apps/meteor/client/lib/presence.spec.ts b/apps/meteor/client/lib/presence.spec.ts new file mode 100644 index 0000000000000..5e630bd4f03da --- /dev/null +++ b/apps/meteor/client/lib/presence.spec.ts @@ -0,0 +1,51 @@ +import { UserStatus } from '@rocket.chat/core-typings'; + +import { Presence } from './presence'; + +jest.mock('meteor/meteor', () => ({ + Meteor: { + subscribe: jest.fn(), + }, +})); + +const mockGet = jest.fn(); + +jest.mock('../../app/utils/client/lib/SDKClient', () => ({ + sdk: { + rest: { + get: (...args: unknown[]) => mockGet(...args), + }, + }, +})); + +describe('Presence fallback status', () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.useFakeTimers(); + Presence.store.clear(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it('should use DISABLED as fallback when status is set to disabled', async () => { + mockGet.mockResolvedValue({ users: [] }); + Presence.setStatus('disabled'); + + Presence.listen('user1', jest.fn()); + await jest.advanceTimersByTimeAsync(500); + + expect(Presence.store.get('user1')?.status).toBe(UserStatus.DISABLED); + }); + + it('should use OFFLINE as fallback when status is set to enabled', async () => { + mockGet.mockResolvedValue({ users: [] }); + Presence.setStatus('enabled'); + + Presence.listen('user1', jest.fn()); + await jest.advanceTimersByTimeAsync(500); + + expect(Presence.store.get('user1')?.status).toBe(UserStatus.OFFLINE); + }); +}); diff --git a/apps/meteor/client/lib/presence.ts b/apps/meteor/client/lib/presence.ts index ebd42bc41abd9..16a5282c56921 100644 --- a/apps/meteor/client/lib/presence.ts +++ b/apps/meteor/client/lib/presence.ts @@ -73,6 +73,8 @@ const getPresence = ((): ((uid: UserPresence['_id']) => void) => { const { users } = await sdk.rest.get('/v1/users.presence', params); + const fallbackStatus = status === 'disabled' ? UserStatus.DISABLED : UserStatus.OFFLINE; + users.forEach((user) => { if (!store.has(user._id)) { notify(user); @@ -81,7 +83,7 @@ const getPresence = ((): ((uid: UserPresence['_id']) => void) => { }); currentUids.forEach((uid) => { - notify({ _id: uid, status: UserStatus.OFFLINE }); + notify({ _id: uid, status: fallbackStatus }); }); currentUids.clear(); diff --git a/apps/meteor/server/modules/listeners/listeners.module.ts b/apps/meteor/server/modules/listeners/listeners.module.ts index 1abc7a0329ee0..db9683cadafd9 100644 --- a/apps/meteor/server/modules/listeners/listeners.module.ts +++ b/apps/meteor/server/modules/listeners/listeners.module.ts @@ -162,6 +162,10 @@ export class ListenersModule { return; } + if (settings.get('Presence_broadcast_disabled')) { + return; + } + notifications.notifyUserInThisInstance(_id, 'userData', { type: 'updated', id: _id, From 5fc5e0d3771ced9568885b4c6b9d2f28d67cc4dd Mon Sep 17 00:00:00 2001 From: Ricardo Garim Date: Mon, 6 Apr 2026 13:19:44 -0300 Subject: [PATCH 2/2] chore: add changeset --- .changeset/long-years-flow.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/long-years-flow.md diff --git a/.changeset/long-years-flow.md b/.changeset/long-years-flow.md new file mode 100644 index 0000000000000..21df4d574e44b --- /dev/null +++ b/.changeset/long-years-flow.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes user status indicator to show disabled state when presence broadcast is turned off