Merge branch 'dev'
CI/CD / deploy (push) Successful in 2m8s Details

This commit is contained in:
Jeff Emmett 2026-04-16 15:01:39 -04:00
commit db7e49ee92
1 changed files with 17 additions and 8 deletions

View File

@ -400,6 +400,11 @@ export class RStackCollabOverlay extends HTMLElement {
// ── Local broadcasting ── // ── 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) { #broadcastPresence(cursor?: { x: number; y: number }, selection?: string) {
if (this.#soloMode) return; // suppress outgoing awareness in solo mode if (this.#soloMode) return; // suppress outgoing awareness in solo mode
@ -411,7 +416,7 @@ export class RStackCollabOverlay extends HTMLElement {
selection, selection,
username: this.#localUsername, username: this.#localUsername,
color: this.#localColor, 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.module) ctxParts.push(peer.module);
if (peer.context) ctxParts.push(peer.context); if (peer.context) ctxParts.push(peer.context);
const ctxStr = ctxParts.join(' · '); 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(` fragments.push(`
<div class="people-row${differentView ? ' different-view' : ''}"> <div class="people-row${differentView ? ' different-view' : ''}">
<span class="dot" style="background:${peer.color}"></span> <span class="dot" style="background:${peer.color}"></span>
@ -778,10 +784,12 @@ export class RStackCollabOverlay extends HTMLElement {
const now = Date.now(); const now = Date.now();
const fragments: string[] = []; 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; if (!peer.cursor) continue;
// Skip peers viewing a different sub-document (e.g. different note in rDocs) // Only show cursors for peers on the same page/view
if (this.#viewId && peer.viewId && this.#viewId !== peer.viewId) continue; if ((localView || peer.viewId) && localView !== peer.viewId) continue;
const age = now - peer.lastSeen; const age = now - peer.lastSeen;
const opacity = age > 5000 ? 0.3 : 1; const opacity = age > 5000 ? 0.3 : 1;
@ -819,10 +827,11 @@ export class RStackCollabOverlay extends HTMLElement {
// Remove all existing focus rings from the document // Remove all existing focus rings from the document
document.querySelectorAll('.rstack-collab-focus-ring').forEach(el => el.remove()); 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; if (!peer.selection) continue;
// Skip peers viewing a different sub-document // Only show focus rings for peers on the same page/view
if (this.#viewId && peer.viewId && this.#viewId !== peer.viewId) continue; if ((localView || peer.viewId) && localView !== peer.viewId) continue;
const target = this.#findCollabEl(peer.selection); const target = this.#findCollabEl(peer.selection);
if (!target) continue; if (!target) continue;