Rebuild breadman as a Tauri 2 + Svelte app (PAD-3) #7

Merged
Breadway merged 4 commits from feature/pad-3-tauri-svelte into main 2026-09-11 18:27:37 +08:00
Owner

Closes the PAD-3 direction change: breadman moves off hand-laid GTK4 onto a Tauri 2 shell with a Svelte frontend. The Rust core is untouched: storage, scheduler, parser and classifier stay in breadpad-shared, and breadman/src/ is now a thin #[tauri::command] layer over it.

Supersedes PR #6 (the GTK AdwDialog New Note / editor unification) which should be closed. Its one requirement, a single editor surface for New note and Edit note, carries over to the Svelte editor here.

Backend (breadman/src/)

  • lib.rs tauri builder, state.rs managed state, commands.rs (list/create/update/delete notes, config load+save, Tier-1 classify_preview for the editor hint, in-session error log), theme.rs.
  • GTK main.rs / editor.rs / screenshot.rs / views/ removed. main.rs keeps the headless CLI paths: breadman done <id>, breadman upcoming --plain, breadman --view <name> (--view editor opens straight into the editor).

Frontend (breadman/ui/)

Svelte 5 + Vite. Sidebar with VIEWS / TYPES / MORE and per-type accent dots; the shared dense single-line row across All / Upcoming / per-type / Archive; one editor modal for New note and Edit note with a live Tier-1 classification readout; width-capped Settings on plain token-matched rows (no AdwSpinRow); Errors. Design follows the PAD-3 direction mockup: Bread design-system tokens, five-type accent system carried sidebar dot to row chip, header search.

Theme

theme.rs renders CSS custom properties from the live pywal palette via bread-theme's css_custom_properties / css_tokens, injected as <style id="bread-theme">, and re-emits theme://changed on a filesystem watch so bread-theme reload recolours the window with no restart.

Build / CI

  • build.rs builds ui/dist on cargo build (skip with BREADMAN_SKIP_UI_BUILD=1 + pnpm -C breadman/ui dev for hot reload).
  • ci/deps.txt adds webkit2gtk-4.1, libsoup3, nodejs, pnpm.
  • dev-release / rc-release / release workflows build with --features breadman/custom-protocol so the frontend is embedded (not the dev server).
  • bakery.toml gains webkit2gtk-4.1.

Verified

  • cargo build --locked (workspace), cargo clippy -p breadman clean, svelte-check 0 errors (5 benign state_referenced_locally warnings in the editor).
  • Ran every view in a nested headless compositor: All / Upcoming / per-type / Archive / Settings / Errors / editor all render and function (create, edit, mark done, delete, search, settings save, live classify preview).

Not in this PR

  • --screenshot <view> capture mode: the GTK path used a native-window grab; the webview needs a compositor-side capture path. breadman --screenshot currently exits with a clear message.
  • CI is unverified against the real self-hosted runner (container image rebuild with the new deps.txt, pnpm install in-container). First check.yml run on this branch will tell.
  • Placeholder app icons in breadman/icons/.
  • On the nested headless compositor WebKitGTK fell back from Varela Round / IBM Plex Mono to a default sans; both fonts are installed and wired through --font-family, so this needs a look on a real desktop.

Refs PAD-3 (breadboard).

