Skip to content

web: create a note directly from the internal link picker#10050

Open
the0s1s wants to merge 5 commits into
streetwriters:masterfrom
the0s1s:feature/create-notes-from-linking
Open

web: create a note directly from the internal link picker#10050
the0s1s wants to merge 5 commits into
streetwriters:masterfrom
the0s1s:feature/create-notes-from-linking

Conversation

@the0s1s

@the0s1s the0s1s commented Jul 2, 2026

Copy link
Copy Markdown

Description

The internal-link picker only searched existing notes, so typing the name of a
note that does not exist left an empty list with no way forward.

This adds a "Create note" action to the picker. When the typed name matches no
existing note (an exact, case-insensitive title check against non-trashed
notes), the picker offers to create that note and insert the nn://note link
in a single step.

Implementation notes:

  • The existence check uses a SQLite LIKE match (no wildcards), which is a
    case-insensitive full-string comparison, filtered to exclude trashed notes.
    The fuzzy full-text lookup that populates the list cannot answer "does an
    exact note with this title exist", so the check is a separate query.
  • On click, the action calls db.notes.add({ title }), refreshes the note
    store, and closes the dialog with the new note's nn://note link.

Type of Change

  • Bug fix
  • [ x ] Feature

Visuals

  • [ X] Attached relevant screenshots / screen recording / GIF
image

Testing

  • Ran all E2E tests
  • Ran all integration tests
  • [x ] Added/updated tests for this change (if needed)
  • N/A (tests not needed — explanation provided below)

If tests were not added, explain why

Tests were added: apps/web/__e2e__/note-linking.test.ts covers both paths:
one test types a title matching no note, asserts the create action appears,
creates the note, and confirms an nn://note link is inserted into the current
note and the new note appears in the list; the second types an existing note's
title and asserts the create action is not offered.

E2E and integration suites were not run to green locally. The web e2e suite
could not load until a separate cross-package Playwright fix (see the
fix/web-e2e-duplicate-playwright branch), and the local machine cannot extract
Playwright browser binaries. The suite does load and discover these tests; they
are expected to run in CI where browsers are provisioned.

Platform

  • [x ] Web
  • Mobile
  • Desktop

Sign-off

  • QA passed
  • UI/UX passed

the0s1s and others added 3 commits June 30, 2026 21:11
The internal-link picker only searched existing notes, so typing the name
of a note that does not exist left an empty list with no way forward. When
the typed name matches no existing note (exact, case-insensitive title check
against non-trashed notes), show a "Create note" action that creates the
note via db.notes.add and inserts the nn://note link in one step.

Signed-off-by: Dru Banks <dru.l.banks@pm.me>
Typing a name that matches no existing note in the internal link dialog now
offers to create that note and link to it in a single step. These end-to-end
tests cover that path: the first checks the create action appears, creates
the note, and inserts an nn://note link into the current note; the second
verifies the action is not offered when a note with that title already exists.

To support the tests, this adds a few hooks to the note-linking dialog (a
testId on the dialog plus ids on the search field and create button) and a
small openNoteLinkDialog() helper on the editor model.

Signed-off-by: Dru Banks <dru.l.banks@pm.me>
@the0s1s

the0s1s commented Jul 2, 2026

Copy link
Copy Markdown
Author

Related to issue #10045

Comment thread packages/intl/src/strings.ts Outdated
Signed-off-by: Dru Banks <dru.l.banks@pm.me>
Comment thread apps/web/src/dialogs/note-linking-dialog.tsx Outdated
Address review feedback on the note-linking dialog: drop the raw db.sql()
LIKE query used to detect an existing note and replace it with the core
collection API, db.notes.all.find((eb) => eb("notes.title", "==", query)).
The notes.title column is COLLATE NOCASE, so "==" is a case-insensitive
full-string match (no LIKE wildcard hazard) and db.notes.all excludes
trashed/archived notes.

Also scope the picker's list search to titles via
db.lookup.notes("title: <query>") instead of the default title+content
full-text search.

Signed-off-by: Dru Banks <dru.l.banks@pm.me>
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.

3 participants