core: drop the two helpers the block editor made unnecessary
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 2m56s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 5m15s
Desktop (Tauri) / Update manifest (push) Successful in 4s
Android / Kotlin + Rust (APK) (push) Successful in 7m30s

`toggle_at` existed to map a tap on `[ ]` inside a plain text field to an item, and
`continuation` to make Return start the next one. The block editor needs neither: a
checkbox is a real Checkbox, so it is tapped rather than located, and Return is the
field's own IME action rather than a shape recognised in a string.

Removed rather than kept for later (rule 22). Both were exported over the FFI with
no Kotlin caller, which is API surface promising something nothing does — and their
tests were weight on code nothing runs.

The section comment above them described the tap-in-a-text-field problem, which is
no longer the problem this pair solves. Rewritten to say what is actually there:
one function to read a body apart, one to put a line back together, and between them
Kotlin renders checkboxes without owning the grammar.
This commit is contained in:
2026-08-24 10:42:26 -04:00
parent 32ec29fc4a
commit a88f7c2dd0
2 changed files with 10 additions and 99 deletions
+10 -23
View File
@@ -501,15 +501,17 @@ impl ThoughtSync {
// ── checklist text, as pure functions ───────────────────────────────────────
//
// Free functions rather than methods, because these touch no database. The editor's
// body field is LOCAL state — it is autosaved on an idle debounce, not written on
// every keystroke — so a checkbox tapped in the editor has to rewrite the text the
// field is holding, not a row the store would hand back a moment later. Routing that
// through the store would overwrite whatever was being typed.
// The pair the block editor is built on: one to read a body apart, one to put a line
// back together. Between them, Kotlin can render a checklist as real checkboxes and
// write the markdown back without owning the grammar — which is the point. Three
// implementations of it is the price already being paid (Rust, Python, TypeScript);
// a fourth in Compose would be one more place for a checklist to change shape when
// it syncs.
//
// They also keep the grammar out of Kotlin. Three implementations of it is the price
// already being paid (Rust, Python, TypeScript); a fourth in Compose would be one
// more place for a checklist to change shape when it syncs.
// Free functions rather than methods, because they touch no database. The editor's
// body is LOCAL state — autosaved on an idle debounce, not written per keystroke —
// so editing a checklist there has to rewrite the text the editor is holding, not a
// row the store would hand back a moment later and overwrite the typing with.
/// One checklist item as the body line that stores it. For an editor that shows a
/// checkbox instead of the markup and has to write the markup back.
@@ -528,21 +530,6 @@ pub fn checklist_items(body: String) -> Vec<BodyItem> {
.collect()
}
/// The body with the item at `line`/`column` ticked or unticked, or null if that is
/// not a checkbox. See `derive::toggle_at` for why the address is line + column and
/// not a text offset.
#[uniffi::export]
pub fn checklist_toggle_at(body: String, line: u32, column: u32) -> Option<String> {
local::derive::toggle_at(&body, line as usize, column as usize)
}
/// What pressing Enter at the end of `line` should leave behind: null to let Enter be
/// Enter, "" to end the list, or the marker to start the next item.
#[uniffi::export]
pub fn checklist_continuation(line: String) -> Option<String> {
local::derive::continuation(&line)
}
/// Helpers, deliberately NOT exported — uniffi only binds what an `#[uniffi::export]`
/// block names, so these stay Rust-side.
impl ThoughtSync {