Closes the PAD-3 direction change: breadman moves off hand-laid GTK4 onto a Tauri 2 shell with a Svelte frontend. The Rust core is untouched: storage, scheduler, parser and classifier stay in `breadpad-shared`, and `breadman/src/` is now a thin `#[tauri::command]` layer over it. Supersedes PR #6 (the GTK `AdwDialog` New Note / editor unification) which should be closed. Its one requirement, a single editor surface for New note and Edit note, carries over to the Svelte editor here. ### Backend (`breadman/src/`) - `lib.rs` tauri builder, `state.rs` managed state, `commands.rs` (list/create/update/delete notes, config load+save, Tier-1 `classify_preview` for the editor hint, in-session error log), `theme.rs`. - GTK `main.rs` / `editor.rs` / `screenshot.rs` / `views/` removed. `main.rs` keeps the headless CLI paths: `breadman done <id>`, `breadman upcoming --plain`, `breadman --view <name>` (`--view editor` opens straight into the editor). ### Frontend (`breadman/ui/`) Svelte 5 + Vite. Sidebar with VIEWS / TYPES / MORE and per-type accent dots; the shared dense single-line row across All / Upcoming / per-type / Archive; one editor modal for New note and Edit note with a live Tier-1 classification readout; width-capped Settings on plain token-matched rows (no `AdwSpinRow`); Errors. Design follows the [PAD-3 direction mockup](https://claude.ai/code/artifact/f5330ab1-b681-40ae-9565-9a58d55f8d65): Bread design-system tokens, five-type accent system carried sidebar dot to row chip, header search. ### Theme `theme.rs` renders CSS custom properties from the live pywal palette via `bread-theme`'s `css_custom_properties` / `css_tokens`, injected as `<style id="bread-theme">`, and re-emits `theme://changed` on a filesystem watch so `bread-theme reload` recolours the window with no restart. ### Build / CI - `build.rs` builds `ui/dist` on `cargo build` (skip with `BREADMAN_SKIP_UI_BUILD=1` + `pnpm -C breadman/ui dev` for hot reload). - `ci/deps.txt` adds `webkit2gtk-4.1`, `libsoup3`, `nodejs`, `pnpm`. - `dev-release` / `rc-release` / `release` workflows build with `--features breadman/custom-protocol` so the frontend is embedded (not the dev server). - `bakery.toml` gains `webkit2gtk-4.1`. ### Verified - `cargo build --locked` (workspace), `cargo clippy -p breadman` clean, `svelte-check` 0 errors (5 benign `state_referenced_locally` warnings in the editor). - Ran every view in a nested headless compositor: All / Upcoming / per-type / Archive / Settings / Errors / editor all render and function (create, edit, mark done, delete, search, settings save, live classify preview). ### Not in this PR - `--screenshot <view>` capture mode: the GTK path used a native-window grab; the webview needs a compositor-side capture path. `breadman --screenshot` currently exits with a clear message. - CI is unverified against the real self-hosted runner (container image rebuild with the new `deps.txt`, `pnpm install` in-container). First `check.yml` run on this branch will tell. - Placeholder app icons in `breadman/icons/`. - On the nested headless compositor WebKitGTK fell back from Varela Round / IBM Plex Mono to a default sans; both fonts are installed and wired through `--font-family`, so this needs a look on a real desktop. Refs PAD-3 (breadboard).
refactor(breadman): rebuild the manager UI as a Tauri 2 + Svelte app
Some checks failed
check / check (push) Failing after 3m40s
bda8d4d007
PAD-3. Replaces breadman's hand-laid GTK4 window with a Tauri 2 shell and a
Svelte frontend. The Rust core does not move: storage, scheduler, parser and
classifier all still live in breadpad-shared, and src/ is now a thin
#[tauri::command] layer over it (list/create/update/delete notes, config
load+save, a Tier-1 classify preview for the editor, an in-session error
log). Layout, density, the five-type accent system and the header-search
placement follow the PAD-3 direction mockup.

- src/: lib.rs (tauri builder), state.rs, commands.rs, theme.rs. The GTK
  main.rs / editor.rs / screenshot.rs / views/ are removed; main.rs keeps
  the headless CLI paths (`done <id>`, `upcoming --plain`, `--view`).
- ui/: Svelte 5 + Vite. Sidebar (VIEWS / TYPES / MORE), the shared dense
  single-line row across All / Upcoming / per-type / Archive, one editor
  surface for New note and Edit note (the PAD-3 "highest-value piece"),
  width-capped Settings on plain token rows, Errors.
- theme.rs bridges the live pywal palette to CSS custom properties via
  bread-theme's css_custom_properties / css_tokens, and re-emits on change
  so `bread-theme reload` recolours the window with no restart.
