diff --git a/.forgejo/workflows/dev-release.yml b/.forgejo/workflows/dev-release.yml index 5c7b221..291d765 100644 --- a/.forgejo/workflows/dev-release.yml +++ b/.forgejo/workflows/dev-release.yml @@ -71,10 +71,10 @@ jobs: echo "::error::BAKERY_MINISIGN_SEC_KEY_PATH secret not set — refusing to regenerate dev index.json unsigned (would leave a stale signature mismatched against fresh content and break bakery for everyone on the dev track)" exit 1 fi - rm -rf /tmp/bread-ecosystem-ci-* 2>/dev/null || true - # mktemp: a fixed clone path races when multiple repos' dev/beta - # workflows run close together on the same self-hosted runner. - ECOSYSTEM_CI_DIR="$(mktemp -d /tmp/bread-ecosystem-ci-XXXXXX)" + # Do not wipe /tmp/bread-ecosystem-ci-* — other products' ci/build.sh + # caches live there and a wipe between their build and test steps + # is a 127 (missing ci/build.sh). + ECOSYSTEM_CI_DIR="$(mktemp -d /tmp/bread-ecosystem-index-XXXXXX)" git clone --branch main https://git.breadway.dev/Breadway/bread-ecosystem.git "${ECOSYSTEM_CI_DIR}" TRACK=dev bash "${ECOSYSTEM_CI_DIR}/scripts/gen-index.sh" rm -rf "${ECOSYSTEM_CI_DIR}" diff --git a/.gitignore b/.gitignore index 7379fb9..14a0220 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,6 @@ logs/ .claude/ # Local hygiene notes (not for commit) + +# graphify knowledge-graph output (local tool cache, not for commit) +graphify-out/ diff --git a/Cargo.lock b/Cargo.lock index 9512dfa..16c4fd9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,8 +55,8 @@ dependencies = [ [[package]] name = "bread-theme" -version = "0.7.2" -source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?tag=v0.7.2#30517f161724132cdeb658c04cf5e490be07ee73" +version = "0.7.4" +source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?tag=v0.7.4#fcba3760387e2523edb71350f8efea3bc851b21e" dependencies = [ "dirs", "gtk4", @@ -78,7 +78,7 @@ dependencies = [ [[package]] name = "breadhelp" -version = "0.2.4" +version = "0.2.6" dependencies = [ "anyhow", "async-channel", @@ -115,7 +115,7 @@ checksum = "f8b4985713047f5faee02b8db6a6ef32bbb50269ff53c1aee716d1d195b76d54" dependencies = [ "glib-sys", "libc", - "system-deps", + "system-deps 7.0.8", ] [[package]] @@ -178,11 +178,10 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "event-listener" -version = "5.4.1" +version = "5.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" dependencies = [ - "concurrent-queue", "parking", "pin-project-lite", ] @@ -209,24 +208,24 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-executor" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" dependencies = [ "futures-core", "futures-task", @@ -235,32 +234,32 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" [[package]] name = "futures-macro" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] name = "futures-task" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-util" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures-core", "futures-macro", @@ -291,7 +290,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 7.0.8", ] [[package]] @@ -324,7 +323,7 @@ dependencies = [ "libc", "pango-sys", "pkg-config", - "system-deps", + "system-deps 7.0.8", ] [[package]] @@ -364,7 +363,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 7.0.8", "windows-sys 0.61.2", ] @@ -418,7 +417,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -428,7 +427,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "030967459f9f676851872c6304adea7825c6d462ec9b72554c733cf0c5952233" dependencies = [ "libc", - "system-deps", + "system-deps 7.0.8", ] [[package]] @@ -439,7 +438,7 @@ checksum = "22a861859b887a79cf461359c192c97a57d8fb0229dd291232e57aa11f6fa72c" dependencies = [ "glib-sys", "libc", - "system-deps", + "system-deps 7.0.8", ] [[package]] @@ -460,7 +459,7 @@ checksum = "5c7ffdfde88f3570d3705e0d8a2433e036d387a1f2930bbf47eafcb5f569fd04" dependencies = [ "glib-sys", "libc", - "system-deps", + "system-deps 7.0.8", ] [[package]] @@ -491,7 +490,7 @@ dependencies = [ "graphene-sys", "libc", "pango-sys", - "system-deps", + "system-deps 7.0.8", ] [[package]] @@ -517,9 +516,9 @@ dependencies = [ [[package]] name = "gtk4-layer-shell" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4069987ff4793699511a251028cc336b438e46565b463f111250148d574752a" +checksum = "17c28ea0f4676fdaaae7ff2413a24d0d35c8657424f84856c1103c73454c9da4" dependencies = [ "bitflags", "gdk4", @@ -532,15 +531,15 @@ dependencies = [ [[package]] name = "gtk4-layer-shell-sys" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f566a5ec5bcc454e7fcf2ab76930887ced5365afce12c1e5201bb296b95f1b9" +checksum = "bcf19bb884ef0ef55b9e6b2b369c39b4fcc0c41e3a0c1cbc8c267720338b690b" dependencies = [ "gdk4-sys", "glib-sys", "gtk4-sys", "libc", - "system-deps", + "system-deps 8.0.0", ] [[package]] @@ -552,7 +551,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -571,7 +570,7 @@ dependencies = [ "gsk4-sys", "libc", "pango-sys", - "system-deps", + "system-deps 7.0.8", ] [[package]] @@ -610,15 +609,15 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libredox" -version = "0.1.18" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a" dependencies = [ "libc", ] @@ -676,7 +675,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 7.0.8", ] [[package]] @@ -693,9 +692,9 @@ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" [[package]] name = "proc-macro-crate" @@ -708,18 +707,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.46" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -752,9 +751,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -762,29 +761,29 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] name = "serde_json" -version = "1.0.150" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -834,6 +833,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "system-deps" version = "7.0.8" @@ -843,7 +853,20 @@ dependencies = [ "cfg-expr", "heck", "pkg-config", - "toml 1.1.3+spec-1.1.0", + "toml 1.1.4+spec-1.1.0", + "version-compare", +] + +[[package]] +name = "system-deps" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83779a5c956bcb6ba627a4ecf0a9d7625db47d7537e0892d97f712ac995648a3" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml 1.1.4+spec-1.1.0", "version-compare", ] @@ -870,7 +893,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -887,9 +910,9 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.3+spec-1.1.0" +version = "1.1.4+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c" +checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" dependencies = [ "indexmap", "serde_core", @@ -946,9 +969,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.1.2+spec-1.1.0" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" dependencies = [ "winnow 1.0.4", ] @@ -984,7 +1007,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -1115,9 +1138,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.28" +version = "0.8.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" +checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7" [[package]] name = "zmij" diff --git a/Cargo.toml b/Cargo.toml index 89eaf46..c93d5c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "breadhelp" -version = "0.2.4" +version = "0.2.6" edition = "2021" [dependencies] @@ -10,7 +10,7 @@ gtk4-layer-shell = "0.8" glib = "0.22" # Shared ecosystem theming — same generated stylesheet bos-settings/breadbar/ # breadbox/breadpad load, so this looks like part of the same desktop. -bread-theme = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.7.2", features = ["gtk"] } +bread-theme = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.7.4", features = ["gtk"] } serde = { version = "1", features = ["derive"] } serde_json = "1" toml = "0.8" diff --git a/ci/build.sh b/ci/build.sh index 668b199..63262e8 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -12,8 +12,8 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" REV="$(cat "${ROOT}/ci/bread-ecosystem.rev")" CACHE_DIR="/tmp/bread-ecosystem-ci-${REV}" -if [ ! -d "$CACHE_DIR" ]; then - rm -rf /tmp/bread-ecosystem-ci-* +if [ ! -f "$CACHE_DIR/ci/build.sh" ]; then + rm -rf "$CACHE_DIR" git clone https://git.breadway.dev/Breadway/bread-ecosystem.git "$CACHE_DIR" git -C "$CACHE_DIR" checkout --quiet "$REV" fi diff --git a/content/daily-use/01-searching-your-files/content.md b/content/daily-use/01-searching-your-files/content.md index b0ee950..2dad088 100644 --- a/content/daily-use/01-searching-your-files/content.md +++ b/content/daily-use/01-searching-your-files/content.md @@ -4,6 +4,6 @@ breadsearch indexes your files so you can find things instantly, without digging through folders. - Open it from BOS Settings, or run it directly. -- Type a few letters of a filename — results update as you type. +- Describe what you are looking for in plain language — breadsearch ranks files by meaning, not by letters in a filename. Results update as you type. - [Run]breadsearch|Open File Search[/Run] diff --git a/content/getting-started/02-essential-keybinds/content.md b/content/getting-started/02-essential-keybinds/content.md index 7063367..132bd70 100644 --- a/content/getting-started/02-essential-keybinds/content.md +++ b/content/getting-started/02-essential-keybinds/content.md @@ -15,7 +15,8 @@ nothing here is mandatory either, click around if you'd rather. - [Show Keybind]super + space[/Show Keybind] opens the launcher (breadbox) - [Show Keybind]super + e[/Show Keybind] opens files (nautilus) - [Show Keybind]super + b[/Show Keybind] opens the browser -- [Show Keybind]super + u[/Show Keybind] opens notes +- [Show Keybind]super + u[/Show Keybind] opens notes (breadpad) +- [Show Keybind]super + ,[/Show Keybind] opens BOS Settings - [Show Keybind]super + l[/Show Keybind] locks the screen ## Screenshots diff --git a/src/content/meta.rs b/src/content/meta.rs index 905ce02..364ca0a 100644 --- a/src/content/meta.rs +++ b/src/content/meta.rs @@ -12,14 +12,23 @@ pub enum Difficulty { #[derive(serde::Deserialize, Clone, Default)] pub struct GuideMeta { pub title: String, + /// Not read by any UI yet — reserved for a future difficulty badge. + /// Real content already sets it, so kept rather than dropped. + #[allow(dead_code)] #[serde(default)] pub difficulty: Difficulty, #[serde(default)] pub tags: Vec, /// Guide dir-names in the same or another category. Unresolvable entries /// are silently dropped when rendering "related guides" — never a crash. + /// Not read by any UI yet — the "related guides" render path doesn't + /// exist. Real content already sets it, so kept rather than dropped. + #[allow(dead_code)] #[serde(default)] pub related: Vec, + /// Not read by any UI yet — reserved for a future "N min read" hint. + /// Real content already sets it, so kept rather than dropped. + #[allow(dead_code)] #[serde(default)] pub estimated_minutes: u32, /// Overrides the parent directory name as the guide's category, if set. diff --git a/src/content/tour.rs b/src/content/tour.rs index 9bda162..6bee9af 100644 --- a/src/content/tour.rs +++ b/src/content/tour.rs @@ -29,6 +29,10 @@ pub enum Success { #[derive(serde::Deserialize, Clone)] pub struct Step { + /// Not read by any Rust code yet — steps are matched by index, not id. + /// Real tour content already sets it (content authors use it to keep + /// track of steps), so kept rather than dropped. + #[allow(dead_code)] pub id: String, pub title: String, pub body: String, diff --git a/src/content/troubleshoot.rs b/src/content/troubleshoot.rs index 7a39da4..948826e 100644 --- a/src/content/troubleshoot.rs +++ b/src/content/troubleshoot.rs @@ -15,6 +15,11 @@ pub struct SymptomOption { pub struct Fix { pub description: String, pub command: String, + /// Not read by `ui::troubleshoot_wizard` yet — the "Run fix" button + /// currently executes unconditionally regardless of this flag. Real + /// symptom content already sets it, so kept rather than dropped; the + /// wizard should gate on it before this is treated as safe. + #[allow(dead_code)] #[serde(default)] pub requires_confirm: bool, } diff --git a/src/services/hyprland.rs b/src/services/hyprland.rs index 4e570fc..ab3bd3e 100644 --- a/src/services/hyprland.rs +++ b/src/services/hyprland.rs @@ -28,10 +28,6 @@ pub struct Client { pub struct Monitor { pub id: i32, pub name: String, - pub x: i32, - pub y: i32, - pub width: i32, - pub height: i32, pub focused: bool, } diff --git a/src/theme.rs b/src/theme.rs index d72f017..89cebf1 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -81,3 +81,8 @@ pub fn load(_display: >k4::gdk::Display) { bread_theme::gtk::apply_shared(); APP_PROVIDER.with(|cell| bread_theme::gtk::apply_css(APP_CSS, cell)); } + +pub fn bind_window(window: &impl gtk4::prelude::IsA) { + bread_theme::gtk::bind_window_auto_with_app_css(window, |_| APP_CSS.to_string()); +} + diff --git a/src/ui/tour/callout.rs b/src/ui/tour/callout.rs index 4943824..8baf553 100644 --- a/src/ui/tour/callout.rs +++ b/src/ui/tour/callout.rs @@ -49,6 +49,7 @@ pub fn build( window.set_layer(Layer::Overlay); window.set_keyboard_mode(KeyboardMode::OnDemand); window.set_monitor(Some(monitor)); + crate::theme::bind_window(&window); if let Some(rect) = rect { let (mon_w, mon_h) = monitor_size; diff --git a/src/ui/tour/mask.rs b/src/ui/tour/mask.rs index 8ae8059..e26c9da 100644 --- a/src/ui/tour/mask.rs +++ b/src/ui/tour/mask.rs @@ -20,6 +20,7 @@ fn new_mask_window(monitor: &gdk4::Monitor) -> Window { window.set_layer(Layer::Overlay); window.set_keyboard_mode(KeyboardMode::None); window.set_monitor(Some(monitor)); + crate::theme::bind_window(&window); let dim = GBox::new(gtk4::Orientation::Vertical, 0); dim.add_css_class("tour-mask"); dim.set_hexpand(true); diff --git a/src/ui/tour/mod.rs b/src/ui/tour/mod.rs index 8112a9d..7404e81 100644 --- a/src/ui/tour/mod.rs +++ b/src/ui/tour/mod.rs @@ -110,7 +110,7 @@ pub fn self_heal() { pub fn on_tour_event(id: &str) { let hit = STATE.with(|cell| { let mut borrow = cell.borrow_mut(); - let Some(state) = borrow.as_mut() else { return None }; + let state = borrow.as_mut()?; // Only a *visibly* confirmed step blocks a re-fire. `confirmed` gets // set below, before `render_step` runs, so that render actually // paints the "done" state instead of the stale pre-confirmation one diff --git a/src/ui/troubleshoot_wizard.rs b/src/ui/troubleshoot_wizard.rs index c012835..a7565d4 100644 --- a/src/ui/troubleshoot_wizard.rs +++ b/src/ui/troubleshoot_wizard.rs @@ -38,6 +38,7 @@ pub fn open(parent: &impl IsA, on_build: impl FnOnce(&Window)) { .default_height(360) .build(); window.add_css_class("wizard-dialog"); + crate::theme::bind_window(&window); let header = gtk4::HeaderBar::new(); header.set_show_title_buttons(true); window.set_titlebar(Some(&header)); diff --git a/src/ui/window.rs b/src/ui/window.rs index 89c3518..866b63d 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -30,13 +30,33 @@ thread_local! { /// over D-Bus to this primary instance by a second `breadhelp` launch — so /// it must build the window at most once and reuse it thereafter. pub fn present(app: &Application, action: Action) { + // Crash-recover keybinds even if this invocation never builds a window + // (silent every-login autostart). + tour::self_heal(); + + // Once onboarding is done, autostart only needs a warm process so + // Super+/ is instant. GTK/theme/font load is most of that cost and is + // paid by staying resident (~14 MiB PSS, no window). Building tabs + // adds ~2 MiB of dead weight for a session that may never open help. + let is_bare_silent_autostart = action.autostart + && action.screenshot.is_none() + && !action.force_onboard + && action.tour_event.is_none() + && action.suggest.is_none() + && State::load().onboarding_completed(); + if is_bare_silent_autostart { + // No window means nothing holds GApplication open. Forget the hold + // guard so the primary instance lives for the session; logout is + // what ends it. Without this, the next Super+/ would cold-start. + std::mem::forget(app.hold()); + return; + } + HANDLE.with(|cell| { - let mut just_built = false; { let mut cell_ref = cell.borrow_mut(); if cell_ref.is_none() { *cell_ref = Some(build(app)); - just_built = true; } } let cell_ref = cell.borrow(); @@ -62,19 +82,14 @@ pub fn present(app: &Application, action: Action) { if let Some(s) = crate::services::breadd::resolve(id) { handle.home.set_suggestion(Some(&s.text)); } - // Only focus the window the first time this process builds it - // (i.e. breadhelp wasn't already running) — a background daemon - // event shouldn't steal focus from whatever the user is doing. - if just_built { - show_window(&handle.window, action.autostart); - } + // Background daemon event — never steal focus. A `--suggest` + // can now be the first invocation of the session because + // silent autostart no longer builds a window. return; } - // Every-login autostart builds the window (so the app is ready to - // respond to SUPER+/ instantly) but only shows UI on a genuine - // first run — never on later logins. First run is now the in-window - // day-zero wizard; the live tour starts when that finishes. + // Bare silent autostart (onboarding done) already returned above. + // Autostart that reaches here is a genuine first run. let onboarded = State::load().onboarding_completed(); if action.autostart && onboarded { return; @@ -131,6 +146,7 @@ fn build(app: &Application) -> Handle { .build(); crate::theme::load(&WidgetExt::display(&window)); + crate::theme::bind_window(&window); let store = Rc::new(ContentStore::load()); let binds = Rc::new(keybinds::load());