From c7c92ee0da63a06a3e0ada12b95b6c7a7802232a Mon Sep 17 00:00:00 2001 From: Brian Krabach Date: Tue, 31 Mar 2026 01:37:49 -0700 Subject: [PATCH] feat: use sessionKey for cross-device dedup in detectBellTransitions (task-18) Replace s.name with s.sessionKey || s.name as the map key in detectBellTransitions so two sessions with the same name on different devices are tracked independently. - prevMap construction uses s.sessionKey || s.name as key - next filter lookup uses the same s.sessionKey || s.name key - Falls back to s.name when no sessionKey is present (backward compatible) Co-authored-by: Amplifier --- muxplex/frontend/app.js | 15 +++++++++------ muxplex/frontend/tests/test_app.mjs | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/muxplex/frontend/app.js b/muxplex/frontend/app.js index 740f7ae..a85f4f8 100644 --- a/muxplex/frontend/app.js +++ b/muxplex/frontend/app.js @@ -66,17 +66,20 @@ function filterByQuery(sessions, query) { * @returns {string[]} names of sessions that newly have or increased bell count */ function detectBellTransitions(prev, next) { - const prevMap = new Map( - (prev || []).map((s) => [s.name, (s.bell && s.bell.unseen_count) || 0]), + var prevMap = new Map( + (prev || []).map(function(s) { + return [s.sessionKey || s.name, (s.bell && s.bell.unseen_count) || 0]; + }), ); return (next || []) - .filter((s) => { - const unseen = s.bell && s.bell.unseen_count; + .filter(function(s) { + var unseen = s.bell && s.bell.unseen_count; if (!unseen || unseen <= 0) return false; - const prevCount = prevMap.has(s.name) ? prevMap.get(s.name) : 0; + var key = s.sessionKey || s.name; + var prevCount = prevMap.has(key) ? prevMap.get(key) : 0; return unseen > prevCount; }) - .map((s) => s.name); + .map(function(s) { return s.name; }); } /** diff --git a/muxplex/frontend/tests/test_app.mjs b/muxplex/frontend/tests/test_app.mjs index 9998e01..155ed52 100644 --- a/muxplex/frontend/tests/test_app.mjs +++ b/muxplex/frontend/tests/test_app.mjs @@ -189,6 +189,27 @@ test('detectBellTransitions does not fire when unseen_count decreases', () => { assert.deepStrictEqual(app.detectBellTransitions(prev, next), []); }); +test('detectBellTransitions uses sessionKey to distinguish same-name sessions across devices', () => { + // Two sessions both named 'main' but from different devices, identified by sessionKey + const prev = [ + { name: 'main', sessionKey: 'device-A::main', bell: { unseen_count: 3 } }, + { name: 'main', sessionKey: 'device-B::main', bell: { unseen_count: 0 } }, + ]; + const next = [ + { name: 'main', sessionKey: 'device-A::main', bell: { unseen_count: 3 } }, // no change + { name: 'main', sessionKey: 'device-B::main', bell: { unseen_count: 2 } }, // increased + ]; + // Only the device-B 'main' session should trigger (its count increased from 0 to 2) + assert.deepStrictEqual(app.detectBellTransitions(prev, next), ['main']); +}); + +test('detectBellTransitions falls back to s.name when no sessionKey present', () => { + // Sessions without sessionKey should still work using name as fallback + const prev = [{ name: 'work', bell: { unseen_count: 0 } }]; + const next = [{ name: 'work', bell: { unseen_count: 1 } }]; + assert.deepStrictEqual(app.detectBellTransitions(prev, next), ['work']); +}); + // --- generateDeviceId --- test('generateDeviceId returns a string matching /^d-[a-z0-9]+$/', () => {