diff --git a/shared/components/rstack-collab-overlay.ts b/shared/components/rstack-collab-overlay.ts index 56344859..97e4f0bd 100644 --- a/shared/components/rstack-collab-overlay.ts +++ b/shared/components/rstack-collab-overlay.ts @@ -400,6 +400,11 @@ export class RStackCollabOverlay extends HTMLElement { // ── Local broadcasting ── + /** Effective view identifier — viewId if set, else moduleId. Used to scope cursor visibility. */ + get #effectiveViewId(): string | null { + return this.#viewId || this.#moduleId || null; + } + #broadcastPresence(cursor?: { x: number; y: number }, selection?: string) { if (this.#soloMode) return; // suppress outgoing awareness in solo mode @@ -411,7 +416,7 @@ export class RStackCollabOverlay extends HTMLElement { selection, username: this.#localUsername, color: this.#localColor, - viewId: this.#viewId, + viewId: this.#effectiveViewId, }); } @@ -619,7 +624,8 @@ export class RStackCollabOverlay extends HTMLElement { if (peer.module) ctxParts.push(peer.module); if (peer.context) ctxParts.push(peer.context); const ctxStr = ctxParts.join(' · '); - const differentView = !!(this.#viewId && peer.viewId && this.#viewId !== peer.viewId); + const localView = this.#effectiveViewId; + const differentView = !!((localView || peer.viewId) && localView !== peer.viewId); fragments.push(`
@@ -778,10 +784,12 @@ export class RStackCollabOverlay extends HTMLElement { const now = Date.now(); const fragments: string[] = []; - for (const peer of this.#peers.values()) { + // Deduplicate by username — only show the most recent cursor per user + const localView = this.#effectiveViewId; + for (const peer of this.#uniquePeers()) { if (!peer.cursor) continue; - // Skip peers viewing a different sub-document (e.g. different note in rDocs) - if (this.#viewId && peer.viewId && this.#viewId !== peer.viewId) continue; + // Only show cursors for peers on the same page/view + if ((localView || peer.viewId) && localView !== peer.viewId) continue; const age = now - peer.lastSeen; const opacity = age > 5000 ? 0.3 : 1; @@ -819,10 +827,11 @@ export class RStackCollabOverlay extends HTMLElement { // Remove all existing focus rings from the document document.querySelectorAll('.rstack-collab-focus-ring').forEach(el => el.remove()); - for (const peer of this.#peers.values()) { + const localView = this.#effectiveViewId; + for (const peer of this.#uniquePeers()) { if (!peer.selection) continue; - // Skip peers viewing a different sub-document - if (this.#viewId && peer.viewId && this.#viewId !== peer.viewId) continue; + // Only show focus rings for peers on the same page/view + if ((localView || peer.viewId) && localView !== peer.viewId) continue; const target = this.#findCollabEl(peer.selection); if (!target) continue;