diff --git a/CHANGELOG.md b/CHANGELOG.md index 520f630..da9476c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -Nothing is released yet. See -[ROADMAP.md](https://github.com/onyks-os/USBGuardGUI/blob/main/ROADMAP.md) for the phase order. +## [0.1.0] - 2026-09-27 + +The first release. ### Added @@ -64,12 +65,5 @@ Nothing is released yet. See - `docs/architecture.md`: `listRules` takes a label filter, not a query — `""` lists every rule, `"match"` would have listed none. Found by introspection before any code depended on it. -### Deprecated - -### Removed - -### Fixed - -### Security - -[Unreleased]: https://github.com/onyks-os/USBGuardGUI/commits/main +[Unreleased]: https://github.com/onyks-os/USBGuardGUI/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/onyks-os/USBGuardGUI/releases/tag/v0.1.0 diff --git a/README.md b/README.md index 19bc690..ac7da93 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ SPDX-License-Identifier: MIT

- USBGuard GUI + USBGuardGUI

@@ -38,6 +38,10 @@ SPDX-License-Identifier: MIT Plug in a device, see it appear as **blocked**, allow it for this session with one click — and when something does not work, be told *exactly* which layer refused and what to run to fix it. +

+ The device list: every connected device, its state, and Allow, Block, and Reject buttons +

+ > [!NOTE] > USBGuardGUI is a front end. The protection comes from the **USBGuard daemon**, which decides what > the kernel lets through; this program only asks it, with your authorization, to change its mind. diff --git a/data/io.github.onyks_os.UsbguardGui.metainfo.xml b/data/io.github.onyks_os.UsbguardGui.metainfo.xml index 79a1f79..94a3444 100644 --- a/data/io.github.onyks_os.UsbguardGui.metainfo.xml +++ b/data/io.github.onyks_os.UsbguardGui.metainfo.xml @@ -69,13 +69,40 @@ keyboard touch + + + Every connected device and whether it is authorized + Ogni dispositivo collegato e se è autorizzato + https://raw.githubusercontent.com/onyks-os/USBGuardGUI/v0.1.0/data/screenshots/01-devices.png + + + Allow, block, or reject a device, for this session or permanently + Consenti, blocca o rifiuta un dispositivo, per questa sessione o permanentemente + https://raw.githubusercontent.com/onyks-os/USBGuardGUI/v0.1.0/data/screenshots/02-device-action.png + + + The policy rules in the order USBGuard evaluates them + Le regole della policy nell’ordine in cui USBGuard le valuta + https://raw.githubusercontent.com/onyks-os/USBGuardGUI/v0.1.0/data/screenshots/03-policy.png + + + A guided editor for new rules + Un editor guidato per le nuove regole + https://raw.githubusercontent.com/onyks-os/USBGuardGUI/v0.1.0/data/screenshots/04-new-rule.png + + + Diagnostics that name the exact cause of an access problem + Una diagnostica che indica la causa esatta di un problema di accesso + https://raw.githubusercontent.com/onyks-os/USBGuardGUI/v0.1.0/data/screenshots/05-diagnostics.png + + #8ff0a4 #26a269 - +

First release.

Prima versione.

diff --git a/data/io.github.onyks_os.UsbguardGui.metainfo.xml.in b/data/io.github.onyks_os.UsbguardGui.metainfo.xml.in index ad31e1c..a34be60 100644 --- a/data/io.github.onyks_os.UsbguardGui.metainfo.xml.in +++ b/data/io.github.onyks_os.UsbguardGui.metainfo.xml.in @@ -62,6 +62,29 @@ touch + + + Every connected device and whether it is authorized + https://raw.githubusercontent.com/onyks-os/USBGuardGUI/v0.1.0/data/screenshots/01-devices.png + + + Allow, block, or reject a device, for this session or permanently + https://raw.githubusercontent.com/onyks-os/USBGuardGUI/v0.1.0/data/screenshots/02-device-action.png + + + The policy rules in the order USBGuard evaluates them + https://raw.githubusercontent.com/onyks-os/USBGuardGUI/v0.1.0/data/screenshots/03-policy.png + + + A guided editor for new rules + https://raw.githubusercontent.com/onyks-os/USBGuardGUI/v0.1.0/data/screenshots/04-new-rule.png + + + Diagnostics that name the exact cause of an access problem + https://raw.githubusercontent.com/onyks-os/USBGuardGUI/v0.1.0/data/screenshots/05-diagnostics.png + + + #8ff0a4 #26a269 @@ -70,7 +93,7 @@ - +

First release.

    diff --git a/data/screenshots/01-devices.png b/data/screenshots/01-devices.png new file mode 100644 index 0000000..394b5c4 Binary files /dev/null and b/data/screenshots/01-devices.png differ diff --git a/data/screenshots/02-device-action.png b/data/screenshots/02-device-action.png new file mode 100644 index 0000000..f3e3d47 Binary files /dev/null and b/data/screenshots/02-device-action.png differ diff --git a/data/screenshots/03-policy.png b/data/screenshots/03-policy.png new file mode 100644 index 0000000..6ecfb92 Binary files /dev/null and b/data/screenshots/03-policy.png differ diff --git a/data/screenshots/04-new-rule.png b/data/screenshots/04-new-rule.png new file mode 100644 index 0000000..1d7098c Binary files /dev/null and b/data/screenshots/04-new-rule.png differ diff --git a/data/screenshots/05-diagnostics.png b/data/screenshots/05-diagnostics.png new file mode 100644 index 0000000..6fde81d Binary files /dev/null and b/data/screenshots/05-diagnostics.png differ diff --git a/po/it.po b/po/it.po index 1ab246b..f2f214d 100644 --- a/po/it.po +++ b/po/it.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: USBGuard GUI\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-09-26 13:04+0200\n" +"POT-Creation-Date: 2026-09-27 22:21+0200\n" "PO-Revision-Date: 2026-09-25 19:39+0200\n" "Last-Translator: onyks-os\n" "Language-Team: Italian\n" @@ -164,21 +164,17 @@ msgstr "Permanentemente" msgid "Written to the policy; survives a restart" msgstr "Scritto nelle regole; resta dopo un riavvio" -#: src/ui/diagnostic_dialog.rs:18 -msgid "USBGuard access" -msgstr "Accesso a USBGuard" +#: src/ui/diagnostic_dialog.rs:21 +msgid "Copy commands" +msgstr "Copia i comandi" -#: src/ui/diagnostic_dialog.rs:19 src/ui/window.rs:44 +#: src/ui/diagnostic_dialog.rs:29 src/ui/window.rs:44 msgid "Checking…" msgstr "Verifica in corso…" -#: src/ui/diagnostic_dialog.rs:21 -msgid "Close" -msgstr "Chiudi" - -#: src/ui/diagnostic_dialog.rs:49 -msgid "Copy commands" -msgstr "Copia i comandi" +#: src/ui/diagnostic_dialog.rs:76 +msgid "USBGuard access" +msgstr "Accesso a USBGuard" #: src/ui/i18n.rs:60 src/ui/window.rs:45 msgid "Connected" @@ -975,11 +971,31 @@ msgstr "dispositivo" msgid "security" msgstr "sicurezza" +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:67 +msgid "Every connected device and whether it is authorized" +msgstr "Ogni dispositivo collegato e se è autorizzato" + +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:71 +msgid "Allow, block, or reject a device, for this session or permanently" +msgstr "Consenti, blocca o rifiuta un dispositivo, per questa sessione o permanentemente" + #: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:75 +msgid "The policy rules in the order USBGuard evaluates them" +msgstr "Le regole della policy nell’ordine in cui USBGuard le valuta" + +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:79 +msgid "A guided editor for new rules" +msgstr "Un editor guidato per le nuove regole" + +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:83 +msgid "Diagnostics that name the exact cause of an access problem" +msgstr "Una diagnostica che indica la causa esatta di un problema di accesso" + +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:98 msgid "First release." msgstr "Prima versione." -#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:77 +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:100 msgid "" "Live device list; allow, block, or reject a device for this session or " "permanently" @@ -987,7 +1003,7 @@ msgstr "" "Elenco dei dispositivi in tempo reale; consenti, blocca o rifiuta un " "dispositivo per questa sessione o permanentemente" -#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:78 +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:101 msgid "" "Policy view in evaluation order, with a guided rule editor and safe rule " "removal" @@ -995,14 +1011,17 @@ msgstr "" "Vista delle regole nell’ordine di valutazione, con un editor guidato e una " "rimozione sicura" -#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:79 +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:102 msgid "Notifications for newly inserted devices that are not authorized" msgstr "Notifiche per i dispositivi appena collegati e non autorizzati" -#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:80 +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:103 msgid "" "Diagnostics that name the exact cause of an access problem, and usbguard-gui " "--diagnose" msgstr "" "Una diagnostica che indica la causa esatta di un problema di accesso, e " "usbguard-gui --diagnose" + +#~ msgid "Close" +#~ msgstr "Chiudi" diff --git a/po/usbguard-gui.pot b/po/usbguard-gui.pot index a10be3b..b86c3be 100644 --- a/po/usbguard-gui.pot +++ b/po/usbguard-gui.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-09-26 13:04+0200\n" +"POT-Creation-Date: 2026-09-27 22:21+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -162,20 +162,16 @@ msgstr "" msgid "Written to the policy; survives a restart" msgstr "" -#: src/ui/diagnostic_dialog.rs:18 -msgid "USBGuard access" +#: src/ui/diagnostic_dialog.rs:21 +msgid "Copy commands" msgstr "" -#: src/ui/diagnostic_dialog.rs:19 src/ui/window.rs:44 +#: src/ui/diagnostic_dialog.rs:29 src/ui/window.rs:44 msgid "Checking…" msgstr "" -#: src/ui/diagnostic_dialog.rs:21 -msgid "Close" -msgstr "" - -#: src/ui/diagnostic_dialog.rs:49 -msgid "Copy commands" +#: src/ui/diagnostic_dialog.rs:76 +msgid "USBGuard access" msgstr "" #: src/ui/i18n.rs:60 src/ui/window.rs:45 @@ -914,27 +910,47 @@ msgstr "" msgid "security" msgstr "" +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:67 +msgid "Every connected device and whether it is authorized" +msgstr "" + +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:71 +msgid "Allow, block, or reject a device, for this session or permanently" +msgstr "" + #: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:75 +msgid "The policy rules in the order USBGuard evaluates them" +msgstr "" + +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:79 +msgid "A guided editor for new rules" +msgstr "" + +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:83 +msgid "Diagnostics that name the exact cause of an access problem" +msgstr "" + +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:98 msgid "First release." msgstr "" -#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:77 +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:100 msgid "" "Live device list; allow, block, or reject a device for this session or " "permanently" msgstr "" -#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:78 +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:101 msgid "" "Policy view in evaluation order, with a guided rule editor and safe rule " "removal" msgstr "" -#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:79 +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:102 msgid "Notifications for newly inserted devices that are not authorized" msgstr "" -#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:80 +#: data/io.github.onyks_os.UsbguardGui.metainfo.xml.in:103 msgid "" "Diagnostics that name the exact cause of an access problem, and usbguard-gui " "--diagnose" diff --git a/src/cli.rs b/src/cli.rs index 7bde246..da61789 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -173,13 +173,9 @@ fn yes_no(value: Option, yes: &str, no: &str) -> String { #[must_use] pub fn format_report(report: &ProbeReport, distro: Distro) -> String { let mut out = String::new(); - let _ = writeln!( - out, - "USBGuard GUI {} — access diagnostics\n", - crate::VERSION - ); + let _ = writeln!(out, "USBGuardGUI {} — access diagnostics\n", crate::VERSION); let line = |out: &mut String, label: &str, value: &str| { - let _ = writeln!(out, " {label:<28}{value}"); + let _ = writeln!(out, " {label:<24}{value}"); }; let bus = if report.state == AccessState::BusUnavailable { "unavailable" diff --git a/src/ui/diagnostic_dialog.rs b/src/ui/diagnostic_dialog.rs index e1f7bbf..60c4cd9 100644 --- a/src/ui/diagnostic_dialog.rs +++ b/src/ui/diagnostic_dialog.rs @@ -13,21 +13,73 @@ use crate::runtime::runtime; use gettextrs::gettext; /// Opens the dialog over `parent`. +/// +/// A full dialog rather than an alert: the report is the `--diagnose` text, +/// aligned in columns, and an alert is too narrow to show it unwrapped. pub(super) fn present(parent: &impl IsA) { - let dialog = adw::AlertDialog::new( - Some(&gettext("USBGuard access")), - Some(&gettext("Checking…")), - ); - dialog.add_response("close", &gettext("Close")); - dialog.set_close_response("close"); + let copy = gtk::Button::builder() + .label(gettext("Copy commands")) + .css_classes(["suggested-action"]) + .visible(false) + .build(); + let header = adw::HeaderBar::new(); + header.pack_start(©); + let summary = gtk::Label::builder() + .label(gettext("Checking…")) + .xalign(0.0) + .wrap(true) + .css_classes(["title-4"]) + .build(); let report_label = gtk::Label::builder() .selectable(true) .xalign(0.0) - .wrap(true) + .yalign(0.0) .css_classes(["monospace"]) .build(); - dialog.set_extra_child(Some(&report_label)); + let report_frame = gtk::Frame::builder() + .child( + >k::ScrolledWindow::builder() + .child(&report_label) + .vscrollbar_policy(gtk::PolicyType::Never) + .propagate_natural_height(true) + .build(), + ) + .build(); + report_label.set_margin_top(12); + report_label.set_margin_bottom(12); + report_label.set_margin_start(12); + report_label.set_margin_end(12); + + let column = gtk::Box::builder() + .orientation(gtk::Orientation::Vertical) + .spacing(12) + .margin_top(6) + .margin_bottom(18) + .margin_start(18) + .margin_end(18) + .build(); + column.append(&summary); + column.append(&report_frame); + + let toolbar = adw::ToolbarView::new(); + toolbar.add_top_bar(&header); + toolbar.set_content(Some( + >k::ScrolledWindow::builder() + .child(&column) + .hscrollbar_policy(gtk::PolicyType::Never) + .propagate_natural_height(true) + .build(), + )); + + let dialog = adw::Dialog::builder() + .title(gettext("USBGuard access")) + .content_width(800) + // Fixed: the report arrives after the dialog is sized, and a dialog + // does not grow to fit it. Longer reports (with a remedy) scroll. + .content_height(480) + .child(&toolbar) + .build(); dialog.present(Some(parent)); // The probe runs on Tokio; the result comes back over a one-shot channel @@ -41,16 +93,18 @@ pub(super) fn present(parent: &impl IsA) { return; }; let distro = Distro::detect(); - dialog.set_body(&super::i18n::access_summary(&report.state)); - report_label.set_text(&format_report(&report, distro)); + summary.set_label(&super::i18n::access_summary(&report.state)); + report_label.set_text(format_report(&report, distro).trim_end()); + // The selectable report is otherwise the first focusable widget, and + // opens with a text cursor in it. + dialog.set_focus(None::<>k::Widget>); if let Some(remedy) = remedy(&report.state, distro).filter(|r| !r.commands.is_empty()) { let commands = remedy.commands.join("\n"); - dialog.add_response("copy", &gettext("Copy commands")); - dialog.set_response_appearance("copy", adw::ResponseAppearance::Suggested); - dialog.connect_response(Some("copy"), move |d, _| { - d.clipboard().set_text(&commands); + copy.connect_clicked(move |button| { + button.clipboard().set_text(&commands); }); + copy.set_visible(true); } }); }