Skip to content

feat: add wiki-link hover previews#756

Closed
maccman wants to merge 3 commits into
nextfrom
codex/wikilink-hover-preview
Closed

feat: add wiki-link hover previews#756
maccman wants to merge 3 commits into
nextfrom
codex/wikilink-hover-preview

Conversation

@maccman

@maccman maccman commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Problem

Wiki links currently require navigation to inspect their target. A hover preview needs to reuse normal date/title/alias semantics without creating missing notes, exposing editor internals, losing pending edits, or allowing preview content to trigger network requests.

What changed

  • add a side-effect-free existing-target resolver with date/title/alias precedence, ambiguity preservation, bounded stale-index disk checks, and a distinct unavailable outcome
  • share that resolver with link navigation and safe note creation so iCloud placeholders and transient reads cannot become duplicate notes
  • wire the Meowdown wiki-link hover card into pointer-capable primary note panes only, with a 300 ms dwell and passive 350 × 200 clipped body
  • read a loaded open session buffer first, otherwise use a generation-pinned disk read, with watcher readiness and request epochs preventing deleted or stale targets from appearing
  • render frontmatter-free local Markdown with inert links, no embeds, and raster-only graph assets; the asset protocol MIME-sniffs preview responses and refuses SVG or other non-raster bytes
  • document the final UX decisions and editor architecture

The editor API is supplied by prosekit/meowdown#288. This branch pins its immutable pkg.pr.new snapshot until that change is released.

Testing

  • pnpm install --frozen-lockfile
  • pnpm check
  • pnpm build
  • pnpm --filter @reflect/core test — 94 files, 1,297 tests
  • pnpm --filter @reflect/desktop test — 219 files, 1,973 tests
  • cargo test -p reflect-open fs::asset_protocol::tests — 5 tests
  • cargo fmt --all -- --check

Scope

Desktop pointer surfaces only. Task editors and touch surfaces remain unchanged; missing, ambiguous, unavailable, and failed targets show no card.


Note

Medium Risk
Touches wiki-link resolution, note creation guards, and asset serving—areas where wrong outcomes create duplicates or load unsafe preview content—but behavior is heavily tested and previews are read-only with explicit unavailable handling.

Overview
Adds passive wiki-link hover previews on pointer-capable desktop note panes (via Meowdown’s WikilinkHoverCard, pinned to a prerelease snapshot). Touch surfaces and task editors do not get the hover renderer.

The preview resolves targets with a new resolveExistingWikiTarget path in @reflect/core (resolved / ambiguous / unavailable / missing), refactors resolveOrCreateNoteWithTitle to delegate to it, and uses the same resolver for link navigation and autocomplete so iCloud placeholders and transient reads cannot be mistaken for “missing” and spawn duplicate notes.

WikiLinkHoverPreview loads generation-pinned content through readExistingNoteSource (live open session when safe, else disk), waits on useFileChanges subscription readiness, and uses request epochs so stale hovers, graph switches, and file watcher events cannot show wrong or deleted notes. The card is inert (interactive / renderEmbeds off), strips frontmatter, and only allows local raster assets via ?reflect-preview=raster; the Tauri asset protocol MIME-sniffs and returns 415 for non-raster preview requests.

MarkdownPreview gains interactive and renderEmbeds flags for passive rendering. Docs mark backlink hover previews as ported.

Reviewed by Cursor Bugbot for commit 5de03f4. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Added passive hover previews for wiki links, including note content, daily-note dates, and empty-note states.
    • Hover previews are non-interactive, local-only, and avoid remote image loading.
    • Added raster-only asset previews for supported image formats.
  • Bug Fixes

    • Improved handling of missing, ambiguous, or unavailable notes during navigation and creation.
    • Prevented stale or outdated preview content from replacing the current preview.
    • Disabled hover previews on touch surfaces.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The change adds side-effect-free existing-note resolution with unavailable outcomes, desktop wiki-link hover previews, inert markdown rendering, touch-surface gating, navigation handling, file-change readiness, and raster-only asset preview enforcement.

Changes

Wiki-link preview flow