- build.rs builds ui/dist on `cargo build` (skip with BREADMAN_SKIP_UI_BUILD);
  ci/deps.txt adds webkit2gtk-4.1 + node + pnpm; the release workflows build
  breadman with the `custom-protocol` feature so the frontend is embedded.

notes.jsonl / archive.jsonl format is unchanged. `--screenshot` capture mode
is not yet ported (needs a compositor-side path for the webview).
fix(breadman): readability pass + friendlier Settings
Some checks failed
check / check (push) Failing after 21s
7283e42ff4
Review feedback from running it on the desktop:

- Type scale up: 16px base (was 15), sidebar section labels 12.5px and
  brighter, nav items 15.5px, note rows 16px, settings labels 16px. The
  14px base read as tiny on a 1920px screen at scale 1.

- Lists and the toolbar now share one centred max-width column so the
  view title, search and rows line up instead of the rows sprawling the
  full window width.

- Settings is its own centred ViewScaffold-style column (was left-aligned
  with a huge right gutter): own <h1>, no shared toolbar, 760px cap,
  margin auto.

- Settings number fields: native spin buttons removed (they crowded and
  clipped "0.6" -> "0."), left-aligned (were right-aligned, so the click
  target read wrong), widened.

- Settings rebuilt for non-power-users:
  - grouped by intent (Notes / Reminders / Calendar sync), plain-language
    labels and one-line help on every field.
  - "Morning starts at" is a time picker; snooze options are preset chips
    (15 min / 30 min / 1 hour / 3 hours / Tomorrow morning) instead of a
    raw comma-separated string; "if a reminder was missed" is a plain
    dropdown instead of a raw minutes number.
  - calendar URL/username/password only appear once sync is switched on.
  - Ollama internals, the confidence threshold (now a % slider), and the
    ONNX model/tokenizer/runtime paths are collapsed into an "Advanced"
    disclosure, closed by default.

- breadman no longer rotates the archive on launch (the GTK build never
  did; it's a viewer, not a writer). The Archive view already merges done
  notes from notes.jsonl with archive.jsonl.
style(breadman): drop em dashes from UI copy and comments
Some checks failed
check / check (push) Failing after 13s
1b246f2191
Standing house rule is no em dashes in authored text. Replaced the six
that slipped in (Settings help strings, a summary label, two code
comments) with sentence breaks and colons.
fix(breadman): wire up --screenshot capture, fix CI's pnpm ignored-builds error
All checks were successful
check / check (push) Successful in 8m20s
8f0110cb31
Two independent CI blockers on this PR:

- pnpm 11's default-deny on dependency build scripts (esbuild's postinstall)
  was making `pnpm install --frozen-lockfile` exit 1 in build.rs, failing
  every check run. The already-committed ui/pnpm-workspace.yaml used
  onlyBuiltDependencies, which this pnpm version silently ignores (confirmed
  against the same bread-ci:breadpad image CI uses); the key it actually
  reads is allowBuilds.

- --screenshot was a stub that just bailed with 'not yet supported'. This
  wires it up for real: main.rs parses --screenshot/--output/--width/--height
  (same convention as breadpad's sibling GTK app), lib.rs sizes/positions the
  webview window to the requested canvas and captures via
  bread_screenshots::capture_region once the frontend confirms its first
  paint (a new notify_ui_ready command, called from App.svelte after tick()
  + a rAF round trip), falling back to a fixed delay if that signal never
  arrives so a render-blocking frontend error can't hang bread-capture.

Verified against the real bread-ci:breadpad CI image on hestia (clippy +
full workspace test suite, both clean) and functionally inside cage (the
isolated single-client compositor bread-capture's pipeline actually uses,
not the live tiling desktop, which doesn't honor client-requested window
geometry and made an earlier local test capture the wrong window entirely):
both the all-notes list view and the editor modal capture correctly.
Breadway deleted branch feature/pad-3-tauri-svelte 2026-09-11 18:27:37 +08:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Breadway/breadpad!7
No description provided.