Fix all issues from code/UX review
ISO structural:
- Move post-install.sh → airootfs/etc/calamares/ (it was never in the squashfs)
- Create airootfs/etc/skel/.config/ with all dotfiles (deploy path now works)
- Add iso/pacman.conf with [breadway] custom repo stub for calamares + bakery
- Add Calamares branding component (bos/branding.desc + show.qml)
- Add missing unpackfs.conf and mount.conf modules
- Add live-session autostart: getty autologin → bash_profile → Hyprland → calamares
- Add polkit rule for wheel-group snapper rollback (pkexec path)
- Remove wlroots from packages (bundled with Hyprland); add bakery to package list
- Fix modules-search path in settings.conf
Dotfiles:
- Rename dotfiles/hyprland/ → dotfiles/hypr/ (Hyprland reads ~/.config/hypr/)
- Fix deprecated shadow options: drop_shadow/shadow_range → shadow { } block
bos-settings Rust:
- Replace glib::MainContext::channel (removed in glib 0.19) with async_channel
- Stream bakery update output line-by-line instead of buffering all at once
- Fix zombie processes: per-package update buttons now wait() in a thread
- Fix sidebar/stack mismatch at startup: select snapshots row to match default view
- Replace deprecated MessageDialog with AlertDialog (GTK 4.10+) throughout
- Use pkexec for snapper rollback so polkit handles privilege escalation
- Add confirmation dialog before delete snapshot (was missing, rollback had one)
- Add refresh button + repopulate after delete in snapshots view
- Add "Saved" / "Error: …" status label to every config view save button
- Add "Remove" buttons to breadbox contexts and breadcrumbs profiles
- Remove hardcoded model string from breadpad defaults
- Drop unused state mod; fix config_dir HOME fallback; fix zombie in editor launches
https://claude.ai/code/session_01WszGHvCmxgcyTwNSkfLF9P
This commit is contained in:
parent
0ff3998c84
commit
d5913da277
32 changed files with 720 additions and 288 deletions
|
|
@ -14,34 +14,22 @@ pub struct BreadConfig {
|
|||
pub adapters: AdaptersConfig,
|
||||
}
|
||||
|
||||
fn default_log_level() -> String {
|
||||
"info".to_string()
|
||||
}
|
||||
fn default_log_level() -> String { "info".to_string() }
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Default)]
|
||||
pub struct AdaptersConfig {
|
||||
#[serde(default = "default_true")]
|
||||
pub keyboard: bool,
|
||||
#[serde(default = "default_true")]
|
||||
pub mouse: bool,
|
||||
#[serde(default = "default_true")]
|
||||
pub touchpad: bool,
|
||||
#[serde(default = "default_true")]
|
||||
pub bluetooth: bool,
|
||||
#[serde(default = "default_true")]
|
||||
pub gamepad: bool,
|
||||
#[serde(default = "default_true")] pub keyboard: bool,
|
||||
#[serde(default = "default_true")] pub mouse: bool,
|
||||
#[serde(default = "default_true")] pub touchpad: bool,
|
||||
#[serde(default = "default_true")] pub bluetooth: bool,
|
||||
#[serde(default = "default_true")] pub gamepad: bool,
|
||||
}
|
||||
|
||||
fn default_true() -> bool {
|
||||
true
|
||||
}
|
||||
fn default_true() -> bool { true }
|
||||
|
||||
impl Default for BreadConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
log_level: default_log_level(),
|
||||
adapters: AdaptersConfig::default(),
|
||||
}
|
||||
Self { log_level: default_log_level(), adapters: AdaptersConfig::default() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +37,12 @@ fn config_path() -> std::path::PathBuf {
|
|||
config::config_dir().join("bread/breadd.toml")
|
||||
}
|
||||
|
||||
fn adapter_row(label: &str, active: bool, cfg: Rc<RefCell<BreadConfig>>, field: &'static str) -> GBox {
|
||||
fn adapter_row(
|
||||
label: &str,
|
||||
active: bool,
|
||||
cfg: Rc<RefCell<BreadConfig>>,
|
||||
field: &'static str,
|
||||
) -> GBox {
|
||||
let row = GBox::new(Orientation::Horizontal, 16);
|
||||
let lbl = Label::new(Some(label));
|
||||
lbl.set_hexpand(true);
|
||||
|
|
@ -60,11 +53,11 @@ fn adapter_row(label: &str, active: bool, cfg: Rc<RefCell<BreadConfig>>, field:
|
|||
let val = s.is_active();
|
||||
let mut c = cfg.borrow_mut();
|
||||
match field {
|
||||
"keyboard" => c.adapters.keyboard = val,
|
||||
"mouse" => c.adapters.mouse = val,
|
||||
"touchpad" => c.adapters.touchpad = val,
|
||||
"bluetooth" => c.adapters.bluetooth = val,
|
||||
"gamepad" => c.adapters.gamepad = val,
|
||||
"keyboard" => c.adapters.keyboard = val,
|
||||
"mouse" => c.adapters.mouse = val,
|
||||
"touchpad" => c.adapters.touchpad = val,
|
||||
"bluetooth" => c.adapters.bluetooth = val,
|
||||
"gamepad" => c.adapters.gamepad = val,
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
|
|
@ -94,15 +87,10 @@ pub fn build() -> GBox {
|
|||
lbl.set_xalign(0.0);
|
||||
let levels = StringList::new(&["error", "warn", "info", "debug", "trace"]);
|
||||
let dropdown = DropDown::new(Some(levels), gtk4::Expression::NONE);
|
||||
let current_pos = match cfg.borrow().log_level.as_str() {
|
||||
"error" => 0u32,
|
||||
"warn" => 1,
|
||||
"info" => 2,
|
||||
"debug" => 3,
|
||||
"trace" => 4,
|
||||
_ => 2,
|
||||
let pos = match cfg.borrow().log_level.as_str() {
|
||||
"error" => 0u32, "warn" => 1, "info" => 2, "debug" => 3, "trace" => 4, _ => 2,
|
||||
};
|
||||
dropdown.set_selected(current_pos);
|
||||
dropdown.set_selected(pos);
|
||||
{
|
||||
let cfg = cfg.clone();
|
||||
dropdown.connect_selected_notify(move |dd| {
|
||||
|
|
@ -116,7 +104,6 @@ pub fn build() -> GBox {
|
|||
row.append(&dropdown);
|
||||
vbox.append(&row);
|
||||
|
||||
// Adapter toggles
|
||||
let adapter_label = Label::new(Some("Adapters"));
|
||||
adapter_label.set_xalign(0.0);
|
||||
adapter_label.set_margin_top(8);
|
||||
|
|
@ -125,25 +112,44 @@ pub fn build() -> GBox {
|
|||
|
||||
let (kbd, mouse, touchpad, bluetooth, gamepad) = {
|
||||
let c = cfg.borrow();
|
||||
(c.adapters.keyboard, c.adapters.mouse, c.adapters.touchpad, c.adapters.bluetooth, c.adapters.gamepad)
|
||||
(c.adapters.keyboard, c.adapters.mouse, c.adapters.touchpad,
|
||||
c.adapters.bluetooth, c.adapters.gamepad)
|
||||
};
|
||||
|
||||
vbox.append(&adapter_row("Keyboard", kbd, cfg.clone(), "keyboard"));
|
||||
vbox.append(&adapter_row("Mouse", mouse, cfg.clone(), "mouse"));
|
||||
vbox.append(&adapter_row("Touchpad", touchpad, cfg.clone(), "touchpad"));
|
||||
vbox.append(&adapter_row("Keyboard", kbd, cfg.clone(), "keyboard"));
|
||||
vbox.append(&adapter_row("Mouse", mouse, cfg.clone(), "mouse"));
|
||||
vbox.append(&adapter_row("Touchpad", touchpad, cfg.clone(), "touchpad"));
|
||||
vbox.append(&adapter_row("Bluetooth", bluetooth, cfg.clone(), "bluetooth"));
|
||||
vbox.append(&adapter_row("Gamepad", gamepad, cfg.clone(), "gamepad"));
|
||||
vbox.append(&adapter_row("Gamepad", gamepad, cfg.clone(), "gamepad"));
|
||||
|
||||
let btn_row = GBox::new(Orientation::Horizontal, 12);
|
||||
btn_row.set_margin_top(16);
|
||||
|
||||
let save_btn = Button::with_label("Save");
|
||||
save_btn.set_margin_top(16);
|
||||
save_btn.set_halign(gtk4::Align::Start);
|
||||
let status_lbl = Label::new(None);
|
||||
status_lbl.add_css_class("dim-label");
|
||||
|
||||
{
|
||||
let cfg = cfg.clone();
|
||||
let path = path.clone();
|
||||
let status_lbl = status_lbl.clone();
|
||||
save_btn.connect_clicked(move |_| {
|
||||
let _ = config::save(&path, &*cfg.borrow());
|
||||
match config::save(&path, &*cfg.borrow()) {
|
||||
Ok(()) => {
|
||||
status_lbl.set_text("Saved");
|
||||
let lbl = status_lbl.clone();
|
||||
glib::timeout_add_seconds_local(3, move || {
|
||||
lbl.set_text("");
|
||||
glib::ControlFlow::Break
|
||||
});
|
||||
}
|
||||
Err(e) => status_lbl.set_text(&format!("Error: {e}")),
|
||||
}
|
||||
});
|
||||
}
|
||||
vbox.append(&save_btn);
|
||||
|
||||
btn_row.append(&save_btn);
|
||||
btn_row.append(&status_lbl);
|
||||
vbox.append(&btn_row);
|
||||
|
||||
vbox
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue