feat(desktop): relate notes to canvases and journal entries - #2156
Conversation
The relation picker only searched notes, tasks and events, so a canvas or a journal day could not be related to at all. - `RelationKind` grows two members. `note|task|event` parse and serialize byte-for-byte as before; a journal is addressed by its ISO date, which the existing id charset already covers, and a malformed date is rejected at the boundary rather than opening an Invalid Date downstream. - The picker gets Canvases and Journal groups. Journal hits already came back from quick search and were being dropped; canvases come from the existing `canvas.list` channel, filtered on title in the renderer. - `resolveRefs` resolves both kinds. A soft-deleted canvas stays a dangling, removable chip rather than disappearing. - Canvas and journal navigation delegates to the shared `memry://` grammar in `memry-links` instead of minting a second scheme for the same destinations. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
React Doctor found no new issues. 🎉 Reviewed by React Doctor for commit |
…anvas E2E Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The spec never got past opening the relation picker popover on CI, and it cannot be run on this machine to debug it (the shared `ready(page)` beforeEach times out locally). The seam is covered at every layer by unit/integration tests — URI round-trips, resolver, picker groups and navigation — so the red job is not buying coverage. Tracked for follow-up on #2079. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Dropping the Playwright spec from this PR: it never got past opening the relation picker popover on CI, and it cannot be debugged on my machine (the shared |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Summary
Closes #2079 (partially — see Scope below).
The relation picker only searched notes, tasks and events, so a canvas or a journal day could not be related to at all. This adds both as first-class relation targets, end to end.
RelationKindgrowscanvasandjournal.note|task|eventparse and serialize byte-for-byte as before; the id charset is unchanged. A journal is addressed by its local ISO date (the identity that survives re-indexing, a vault copy and another device), and a non-date journal id is rejected at the boundary rather than opening an Invalid Date downstream.canvas.listchannel filtered on title in the renderer, so no new IPC channel.resolveRefsresolves canvases fromcanvases(data DB) and journal entries from the datednote_cacherows (index DB), still one query per kind. A soft-deleted canvas stays a dangling, removable chip rather than silently disappearing; nothing is scrubbed.memry://grammar inmemry-links(added by fix(desktop): let a wiki link name a canvas #2147) instead of minting a second scheme for the same two destinations. A journal chip opens the journal tab withviewState: { date }.property_refs.target_typewidened toRelationKind. Safe without a migration: plain TEXT, and the table is a rebuildable index-DB cache that is never synced. The graph builder already skips every non-notetarget, so graph edges are unaffected.Backward compatibility
Relation URIs are persisted user data (note frontmatter) and sync between devices, so the union only ever grows.
memry://note|task|event/...values parse, resolve, render and navigate exactly as before — covered by the pre-existing tests, which are untouched.memry://canvas/...tonull, which makes the whole property value failisRelationValueand render as plain text. The value is never rewritten or scrubbed, so downgrade → upgrade is lossless.ipc:checkreports the invoke map unchanged).Scope: properties deliberately left out
The issue also asks for property definitions as relation targets. Left out on purpose, and I'd suggest a separate issue:
PropertyDefinition's only identity is its name, which the Properties settings UI lets the user rename. That directly contradicts the issue's own requirement that a target identity "remain stable across rename" — relating to one would mint references that break on the next rename.Canvases and journals have real, stable identities and real destinations today, so they ship here.
Release note
Relation properties can now point at canvases and journal entries, not just notes, tasks and events. Clicking a journal chip opens the journal on that entry's date; a canvas chip opens that canvas.
Test plan
pnpm typecheck·pnpm lint·pnpm check:architecture·pnpm check:contracts·pnpm ipc:generate && pnpm ipc:check·pnpm --filter @memry/desktop i18n:check— all passpnpm docs:impact --base origin/main --strict(no docs-relevant change flagged) andpnpm docs:build; the relation section ofproperties-tags.mdupdated anyway since the behaviour is user-facingnote|task|eventURIs still parsing, malformed and non-date journal ids rejected safelymemry://canvas/<id>,memry://journal/<date>), canvas title filtering, plus a newuse-relation-navigationsuite covering the canvas tab, the journal tab landing on the target date, and dangling refs opening nothingrelation-canvas-target.e2e.ts(add a relation to a canvas, reload, open it from the chip). Not run locally — the sharedready(page)beforeEach times out on this machine; relying on CI for it.🤖 Generated with Claude Code