ENG-1249 Implement Discourse context overlay in Live Preview - #1414
ENG-1249 Implement Discourse context overlay in Live Preview#1414trangdoan982 wants to merge 4 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
There was a problem hiding this comment.
Devin Review found 4 potential issues.
2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)
PR size/scope checkThis PR is over our review-size guideline.
Please split this into smaller PRs unless there is a clear reason the changes need to land together. If keeping it as one PR, please add a brief justification covering:
|
0fc857f to
11693d4
Compare
64e59c1 to
2e483b3
Compare
Links to a discourse node carry an inline badge with that node's relation count; selecting it opens a popover built on RelationshipSection, the same component the Discourse Context panel renders, so the two cannot disagree. Toggled by a General setting, applied without a reload. The count matches what the panel would list rather than what the store holds: relations awaiting acceptance after an import are excluded, and so are relations whose relation type has been deleted, which the panel drops but relations.json keeps. The badge is plain DOM rather than React so the Reading view counterpart can share it without mounting a React root per link. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review finding: changing a relation while its popover is open replaced the badge the popover is anchored to, leaving the positioning callback bound to a detached element, so the popover jumped on its next resize. CM6 rebuilds a widget's DOM whenever eq() is false, which a count change always is, so the badge now updates through updateDOM and the anchor stays connected. The same helper serves the Reading view path. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four review findings: Picking a node for a new relation dismissed the popover: Obsidian mounts AbstractInputSuggest's list on document.body, so the outside-click guard counted it as outside. Clicks inside a suggestion container are now kept. A popover taller than the space above opened downward and clipped. It now opens toward whichever side has more room. The zero-relation message lives outside React, so adding the first relation from the popover left it beside the new one. It clears itself on the next index change. Removing nodeTypeId from a file suppressed the refresh that should have removed its badges, since the check ran against the new metadata. Files that were nodes are now remembered until they stop being one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Leaves only the constraint each one exists to record. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2e483b3 to
2a60173
Compare
mdroidian
left a comment
There was a problem hiding this comment.
Same as #1413: ENG-1249 Add a cached relations index and link resolution
There should be one PR per ticket. If the original ticket needs to be broken up into three, then create a parent ticket and 3 children tickets, please.
|
ahh gotcha, this answers my question earlier. in case it left you a notification |
|
Superseded by #1434. Closed automatically when its head branch was renamed to |
Second of three stacked PRs for ENG-1249. Stack: #1413 → this → #1415. Based on #1413 — review that first; this diff is against it.
https://www.loom.com/share/a7a58ec7bfd54d34b702c395acffe819
Reviewer brief
Result: In Live Preview, every link to a discourse node carries an inline badge with that node's relation count. Selecting it opens a popover listing those relations, with the option to add one. A node with no relations still badges, reading
0, and its popover says "No discourse relation found". Toggled by Show discourse context overlay in General settings, applied without a reload. Reading view is unchanged and follows in #1415.Review focus: how a badge learns its count changed, and the two CodeMirror flags whose meaning is easy to invert. Both expanded below.
How a badge gets on screen
flowchart LR DOC["editor text<br>see [[Claim A|this]]"] --> RE["extractLinktext<br>→ 'Claim A'"] RE --> RES["resolveDiscourseLinkTarget"] RES --> IDX[("RelationsIndex")] RES --> OUT["file, nodeType, count 4"] OUT --> W["CM6 widget decoration"] W --> BADGE["shared badge element"]The badge is plain DOM, not React. Neither render surface has a React root where a badge is inserted, and mounting one per link — dozens per note — would be far heavier than the badge deserves. #1415 reuses this same element, which is what keeps the two surfaces from drifting apart visually.
React appears exactly once, in the popover, which renders
RelationshipSection— the same component the sidebar panel uses, so the two cannot disagree about a node's relations.How a badge learns its count changed — the subtle part
Nothing about the document changes when a relation is added. The count lives entirely outside the text being rendered.
The trap is in the last two steps.
update()early-returns when nothing relevant changed, and an empty transaction changes neither the document nor the viewport — so the guard swallowed exactly the signal the refresh was sending:The fix gives
update()something it can observe: the index exposes a monotonic version, compared alongside the setting.Two flags whose meaning inverts easily
ignoreEvent()returnstrue— the CM6 default, and the one we want. The subject of "ignore" is the editor, not the widget:truekeeps CM6 out of the way so the badge's own click listener fires. Returningfalsereads like "let the widget receive clicks" and does the opposite — an earlier revision had a badge that rendered perfectly and was completely inert.updateDOM()returnstrue— meaning the element was updated in place and must not be replaced. CM6 rebuilds a widget's DOM whenevereq()is false, which a count change always is; replacing the element would detach the anchor an open popover is positioned against.Verification
pnpm ci:validate: 8/8 check-types, 5/5 test:unit.Scope check
$scope-checkagainst the ENG ticket and final diff.Done When: None. Covers the setting and the overlay for one surface; the second follows.Local delegated full review
Review findings addressed here: badges update in place so an open popover keeps a connected anchor; the outside-click guard no longer treats Obsidian's suggestion overlay as outside; the popover opens toward whichever side has more room; the empty-state message clears when the first relation is added; and a file that stops being a discourse node now triggers the refresh that removes its badges.
Warning
Known limitation: Live Preview skips a link straddling a viewport-range boundary. The badge also does not model
buildGroupedRelationsdropping relations whose endpoint no longer resolves to a file, so a relation pointing at a deleted note is still counted — that needs a file lookup per relation on a render path, so it is left as a follow-up.🤖 Generated with Claude Code