Repository navigation
Worktree rich text notes - #1
Conversation
A single multiline TextInput has nowhere to put a bullet, an alignment or
an image, so a note becomes a column of blocks -- one TextInput each,
edited in place. Enter splits at the caret, Backspace at the start merges
upward, and the first paragraph renders at 28px: the first line has
always been the title, this makes it look like what it already was.
Storage keeps both representations. `doc` is the new nullable column
holding the block document; `body` stays the plain-text projection of it,
so search ranking, #hashtag parsing, deriveTitle, the list preview and
the Phase 4 sync cursor go on reading exactly what they read before. A
null `doc` is a plain-text note -- every note written until now -- which
parses back as paragraphs, so there is nothing to migrate.
The detail screen moves from save-on-blur to a 600ms autosave: with a
block per line, blur fires every time the caret crosses a boundary.
Two things only the web build gets wrong, both fixed here: it renders
`<textarea rows={2}>`, which made every block two lines tall, and it ran
the default Backspace after our merge, eating the character at the seam.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The marker is structure, not text: a bullet is a block type, drawn in a fixed gutter beside its own input. It cannot be typed over or half deleted, and a line that wraps hangs under the first word rather than under the dot. The list behaves the way the key that made it suggests. Enter continues it, Enter on an empty bullet ends it, and Backspace at the start un-bullets the line before it starts joining it to the one above -- so there is always a way out that is not the toolbar. The toolbar itself appears only while a block has the caret, and hands the caret straight back after a tap, so the keyboard never drops. It reports what the current block is rather than listing everything possible; alignment and images join it in the next two commits. `toggleBullet` is a pure function in core, so what the toolbar does to a document is tested without a simulator. Reopening a saved note now proves the `doc` column round-trips: the bullets come back as bullets, not as literal "- " at the front of a paragraph. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Alignment is per block, which is the unit a reader thinks in -- one centred heading over left-aligned paragraphs, rather than a mode the whole note is in. A new line inherits the alignment of the one it came from, so a centred run stays centred without touching the toolbar again. It stays presentation: `documentToText` ignores it, so `body` -- and with it search, the title and the list preview -- reads exactly the same whichever edge the words sit against. The icons are drawn from four bars rather than set in a font: the app ships no icon set, and three glyphs that only differ by which end the short bars sit at is precisely the shape being described. Alignment goes through the style, not the same-named TextInput prop, which react-native-web silently drops. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The picked file is copied into the app's own storage rather than referenced where it sits: the picker hands back a URI in a cache or a system photo container, which the app may not be able to read later. What the note stores is a relative path, `attachments/<uuid>.jpg`, never an absolute file:// URI -- iOS moves the app container between installs, so an absolute URI saved today is a broken image after the next update. The name is a fresh UUID because two photos off a camera roll are routinely both IMG_0001.jpg. Intrinsic width and height travel with the block, so the space is held open before the file loads and the note does not jump as its photos appear. Removing an image takes it out of the document and leaves the file. A note's delete is soft everywhere else in this app, and an orphaned file is cheaper than a photo the user cannot get back. The web build has no expo-file-system, so it does not offer the button at all rather than offering it and failing -- and a note written on a phone still opens there, with its photos as placeholders. Verified: the pure document operations by unit test, and the web degradation in the browser. The device path -- pick, copy, render, long-press to remove -- is not exercised here; there is no simulator in this environment, so it needs a run on a phone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
product.md and plan.md both said "attachments, images, link unfurling -- text and URLs only through Rollout 1", which the last four commits made false. Since product.md is the authority when the two plans disagree, it is the file that most needs to be true. Images are split from the thing they were bundled with. Local images are in; link unfurling stays out, and now says why -- it is a network call the composer should never make. Other attachments stay out: a file, a recording or a video is not a note. plan.md also gains `doc` in the DDL and the two lines of model rationale worth knowing before touching it: that `body` is a projection rewritten on every edit, and that a null `doc` is a plain-text note, which is why this shipped without a backfill. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`editContent` and the changed `editBody` shipped without tests, and the case that matters most had none at all: a note already on someone's device, whose `doc` is null. It has to open, read back identically, and gain a document on its first edit without its text moving. Also pins the invariant the two columns rest on -- that `body` is exactly `documentToText(doc)` -- and that `editBody` clears `doc`, so a stale document can never outlive the text it described. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (20)
📝 WalkthroughWalkthroughThe PR adds a block-document model with paragraphs, bullets, alignment, and images. Notes store serialized documents with plain-text projections. The mobile app adds block editing, autosave, formatting controls, local image attachments, database migrations, and rollout documentation. ChangesRich Text Notes
Estimated code review effort: 4 (Complex) | ~60 minutes Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary by CodeRabbit