scratch: the scratchpad is the inbox, with ways out and a search

A note now leaves the scratchpad by becoming something else: `K` keeps it
as a document, as before; `C` makes it a card where `:card` would put one,
the first line its title; `A` opens `:append` with the document on screen
filled in, Tab completing any other title, and puts the note at its end.

`/api/capture` takes `to: "note"` and `to: "document"` (named as a link
names it), and `note`, the scratch note the text came from, dropped once
the text has landed. Appending keeps the revision before it and indexes
links and media, as a save does.

Migration 0028 adds `scratch_fts`; `GET /api/scratch?q=` searches it, and
`/` lists note hits under "notes" after the cards, Enter lowering the
drawer at the note.

The `c` capture line cycles its target with Tab: a card, a note, or a
timed line in today's entry, which `:today <text>` now writes.
This commit is contained in:
nvrl committed 2026-10-22 11:22:55 +02:00
1 parent ccc91028e7
commit 2233fa41a6
20 files changed
+561 -84

No files matched your search

+10 -3
View File
@@ -105,7 +105,7 @@ export interface ApiToken {
/** Where `POST /api/capture` put the text. */
export interface Captured {
to: 'card' | 'diary'
to: 'card' | 'diary' | 'note' | 'document'
id: number
where: string
}
@@ -608,8 +608,15 @@ export const api = {
},
) => request<Moved>(`/cards/${id}`, { method: 'PUT', body: body(patch) }),
/** The scratchpad's notes, the one touched last first. */
scratch: () => request<ScratchNote[]>('/scratch'),
/** The scratchpad's notes, the one touched last first — or those a search finds, the best first. */
scratch: (q?: string) => request<ScratchNote[]>(`/scratch${q === undefined ? '' : `?q=${encodeURIComponent(q)}`}`),
/**
* Text written down somewhere: a card in an inbox, a line in today's entry,
* a note, the end of a document. With `note`, the text is that note's, and
* it leaves the scratchpad once the text has landed.
*/
capture: (input: { text: string; to: Captured['to']; space?: string; document?: string; note?: number }) =>
request<Captured>('/capture', { method: 'POST', body: body(input) }),
createScratch: (text: string) => request<ScratchNote>('/scratch', { method: 'POST', body: body({ body: text }) }),
updateScratch: (id: number, text: string) =>
request<ScratchNote>(`/scratch/${id}`, { method: 'PUT', body: body({ body: text }) }),