From e50bd677d69bd3fb04fa9b6f6c871d19c22331af Mon Sep 17 00:00:00 2001 From: Lotus CI Date: Sun, 11 Oct 2026 22:04:57 -0400 Subject: [PATCH] fix(presence): closing a tab no longer erases your custom status (#339) The pagehide keepalive write sent { presence: 'offline' } with no status_msg, which Synapse treats as clearing it, so closing or reloading any Lotus tab wiped the user's status for everyone (intermittently, as the 10 s presence rate limit sometimes 429'd the write). It now sends the current status along with the offline state. Verified against the local Synapse: with a status set from another device, two reloads and a tab close keep it (server shows offline/"Gone fishing" after the close; before, the first reload wiped it). Fixes #339 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 --- src/app/hooks/usePresenceUpdater.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/hooks/usePresenceUpdater.ts b/src/app/hooks/usePresenceUpdater.ts index da28812f1..74a57644e 100644 --- a/src/app/hooks/usePresenceUpdater.ts +++ b/src/app/hooks/usePresenceUpdater.ts @@ -167,13 +167,17 @@ export function usePresenceUpdater() { // it isn't usable here. fetch(..., { keepalive: true }) lets the request outlive the // page and is the correct mechanism for an authed endpoint. (keepalive bodies are // capped at 64KB, which this tiny payload is well under.) + // [Gitea #339] Synapse treats a missing status_msg as "clear it", so a bare + // { presence: 'offline' } wiped the user's custom status for everyone whenever + // any tab closed or reloaded. Send the current status along with it. + const status = readStatus(); fetch(`${baseUrl}/_matrix/client/v3/presence/${encodeURIComponent(userId)}/status`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }, - body: JSON.stringify({ presence: 'offline' }), + body: JSON.stringify({ presence: 'offline', ...(status ? { status_msg: status } : {}) }), keepalive: true, }).catch((err) => warnPresenceFailure('offline (pagehide)', err)); };