diff --git a/shared/components/rstack-collab-overlay.ts b/shared/components/rstack-collab-overlay.ts index d663e5c..859815e 100644 --- a/shared/components/rstack-collab-overlay.ts +++ b/shared/components/rstack-collab-overlay.ts @@ -485,6 +485,19 @@ export class RStackCollabOverlay extends HTMLElement { } } + /** Deduplicate peers by username, keeping the most recently seen entry per user. */ + #uniquePeers(): PeerState[] { + const byName = new Map(); + for (const peer of this.#peers.values()) { + const key = peer.username.toLowerCase(); + const existing = byName.get(key); + if (!existing || peer.lastSeen > existing.lastSeen) { + byName.set(key, peer); + } + } + return Array.from(byName.values()); + } + // ── Color assignment ── #colorForPeer(peerId: string): string { @@ -536,7 +549,8 @@ export class RStackCollabOverlay extends HTMLElement { const countEl = this.#shadow.getElementById('panel-count'); if (!list) return; - const onlineCount = this.#peers.size + 1; + const uniquePeers = this.#uniquePeers(); + const onlineCount = uniquePeers.length + 1; if (countEl) countEl.textContent = this.#connState === 'connected' ? `${onlineCount} online` : '\u2014'; const fragments: string[] = []; @@ -566,9 +580,9 @@ export class RStackCollabOverlay extends HTMLElement { `); - // Remote peer rows + // Remote peer rows (deduplicated by username) const isCanvas = this.#moduleId === 'rspace'; - for (const [pid, peer] of this.#peers) { + for (const peer of uniquePeers) { const ctxParts: string[] = []; if (peer.module) ctxParts.push(peer.module); if (peer.context) ctxParts.push(peer.context); @@ -580,15 +594,15 @@ export class RStackCollabOverlay extends HTMLElement { ${this.#escHtml(peer.username)} ${ctxStr ? `${this.#escHtml(ctxStr)}` : ''} - ${isCanvas ? `` : ''} + ${isCanvas ? `` : ''} `); // Expanded actions for canvas - if (isCanvas && this.#openActionsId === pid) { + if (isCanvas && this.#openActionsId === peer.peerId) { fragments.push(`
- - + +
`); } @@ -707,9 +721,10 @@ export class RStackCollabOverlay extends HTMLElement { return; } - const count = this.#peers.size + 1; // +1 for self + const uniquePeers = this.#uniquePeers(); + const count = uniquePeers.length + 1; // +1 for self - const dots = Array.from(this.#peers.values()) + const dots = uniquePeers .slice(0, 5) // show max 5 dots .map(p => ``) .join('');