Layer / File(s) Summary
Existing-target resolution and unavailable outcomes
packages/core/src/graph/resolve-existing-wiki-target.ts, packages/core/src/graph/create-note.ts, packages/core/src/actions/*, packages/core/src/exports/platform.ts, packages/core/src/graph/*test.ts
Existing targets are resolved through indexed and slug-family disk checks, with generation-pinned reads and explicit missing, resolved, ambiguous, and unavailable results.
Scoped preview loading and file-change invalidation
apps/desktop/src/components/wiki-link-hover-preview.tsx, apps/desktop/src/components/wiki-link-hover-preview.test.tsx, apps/desktop/src/lib/*
Hover previews load live or generation-pinned note content, wait for watcher readiness, invalidate stale results, dismiss on file changes, and render empty daily notes distinctly.
Editor hover-card wiring and inert markdown rendering
apps/desktop/src/editor/*, apps/desktop/src/components/note-pane.tsx, apps/desktop/src/components/route-content.test.tsx, docs/contributing/*, docs/porting/*, pnpm-workspace.yaml
NoteEditor accepts a hover renderer, NotePane enables it only for writable non-touch surfaces, and MarkdownPreview supports inert rendering with embeds disabled.
Navigation and autocomplete outcome handling
apps/desktop/src/editor/use-wiki-link-navigation.ts, apps/desktop/src/editor/use-editor-autocomplete.ts, related tests
Date and title navigation now use existing-target resolution when generation is available and report unavailable notes instead of creating or navigating.
Raster-preview MIME enforcement
apps/desktop/src-tauri/src/fs/asset_protocol.rs
Raster preview requests are recognized explicitly and served only when sniffed content has an approved raster MIME type.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant NotePane
  participant NoteEditor
  participant WikilinkHoverCard
  participant WikiLinkHoverPreview
  participant ReflectCore
  User->>NotePane: hover wiki link
  NotePane->>NoteEditor: provide hover renderer on non-touch surface
  NoteEditor->>WikilinkHoverCard: mount renderer
  WikilinkHoverCard->>WikiLinkHoverPreview: provide target and dismiss
  WikiLinkHoverPreview->>ReflectCore: resolve and read existing note
  ReflectCore-->>WikiLinkHoverPreview: generation-pinned note content
  WikiLinkHoverPreview-->>WikilinkHoverCard: render inert markdown preview
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding wiki-link hover previews.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/wikilink-hover-preview

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/core/src/graph/resolve-existing-wiki-target.test.ts (1)

20-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid the unchecked params type assertion.

as unknown[] is erased at runtime. Narrow the bridge payload with Array.isArray before passing it to query.

As per coding guidelines, “Avoid type assertions unless genuinely necessary.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/graph/resolve-existing-wiki-target.test.ts` around lines 20
- 25, Update the invoke mock’s db_query branch to validate args?.['params'] with
Array.isArray before passing it to query, using an empty array when the payload
is not an array; remove the unchecked as unknown[] assertion while preserving
the existing SQL fallback and query result behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/desktop/src/lib/use-file-changes.ts`:
- Around line 26-28: Update the subscription lifecycle in useFileChanges so
disabling or unsubscribing invalidates readiness even when the same handler is
later re-enabled. Track a subscription epoch or equivalent generation and
require the current subscription’s subscribeFileChanges promise to resolve
before the readiness check returns true; add coverage for the handler → null →
same handler sequence.

---

Nitpick comments:
In `@packages/core/src/graph/resolve-existing-wiki-target.test.ts`:
- Around line 20-25: Update the invoke mock’s db_query branch to validate
args?.['params'] with Array.isArray before passing it to query, using an empty
array when the payload is not an array; remove the unchecked as unknown[]
assertion while preserving the existing SQL fallback and query result behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0572a91f-e205-4882-a46d-12aa60aab871

📥 Commits

Reviewing files that changed from the base of the PR and between 25220eb and 3a9b6df.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (28)
  • apps/desktop/src-tauri/src/fs/asset_protocol.rs
  • apps/desktop/src/components/note-pane.tsx
  • apps/desktop/src/components/route-content.test.tsx
  • apps/desktop/src/components/wiki-link-hover-preview.test.tsx
  • apps/desktop/src/components/wiki-link-hover-preview.tsx
  • apps/desktop/src/editor/markdown-preview.tsx
  • apps/desktop/src/editor/note-editor.test.tsx
  • apps/desktop/src/editor/note-editor.tsx
  • apps/desktop/src/editor/use-editor-autocomplete.test.tsx
  • apps/desktop/src/editor/use-editor-autocomplete.ts
  • apps/desktop/src/editor/use-wiki-link-hover-preview.tsx
  • apps/desktop/src/editor/use-wiki-link-navigation.test.tsx
  • apps/desktop/src/editor/use-wiki-link-navigation.ts
  • apps/desktop/src/lib/read-existing-note-source.test.ts
  • apps/desktop/src/lib/read-existing-note-source.ts
  • apps/desktop/src/lib/use-file-changes.test.tsx
  • apps/desktop/src/lib/use-file-changes.ts
  • docs/contributing/editor-architecture.md
  • docs/porting/README.md
  • docs/porting/backlink-hover-previews.md
  • packages/core/src/actions/backlink-target.test.ts
  • packages/core/src/actions/backlink-target.ts
  • packages/core/src/exports/platform.ts
  • packages/core/src/graph/create-note.test.ts
  • packages/core/src/graph/create-note.ts
  • packages/core/src/graph/resolve-existing-wiki-target.test.ts
  • packages/core/src/graph/resolve-existing-wiki-target.ts
  • pnpm-workspace.yaml

Comment thread apps/desktop/src/lib/use-file-changes.ts

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 53932c6. Configure here.

Comment thread apps/desktop/src/lib/use-file-changes.ts Outdated
Comment thread apps/desktop/src/components/wiki-link-hover-preview.tsx
@ocavue

ocavue commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

implemented in #768

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants