From 3232c83bf3d5ca045050dbda78a2a82c3d4ade94 Mon Sep 17 00:00:00 2001 From: Loudghiri Ahmed Date: Mon, 31 Jul 2023 10:41:56 +0200 Subject: [PATCH] FIX: ensure presence channels 'leave' correctly when the tab is backgrounded Co-authored-by: David Taylor --- .../discourse/app/services/presence.js | 14 ++++++- .../tests/unit/services/presence-test.js | 37 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/discourse/app/services/presence.js b/app/assets/javascripts/discourse/app/services/presence.js index 1b6128f762a..d503a7fdda4 100644 --- a/app/assets/javascripts/discourse/app/services/presence.js +++ b/app/assets/javascripts/discourse/app/services/presence.js @@ -266,6 +266,7 @@ export default class PresenceService extends Service { this._presentProxies = new Map(); this._subscribedProxies = new Map(); this._initialDataRequests = new Map(); + this._previousPresentButInactiveChannels = new Set(); if (this.currentUser) { window.addEventListener("beforeunload", this._beaconLeaveAll); @@ -512,6 +513,7 @@ export default class PresenceService extends Service { try { const presentChannels = []; + const presentButInactiveChannels = new Set(); const channelsToLeave = queue .filter((e) => e.type === "leave") .map((e) => e.channel); @@ -524,11 +526,19 @@ export default class PresenceService extends Service { ) { presentChannels.push(channelName); } else { - channelsToLeave.push(channelName); + presentButInactiveChannels.add(channelName); + if (!this._previousPresentButInactiveChannels.has(channelName)) { + channelsToLeave.push(channelName); + } } } + this._previousPresentButInactiveChannels = presentButInactiveChannels; - if (queue.length === 0 && presentChannels.length === 0) { + if ( + queue.length === 0 && + presentChannels.length === 0 && + channelsToLeave.length === 0 + ) { return; } diff --git a/app/assets/javascripts/discourse/tests/unit/services/presence-test.js b/app/assets/javascripts/discourse/tests/unit/services/presence-test.js index 51ab78b72bc..92be317eb35 100644 --- a/app/assets/javascripts/discourse/tests/unit/services/presence-test.js +++ b/app/assets/javascripts/discourse/tests/unit/services/presence-test.js @@ -426,6 +426,43 @@ module("Unit | Service | presence | entering and leaving", function (hooks) { ); }); + test("updates the server presence after going idle", async function (assert) { + const presenceService = getOwner(this).lookup("service:presence"); + presenceService.currentUser = currentUser(); + const channel = presenceService.getChannel("/test/ch1"); + + await channel.enter(); + requests.pop(); // Throw away this request + + setTestPresence(false); + + await presenceService._updateServer(); + assert.strictEqual( + requests.length, + 1, + "updated the server after going idle" + ); + let request = requests.pop(); + assert.true( + request.getAll("leave_channels[]").includes("/test/ch1"), + "left ch1" + ); + + // Go back online + setTestPresence(true); + await presenceService._updateServer(); + assert.strictEqual( + requests.length, + 1, + "updated the server after going back online" + ); + request = requests.pop(); + assert.true( + request.getAll("present_channels[]").includes("/test/ch1"), + "rejoined ch1" + ); + }); + test("handles the onlyWhileActive flag", async function (assert) { const presenceService = getOwner(this).lookup("service:presence"); presenceService.currentUser = currentUser();