Summary
The presence-avatar component (AwarenessView / "Active Users") only mounts correctly for the view mode that was active when the note was first opened. Switching between Reading View and Live Preview afterward causes the avatar to disappear, because the component is inserted next to .inline-title and never re-mounted on view-mode change. Additionally, the component hard-depends on .inline-title existing at all, so disabling "Show inline title" in Obsidian settings prevents the avatar from being created in any view mode.
Environment
- Obsidian version: [1.12.7]
- Relay plugin version: [0.7.6]
- Reproduced in a clean vault with all other themes/snippets/plugins disabled
- Reproduced with a newly created shared folder and a brand-new note
Bug 1: Avatar mounts once and doesn't survive Reading View ⇄ Live Preview switching
Steps to reproduce
- Create a shared folder, create a new note inside it, with at least 2 users connected to the same document.
- Set Obsidian's default new-tab view to Reading view.
- Close and reopen the note (or open a new tab) — the note opens in Reading view.
- Observe: the "Active Users" avatar is visible in Reading view. ✅
- Switch to Live Preview / Edit mode on the same note.
- Observe: the avatar disappears. ❌
- Repeat with default view set to Editing view instead — the avatar shows correctly in Live Preview but disappears when switching to Reading view.
Root cause (confirmed via DevTools)
wrapTitle() in the awareness view class only runs once, guarded by:
wrapTitle(){
if(!this.view.view.containerEl || this.destroyed || this.awarenessElement) return;
let t = this.view.view.containerEl.querySelector(".inline-title");
...
this.awarenessElement = document.createElement("div");
...
t.insertAdjacentElement("afterend", this.awarenessElement);
}
Since this.awarenessElement is set after the first successful mount, this method short-circuits on every subsequent call and never re-runs — even though it appears to be called again on attach().
Obsidian maintains separate DOM subtrees for markdown-reading-view and the Live Preview/source editor, both containing an element with class iconic-title-wrapper. When the note is first opened in Reading view, Relay's awareness container is inserted into the Reading-view copy of this wrapper. When the user switches to Live Preview, Obsidian sets that entire subtree (markdown-reading-view and its ancestor iconic-title-wrapper) to display: none — and since Relay never re-mounts into the now-active Live Preview title wrapper, the avatar element is still in the DOM, but sitting inside a hidden subtree.
Verified with DevTools — the avatar element persists, but its ancestor chain shows:
0 user-awareness-container display: flex height: 0
1 iconic-title-wrapper display: none height: 0 <-- hidden
2 mod-header mod-ui display: block height: 0
...
5 markdown-reading-view display: none height: 0 <-- hidden
6 view-content display: block height: 1390
7 workspace-leaf-content ... display: flex height: 1390
Because an ancestor is display: none, no CSS workaround (including position: fixed !important) can make the avatar visible again — a display:none ancestor suppresses rendering of its entire subtree regardless of the child's own position/z-index.
Expected behavior
The awareness avatar should remain visible regardless of which view mode (Reading / Live Preview) is currently active, and should follow the user when switching between them on the same note.
Suggested fix
Re-run wrapTitle() (or fully re-create awarenessElement) whenever the active view mode changes for the same document — e.g. by listening to workspace.on("layout-change") and/or workspace.on("active-leaf-change"), and resetting this.awarenessElement = undefined before re-calling wrapTitle() so it queries the currently-visible .inline-title instead of reusing a stale one.
Bug 2: Avatar fails to mount entirely when "Show inline title" is disabled
Steps to reproduce
- In Obsidian settings → Appearance (or Editor), disable "Show inline title".
- Open a note in a shared folder with active collaborators.
- Observe:
.user-awareness-container is never created in either Reading view or Live Preview. Console shows: Could not find inline-title element to position awareness component.
Root cause
wrapTitle() exclusively looks for .inline-title:
let t = this.view.view.containerEl.querySelector(".inline-title");
if(!t){
this.warn("Could not find inline-title element to position awareness component");
return;
}
There is no fallback anchor element, so disabling this fairly common personalization setting silently disables the entire presence feature with no visible error to the end user (only a console warning).
Expected behavior
The awareness avatar should still display somewhere sensible (e.g. view header / title container area) even when inline title is disabled.
Suggested fix
Add a fallback anchor when .inline-title is not found — e.g. .view-header-title-container, .view-header, or .workspace-leaf-content — so the component can still mount and position itself reasonably without depending on inline title being enabled.
Additional notes
- This was reproduced in a fully clean vault (no other plugins, themes, or CSS snippets enabled), so it is not caused by theme/plugin conflicts.
- Current workaround: set Obsidian's default new-tab view to "Editing view" in Settings → Editor, which avoids triggering Bug 1 in normal daily use (but does not fix Bug 2).
Summary
The presence-avatar component (
AwarenessView/ "Active Users") only mounts correctly for the view mode that was active when the note was first opened. Switching between Reading View and Live Preview afterward causes the avatar to disappear, because the component is inserted next to.inline-titleand never re-mounted on view-mode change. Additionally, the component hard-depends on.inline-titleexisting at all, so disabling "Show inline title" in Obsidian settings prevents the avatar from being created in any view mode.Environment
Bug 1: Avatar mounts once and doesn't survive Reading View ⇄ Live Preview switching
Steps to reproduce
Root cause (confirmed via DevTools)
wrapTitle()in the awareness view class only runs once, guarded by:Since
this.awarenessElementis set after the first successful mount, this method short-circuits on every subsequent call and never re-runs — even though it appears to be called again onattach().Obsidian maintains separate DOM subtrees for
markdown-reading-viewand the Live Preview/source editor, both containing an element with classiconic-title-wrapper. When the note is first opened in Reading view, Relay's awareness container is inserted into the Reading-view copy of this wrapper. When the user switches to Live Preview, Obsidian sets that entire subtree (markdown-reading-viewand its ancestoriconic-title-wrapper) todisplay: none— and since Relay never re-mounts into the now-active Live Preview title wrapper, the avatar element is still in the DOM, but sitting inside a hidden subtree.Verified with DevTools — the avatar element persists, but its ancestor chain shows:
Because an ancestor is
display: none, no CSS workaround (includingposition: fixed !important) can make the avatar visible again — adisplay:noneancestor suppresses rendering of its entire subtree regardless of the child's ownposition/z-index.Expected behavior
The awareness avatar should remain visible regardless of which view mode (Reading / Live Preview) is currently active, and should follow the user when switching between them on the same note.
Suggested fix
Re-run
wrapTitle()(or fully re-createawarenessElement) whenever the active view mode changes for the same document — e.g. by listening toworkspace.on("layout-change")and/orworkspace.on("active-leaf-change"), and resettingthis.awarenessElement = undefinedbefore re-callingwrapTitle()so it queries the currently-visible.inline-titleinstead of reusing a stale one.Bug 2: Avatar fails to mount entirely when "Show inline title" is disabled
Steps to reproduce
.user-awareness-containeris never created in either Reading view or Live Preview. Console shows:Could not find inline-title element to position awareness component.Root cause
wrapTitle()exclusively looks for.inline-title:There is no fallback anchor element, so disabling this fairly common personalization setting silently disables the entire presence feature with no visible error to the end user (only a console warning).
Expected behavior
The awareness avatar should still display somewhere sensible (e.g. view header / title container area) even when inline title is disabled.
Suggested fix
Add a fallback anchor when
.inline-titleis not found — e.g..view-header-title-container,.view-header, or.workspace-leaf-content— so the component can still mount and position itself reasonably without depending on inline title being enabled.Additional notes