feat(tui): runtime theme-toggle hotkey (theme iter 3)#184
Merged
Conversation
Press uppercase T from any non-text-input context to cycle through the registered palettes (today: dalton-dark <-> dalton-bright). The swap is session-only — it never writes back to [ui] theme in config.toml, and the next launch resolves theme exactly as before through the layered CLI / env / config / auto-detect chain (#137 contract preserved). What landed: - Theme::cycle_next(current) + Theme::concrete() table — deterministic order driven by the registry, wraps last → first, defensive against unknown current. - Theme::name(theme) for the status-bar toast label. - Global ACTIVE moved from OnceLock<Theme> to RwLock<Theme>; theme() returns by value (Theme: Copy) so callers don't hold a lock across the hot draw path. New theme::set() is the in-session swap path. - App::cycle_theme() reuses the existing set_status_ok toast slot (#135-B / #137 P1) — no new toast subsystem. - Gated by App::in_text_input_context() to avoid hijacking T while the user is editing an annotation prompt or bib-export path. Tests: - cycle_next coverage: two-theme round-trip, single-theme no-op, three-theme full cycle, unknown-current → first. - theme::name round-trips both palettes. - App::handle_key('T') outside input → toggle + toast. - App::handle_key('T') inside an open BibExportPrompt → no toggle, prompt absorbs the keystroke as a path char. - Toggle does not rewrite config.toml on disk. VHS tape (tests/vhs/theme-toggle.tape) captures dark → light → dark transitions plus the post-toggle status-bar toast. Closes #175
8ed58d1 to
d203c62
Compare
10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Tfrom any non-text-input context to cycle the active palette (today:dalton-dark↔dalton-bright). Status bar flashestheme: <name>via the existing toast slot (feat(bib): CSL-JSON + TUI export keybind + diff (iter 3 of 3) #135-B / feat(tui): light mode + auto-detect (theme iter 2) #137 P1).[ui] themeinconfig.toml. Next launch resolves theme exactly as before through the CLI / env / config / auto-detect precedence chain (the feat(tui): light mode + auto-detect (theme iter 2) #137 contract is preserved).Theme::cycle_next+Theme::concrete()table are deterministic and wrap last → first; defensive whencurrentis unknown.Why
T?Both
tandTwere unused across the entire TUI keymap (verified by full-crate grep). PickedTso it parallels the other capital action keys —D(download),R(reader),O(open externally),E(export). Lowercase letters are reserved for navigation / list controls.Mechanical changes
theme::ACTIVEmoved fromOnceLock<Theme>toRwLock<Theme>;theme()now returnsThemeby value (Copy, ~24 fields), so view callsites don't hold the lock across the hot draw path.theme::set(t)is the in-session swap.App::cycle_theme()+App::in_text_input_context()— the latter mirrors the prompt-gating pattern already used inhandle_paper_detail_key/handle_question_dashboard_key.Test plan
cargo test -p scitadel-tui— 51/51 passing (4 newcycle_nextcases +theme_name_round_trips_concrete_palettes+set_swaps_active_theme+ 3 newAppkeybind tests).cargo test --workspace --exclude scitadel-tui— all green.just lint— fmt + clippy clean (-D warnings).tests/vhs/theme-toggle.tapeships dark → light → wrap-back-to-dark and the post-toggle status-bar toast.scitadel tui --theme dark, pressT, confirm light palette + toast; pressTagain, confirm wrap to dark.E), pressT, confirm theme is unchanged andTlands in the path buffer.Closes #175