diff --git a/BREAD_DESIGN_SYSTEM.md b/BREAD_DESIGN_SYSTEM.md deleted file mode 100644 index 942f7a2..0000000 --- a/BREAD_DESIGN_SYSTEM.md +++ /dev/null @@ -1,118 +0,0 @@ -# Bread Design System - -Unified visual identity for breadbar, breadbox, breadpad/breadman, and -bos-settings. - -## Architecture (single source of truth) - -The tokens below are implemented once in the **`bread-theme`** crate as -`stylesheet(&Palette)` — the full component stylesheet (buttons, entries, -switches, lists/rows/sidebars, cards, chips, scrollbars, headings) over a -canonical `@define-color` palette (`surface`=color0, `overlay`=color7, -`accent`=color4). - -- The `bread-theme` **CLI** renders it from the live pywal palette to - `$XDG_RUNTIME_DIR/bread/theme.css` (run at login and from a pywal hook). -- Every GUI loads that file via `bread_theme::gtk::apply_shared()` and - **live-reloads** it, then layers on only its own app-specific rules. - -Result: one definition, no per-app drift, and palette changes recolour the -whole desktop with no rebuilds. Apps reference the shared `@define-color` -names rather than raw palette slots. - -## Typography - -- **Font Family**: Varela Round, sans-serif -- **Base Size**: 14px -- **Secondary**: 12px (metadata, helper text, secondary labels) -- **Font Weight**: Normal (400) for body, Bold (700) for emphasis - -## Spacing Scale (4px units) - -Use these values consistently across all projects: - -- **xs**: 4px (small gaps, internal padding) -- **sm**: 8px (default spacing between elements) -- **md**: 12px (medium spacing, main padding) -- **lg**: 16px (large padding, major spacing) -- **xl**: 20px (extra large spacing, section breaks) - -## Border Radius - -Establish a visual hierarchy with consistent rounding: - -- **Primary** (buttons, cards, main containers): **8px** -- **Secondary** (input fields, chips, entries): **6px** -- **Tertiary** (small interactive elements): **4px** -- **Pill** (fully rounded buttons, badges): **999px** - -## Color System - -All projects use **pywal dynamic theming** with **Catppuccin Mocha** as the fallback palette: - -- **Background**: `#1e1e2e` (Catppuccin) -- **Foreground**: `#cdd6f4` (Catppuccin) -- **Surface**: `#181825` (Catppuccin) -- **Accent**: Dynamic (from pywal) - -Color palette slots (via wal): -- color0–color7: ANSI colors -- Semantic: red, green, yellow, blue, pink, teal - -## Component Standards - -### Buttons -- Border Radius: 8px -- Padding: 8px 16px (primary), 4px 8px (secondary) -- Font Size: 14px -- Background: Theme accent color - -### Input Fields -- Border Radius: 6px -- Padding: 12px 16px -- Font Size: 14px -- Border: 1px or 2px solid (blue on focus) - -### Cards -- Border Radius: 8px -- Padding: 12px -- Margin: 8px -- Box Shadow: Optional, for depth - -### Stat Labels -- Font Size: 14px -- Margin Right (between icon/text): 5px -- Group Margin Right: 12px - -### Notification Cards -- Border Radius: 8px -- Padding: 12px -- Margin Bottom: 8px -- Font Size: 14px (summary), 12px (body) - -## Current Implementation - -All GUI apps load `bread_theme::stylesheet` (via the generated shared file) and -add only app-specific rules: - -- **breadbar** — shared base + bar window, workspace buttons, stats, notification - and OSD cards. -- **breadbox** — shared base + launcher panel, search entry, result rows. -- **breadpad / breadman** — shared base + capture popup, type chips, note cards, - reminder window, sidebar rows. -- **bos-settings** — shared base + content padding only (was previously a - hardcoded Nord palette; migrated to the shared stylesheet). -- **breadcrumbs** — CLI tool; ANSI colours only, no GUI styling. - -> Palette note: the fallback is Catppuccin Mocha, but installs (e.g. BOS) drive -> the real palette from pywal — BOS ships a black-base palette. - -## Future Consistency Checks - -When adding new components or updating existing ones: -1. Use Varela Round for all text -2. Set base font size to 14px (12px for secondary) -3. Use spacing scale (4px units: 4, 8, 12, 16, 20) -4. Use border radius from this system (8px default, 6px secondary) -5. Leverage pywal colors for dynamic theming -6. Keep margins/padding consistent across similar components diff --git a/README.md b/README.md index 1ec4cff..405c193 100644 --- a/README.md +++ b/README.md @@ -18,36 +18,6 @@ bakery install breadbar | `breadcrumbs` | Profile-aware Wi-Fi state machine with Tailscale exit-node management and a self-healing watch daemon | | `breadpad` | Quick-capture scratchpad popup with AI-powered note classification, reminders, recurrence, and a full note viewer (`breadman`) | -## Recommended keybinds - -The ecosystem assumes a Hyprland setup with `SUPER` as the modifier. The -conventional bindings (used by BOS and recommended for any install): - -| Keys | Action | -|------|--------| -| `SUPER+Space` | `breadbox` — app launcher | -| `SUPER+U` | `breadpad` — quick-capture notes/reminders | -| `SUPER+M` | `breadman` — note viewer / manager | -| `SUPER+,` | settings (`bos-settings`, where installed) | - -`breadbar` and `breadd` are services started at login (`exec-once`), not bound -to keys. - -## Theming - -All GUIs share one look via `bread-theme`. The `bread-theme` CLI renders the -component stylesheet from your pywal palette (Catppuccin Mocha fallback) to -`$XDG_RUNTIME_DIR/bread/theme.css`; every app loads that file and **live-reloads** -it, so changing your wallpaper recolours the whole ecosystem with no rebuilds: - -```sh -wal -i ~/Pictures/wall.png # regenerate pywal palette -bread-theme generate # render the shared stylesheet (run from a wal hook) -``` - -See [`BREAD_DESIGN_SYSTEM.md`](BREAD_DESIGN_SYSTEM.md) for the tokens (fonts, -spacing, radii, colour roles) the stylesheet is built from. - ## Installing bakery `bakery` is the package manager for the ecosystem. Install it with the bootstrap script: diff --git a/bread-theme/Cargo.toml b/bread-theme/Cargo.toml index 8dc41e7..39930a1 100644 --- a/bread-theme/Cargo.toml +++ b/bread-theme/Cargo.toml @@ -18,9 +18,3 @@ gtk4 = { version = "0.11", features = ["v4_12"], optional = true } # Enable GTK4 CSS provider helpers (breadbar, breadbox, breadpad use this). # bread (daemon) and breadcrumbs (CLI) depend on this crate without the feature. gtk = ["dep:gtk4"] - -# The generator CLI. It only touches the gtk-free lib API (render + write), so -# it builds without the gtk feature and stays light. -[[bin]] -name = "bread-theme" -path = "src/bin/bread-theme.rs" diff --git a/bread-theme/src/bin/bread-theme.rs b/bread-theme/src/bin/bread-theme.rs deleted file mode 100644 index 266ea9c..0000000 --- a/bread-theme/src/bin/bread-theme.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! `bread-theme` — generates the ecosystem's shared GTK stylesheet from the -//! current pywal palette and writes it to the canonical path that every bread -//! GUI loads. Run it at session start, and again after the wallpaper/palette -//! changes (e.g. from a pywal hook); apps watch the file and recolour live. -//! -//! bread-theme # same as `generate` -//! bread-theme generate # render + write the shared stylesheet -//! bread-theme reload # re-render from the current pywal palette and -//! # signal every running bread GUI to recolour -//! bread-theme path # print the stylesheet path -//! bread-theme print # render to stdout (no write) - -use std::process::ExitCode; - -fn write_and_report(verb: &str) -> ExitCode { - match bread_theme::write_shared_css() { - Ok(path) => { - eprintln!("bread-theme: {verb} {}", path.display()); - ExitCode::SUCCESS - } - Err(e) => { - eprintln!("bread-theme: failed to write stylesheet: {e}"); - ExitCode::FAILURE - } - } -} - -fn main() -> ExitCode { - let cmd = std::env::args().nth(1).unwrap_or_else(|| "generate".into()); - match cmd.as_str() { - "path" => { - println!("{}", bread_theme::shared_css_path().display()); - ExitCode::SUCCESS - } - "print" => { - print!("{}", bread_theme::render()); - ExitCode::SUCCESS - } - "generate" => write_and_report("wrote"), - // `reload` is `generate` from the caller's view, but it's the verb to use - // after changing pywal colours: rewriting the file (atomic rename) trips - // the file monitor in every running bread GUI, so they all re-read the - // palette and recolour live — shared widgets *and* each app's own rules. - "reload" => write_and_report("reloaded"), - "-h" | "--help" | "help" => { - eprintln!( - "bread-theme — shared stylesheet generator\n\n\ - USAGE:\n bread-theme [generate|reload|path|print]\n\n\ - generate render the pywal palette to the shared stylesheet (default)\n\ - reload re-render and signal running bread GUIs to recolour live\n\ - path print the stylesheet path ({})\n\ - print render to stdout without writing", - bread_theme::shared_css_path().display() - ); - ExitCode::SUCCESS - } - other => { - eprintln!("bread-theme: unknown command '{other}' (try generate|reload|path|print)"); - ExitCode::FAILURE - } - } -} diff --git a/bread-theme/src/gtk.rs b/bread-theme/src/gtk.rs index aab7d01..6e62cb4 100644 --- a/bread-theme/src/gtk.rs +++ b/bread-theme/src/gtk.rs @@ -1,100 +1,7 @@ -use gtk4::gio; -use gtk4::prelude::*; use gtk4::CssProvider; use std::cell::RefCell; use std::path::Path; -thread_local! { - static SHARED_PROVIDER: RefCell> = const { RefCell::new(None) }; - static SHARED_MONITOR: RefCell> = const { RefCell::new(None) }; - static APP_PROVIDER: RefCell> = const { RefCell::new(None) }; - static APP_MONITOR: RefCell> = const { RefCell::new(None) }; - #[allow(clippy::type_complexity)] - static APP_BUILDER: RefCell String>>> = const { RefCell::new(None) }; -} - -fn reload_shared() { - let css = std::fs::read_to_string(crate::shared_css_path()) - .unwrap_or_else(|_| crate::render()); - SHARED_PROVIDER.with(|cell| apply_css(&css, cell)); -} - -fn reload_app() { - let css = APP_BUILDER.with(|b| b.borrow().as_ref().map(|f| f())); - if let Some(css) = css { - APP_PROVIDER.with(|cell| apply_css(&css, cell)); - } -} - -/// Watch the shared stylesheet for changes and run `reload` when it's rewritten. -/// -/// `bread-theme` writes the file with write-tmp-then-rename (atomic), which -/// *replaces the inode*. A monitor on the file itself dies after the first -/// replace (inotify reports DELETE_SELF and never re-arms), so we monitor the -/// parent *directory* and filter for the stylesheet's filename — that fires -/// reliably on every reload. Returns the monitor (keep it alive to stay armed). -fn watch_theme_file(reload: fn()) -> Option { - let target = crate::shared_css_path(); - let dir = target.parent()?; - // The dir must exist to be monitored; `bread-theme generate` makes it at - // login, but create it here too so a GUI started first still arms the watch. - let _ = std::fs::create_dir_all(dir); - let monitor = gio::File::for_path(dir) - .monitor_directory(gio::FileMonitorFlags::WATCH_MOVES, gio::Cancellable::NONE) - .ok()?; - monitor.connect_changed(move |_, file, other, _event| { - // The rename lands as an event whose file (or move destination) is the - // stylesheet. Match either to catch both CREATED/CHANGED and MOVED_IN. - let is_target = |f: &gio::File| f.path().as_deref() == Some(target.as_path()); - if is_target(file) || other.is_some_and(is_target) { - reload(); - } - }); - Some(monitor) -} - -/// Apply an app's *own* stylesheet and keep it live across palette changes. -/// -/// `build` is called now to produce the app-specific CSS, and again every time -/// the shared theme file is rewritten — i.e. whenever `bread-theme reload` (or -/// `generate`) runs after pywal changes. The app recolours in place, no restart. -/// -/// This is the counterpart to [`apply_shared`]: that hot-reloads the *shared* -/// component sheet; this hot-reloads the app's *own* rules (which are built from -/// the palette, so they'd otherwise be frozen at startup). Apps that build their -/// CSS from [`crate::stylesheet`] themselves can use this alone; apps that layer -/// on top of [`apply_shared`] call both. -/// -/// Call once at startup. The closure should read the current palette -/// ([`crate::load_palette`]) each time so it picks up the new colours. -pub fn apply_app_css String + 'static>(build: F) { - APP_BUILDER.with(|b| *b.borrow_mut() = Some(Box::new(build))); - reload_app(); - APP_MONITOR.with(|cell| { - if cell.borrow().is_some() { - return; - } - *cell.borrow_mut() = watch_theme_file(reload_app); - }); -} - -/// Load the ecosystem's shared stylesheet (the file written by -/// `bread-theme generate`, or a freshly rendered fallback if absent) at -/// APPLICATION priority, and watch the file so the whole UI recolours live when -/// the palette changes — no app rebuild or restart needed. -/// -/// Call once at startup; then add the app's own CSS provider *after* this so -/// app-specific rules win on equal specificity. -pub fn apply_shared() { - reload_shared(); - SHARED_MONITOR.with(|cell| { - if cell.borrow().is_some() { - return; - } - *cell.borrow_mut() = watch_theme_file(reload_shared); - }); -} - /// Apply a CSS string to the default display at APPLICATION priority. /// Re-uses an existing provider if one is passed in (for SIGHUP reloads). pub fn apply_css(css: &str, provider: &RefCell>) { diff --git a/bread-theme/src/lib.rs b/bread-theme/src/lib.rs index 2ee2307..7d649e8 100644 --- a/bread-theme/src/lib.rs +++ b/bread-theme/src/lib.rs @@ -54,165 +54,6 @@ pub fn css_vars(p: &Palette) -> String { ) } -/// Relative luminance (WCAG, sRGB) of a `#rrggbb` colour, 0.0 (black) – 1.0 (white). -pub fn luminance(hex: &str) -> f32 { - let h = hex.trim_start_matches('#'); - let lin = |i: usize| -> f32 { - let c = u8::from_str_radix(h.get(i..i + 2).unwrap_or("00"), 16).unwrap_or(0) as f32 / 255.0; - if c <= 0.04045 { c / 12.92 } else { ((c + 0.055) / 1.055).powf(2.4) } - }; - 0.2126 * lin(0) + 0.7152 * lin(2) + 0.0722 * lin(4) -} - -/// Pick a legible ink (near-black or near-white) for text drawn on `hex`. -/// 0.179 is the WCAG crossover where contrast against black equals contrast -/// against white — so whichever side we pick always wins. This is what keeps -/// text readable no matter how light or dark pywal makes a given palette slot, -/// without altering the palette colours themselves. -pub fn ink_on(hex: &str) -> &'static str { - if luminance(hex) > 0.179 { "#11111b" } else { "#f5f5f5" } -} - -/// Canonical `@define-color` block: the single naming all bread apps share. -/// `surface` = color0 (darkest surface), `overlay` = color7 (muted), and -/// `accent` = color4. Apps must use these names, not raw palette slots, so the -/// whole ecosystem recolours together. -/// -/// The `on-*` colours are computed ink (black/white) guaranteed to be legible on -/// the matching background — use `@on-surface` for text on a `@surface` panel, -/// `@on-accent` on an `@accent` button, etc. They exist because pywal can emit a -/// light value in any slot, and white text on a light surface disappears. -fn define_colors(p: &Palette) -> String { - format!( - "@define-color bg {bg};\n\ - @define-color fg {fg};\n\ - @define-color surface {c0};\n\ - @define-color overlay {c7};\n\ - @define-color accent {c4};\n\ - @define-color red {c1};\n\ - @define-color green {c2};\n\ - @define-color yellow {c3};\n\ - @define-color blue {c4};\n\ - @define-color pink {c5};\n\ - @define-color teal {c6};\n\ - @define-color on-bg {on_bg};\n\ - @define-color on-surface {on_surface};\n\ - @define-color on-accent {on_accent};\n\ - @define-color on-red {on_red};\n\ - @define-color on-overlay {on_overlay};\n", - bg = p.background, fg = p.foreground, - c0 = p.color0, c1 = p.color1, c2 = p.color2, c3 = p.color3, - c4 = p.color4, c5 = p.color5, c6 = p.color6, c7 = p.color7, - on_bg = ink_on(&p.background), - on_surface = ink_on(&p.color0), - on_accent = ink_on(&p.color4), - on_red = ink_on(&p.color1), - on_overlay = ink_on(&p.color7), - ) -} - -/// The full shared component stylesheet — the single source of truth for how -/// every bread GUI (bos-settings, breadbar, breadbox, breadpad, breadman) styles -/// common widgets. Apps load this, then append only their own *layout* rules. -/// -/// Built entirely from the design tokens (font, spacing, radii) and the -/// `@define-color` palette, so changing the palette recolours every app. -pub fn stylesheet(p: &Palette) -> String { - use tokens::*; - format!( - "{vars}\ - * {{ font-family: '{font}'; font-size: {base}px; }}\n\ - /* Colour is set on containers; labels inherit it, so text on any panel,\ - button, or accent is always the legible ink for that background. Bare\ - `label {{ color }}` is deliberately avoided — as a type selector it\ - would override a container's colour on its own child labels. */\n\ - window {{ background-color: @bg; color: @on-bg; }}\n\ - .dim-label, .dim {{ opacity: 0.6; font-size: {sec}px; }}\n\ - .title {{ font-size: 1.4em; font-weight: bold; }}\n\ - .heading {{ font-weight: bold; opacity: 0.85; }}\n\ - .subtitle {{ opacity: 0.7; font-size: {sec}px; }}\n\ - button {{ background-color: @surface; color: @on-surface; border: none;\ - border-radius: {r1}px; padding: {sm}px {lg}px; }}\n\ - button:hover {{ background-color: alpha(@on-surface, 0.14); }}\n\ - button:active {{ background-color: alpha(@on-surface, 0.20); }}\n\ - button:disabled {{ opacity: 0.5; }}\n\ - button.flat {{ background-color: transparent; color: @on-bg; }}\n\ - button.suggested-action {{ background-color: @accent; color: @on-accent; }}\n\ - button.suggested-action:hover {{ background-color: alpha(@accent, 0.85); }}\n\ - button.destructive-action {{ background-color: @red; color: @on-red; }}\n\ - button.destructive-action:hover {{ background-color: alpha(@red, 0.85); }}\n\ - entry, spinbutton {{ background-color: @surface; color: @on-surface;\ - border: 1px solid @overlay; border-radius: {r2}px;\ - padding: {xs}px {sm}px; caret-color: @on-surface; }}\n\ - entry:focus-within, spinbutton:focus-within {{ border-color: @accent; outline: none; }}\n\ - entry image, spinbutton button {{ color: @on-surface; }}\n\ - dropdown > button {{ background-color: @surface; color: @on-surface; border-radius: {r2}px; }}\n\ - popover > contents {{ background-color: @surface; color: @on-surface; border-radius: {r1}px; }}\n\ - switch {{ background-color: @overlay; border-radius: {pill}px; }}\n\ - switch:checked {{ background-color: @accent; }}\n\ - switch slider {{ background-color: @on-surface; border-radius: {pill}px; }}\n\ - list, listbox {{ background-color: transparent; }}\n\ - row {{ border-radius: {r2}px; }}\n\ - row:selected, list row:selected {{ background-color: @accent; color: @on-accent; }}\n\ - .sidebar {{ background-color: @surface; color: @on-surface; }}\n\ - .sidebar row {{ padding: {sm}px {md}px; }}\n\ - .sidebar row:selected {{ background-color: @accent; color: @on-accent; }}\n\ - .sidebar .section-header {{ padding: {md}px {md}px {xs}px {md}px;\ - font-size: {sec}px; font-weight: bold; opacity: 0.55; }}\n\ - .card {{ background-color: @surface; color: @on-surface; border-radius: {r1}px; padding: {md}px; }}\n\ - .chip, .pill {{ background-color: @overlay; color: @on-overlay; border-radius: {pill}px;\ - padding: {xs}px {md}px; font-size: {sec}px; }}\n\ - .chip.active, .pill.active {{ background-color: @accent; color: @on-accent; }}\n\ - scrollbar {{ background-color: transparent; }}\n\ - scrollbar slider {{ background-color: alpha(@on-bg, 0.25); border-radius: {pill}px;\ - min-width: 6px; min-height: 6px; }}\n\ - scrollbar slider:hover {{ background-color: alpha(@on-bg, 0.45); }}\n\ - textview, .mono {{ font-family: monospace; }}\n\ - textview text {{ background-color: @surface; color: @on-surface; }}\n", - vars = define_colors(p), - font = FONT_FAMILY, - base = FONT_SIZE_BASE, - sec = FONT_SIZE_SECONDARY, - xs = SPACE_XS, sm = SPACE_SM, md = SPACE_MD, lg = SPACE_LG, - r1 = RADIUS_PRIMARY, r2 = RADIUS_SECONDARY, pill = RADIUS_PILL, - ) -} - -/// Render the shared stylesheet for the current (pywal) palette. Used by the -/// `bread-theme` generator and as the in-app fallback when the generated file -/// isn't present yet. -pub fn render() -> String { - stylesheet(&load_palette()) -} - -/// Canonical path of the generated shared stylesheet. Apps load it; the -/// `bread-theme generate` CLI writes it. Per-session under `XDG_RUNTIME_DIR`, -/// falling back to the cache dir. -pub fn shared_css_path() -> std::path::PathBuf { - if let Ok(rt) = std::env::var("XDG_RUNTIME_DIR") { - if !rt.is_empty() { - return std::path::PathBuf::from(rt).join("bread").join("theme.css"); - } - } - dirs::cache_dir() - .unwrap_or_else(|| std::path::PathBuf::from("/tmp")) - .join("bread") - .join("theme.css") -} - -/// Write the shared stylesheet to [`shared_css_path`] (atomic rename). Returns -/// the path written. Used by the `bread-theme` CLI. -pub fn write_shared_css() -> std::io::Result { - let path = shared_css_path(); - if let Some(parent) = path.parent() { - std::fs::create_dir_all(parent)?; - } - let tmp = path.with_extension("css.tmp"); - std::fs::write(&tmp, render())?; - std::fs::rename(&tmp, &path)?; - Ok(path) -} - /// Convert a `#rrggbb` hex colour to `rgba(r, g, b, alpha)`. pub fn hex_to_rgba(hex: &str, alpha: f32) -> String { let h = hex.trim_start_matches('#'); @@ -241,66 +82,6 @@ mod tests { assert!(css.contains("14px")); } - #[test] - fn stylesheet_defines_canonical_colors_and_components() { - let css = stylesheet(&Palette::default()); - for name in &["bg", "fg", "surface", "overlay", "accent", "red", "blue"] { - assert!(css.contains(&format!("@define-color {name} ")), "missing @define-color {name}"); - } - // a representative spread of the shared component selectors - for sel in &["button", "entry", "switch:checked", ".card", ".sidebar", "scrollbar slider", ".title"] { - assert!(css.contains(sel), "stylesheet missing selector: {sel}"); - } - assert!(css.contains("Varela Round")); - } - - #[test] - fn luminance_black_and_white_are_extremes() { - assert!(luminance("#000000") < 0.01); - assert!(luminance("#ffffff") > 0.99); - } - - #[test] - fn ink_on_picks_dark_text_for_light_backgrounds() { - // Light pywal slots (the case that made white text vanish) get dark ink. - assert_eq!(ink_on("#ffffff"), "#11111b"); - assert_eq!(ink_on("#f9e2af"), "#11111b"); // pale yellow - assert_eq!(ink_on("#a6e3a1"), "#11111b"); // pale green - } - - #[test] - fn ink_on_picks_light_text_for_dark_backgrounds() { - assert_eq!(ink_on("#000000"), "#f5f5f5"); - assert_eq!(ink_on("#1e1e2e"), "#f5f5f5"); // catppuccin base - } - - #[test] - fn stylesheet_defines_on_colors() { - let css = stylesheet(&Palette::default()); - for name in &["on-bg", "on-surface", "on-accent", "on-red", "on-overlay"] { - assert!(css.contains(&format!("@define-color {name} ")), "missing @define-color {name}"); - } - } - - #[test] - fn stylesheet_has_no_blanket_label_color_rule() { - // A bare `label { color: ... }` would override container colours on child - // labels — the bug that made coloured-background text illegible. - let css = stylesheet(&Palette::default()); - assert!(!css.contains("label { color:"), "blanket label colour rule reintroduced"); - } - - #[test] - fn shared_css_path_uses_runtime_dir() { - std::env::set_var("XDG_RUNTIME_DIR", "/run/user/1234"); - assert_eq!(shared_css_path(), std::path::PathBuf::from("/run/user/1234/bread/theme.css")); - } - - #[test] - fn render_is_nonempty_css() { - assert!(render().contains("@define-color bg ")); - } - #[test] fn hex_to_rgba_known_value() { assert_eq!(hex_to_rgba("#1e1e2e", 1.0), "rgba(30, 30, 46, 1)"); diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index 793c187..b6078f3 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -10,7 +10,7 @@ license=('MIT') # Some Rust deps (ring/mlua) build vendored C/asm into static archives; makepkg's # default -flto=auto emits GCC LTO bitcode the Rust (lld) link cannot read, # causing undefined-symbol errors. Disable LTO. -options=(!lto !debug) +options=(!lto) depends=('glibc' 'gcc-libs') makedepends=('rust' 'cargo') source=("${pkgname}-${pkgver}.tar.gz") diff --git a/registry/bread-ecosystem.toml b/registry/bread-ecosystem.toml index 96887cb..530f938 100644 --- a/registry/bread-ecosystem.toml +++ b/registry/bread-ecosystem.toml @@ -36,8 +36,3 @@ description = "Profile-aware Wi-Fi state machine with Tailscale integration" name = "breadpad" repo = "Breadway/breadpad" description = "Quick-capture scratchpad and note viewer with AI classification" - -[[products]] -name = "breadpaper" -repo = "Breadway/breadpaper" -description = "Wallpaper manager for the bread desktop"