Add first-run permission summary dialog before launch
This commit is contained in:
83
src/ui/permission_dialog.rs
Normal file
83
src/ui/permission_dialog.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
use adw::prelude::*;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::core::database::Database;
|
||||
use crate::core::launcher;
|
||||
use crate::i18n::i18n;
|
||||
|
||||
/// Show a first-run permission summary before launching an AppImage.
|
||||
/// Returns a dialog that the caller should present. The `on_proceed` callback
|
||||
/// is called if the user chooses to continue.
|
||||
pub fn show_permission_dialog(
|
||||
parent: &impl IsA<gtk::Widget>,
|
||||
app_name: &str,
|
||||
record_id: i64,
|
||||
db: &Rc<Database>,
|
||||
on_proceed: impl Fn() + 'static,
|
||||
) {
|
||||
let dialog = adw::AlertDialog::builder()
|
||||
.heading(&format!("Launch {}?", app_name))
|
||||
.body(&i18n(
|
||||
"This AppImage will run with your full user permissions. \
|
||||
It can access your files, network, and desktop.",
|
||||
))
|
||||
.build();
|
||||
|
||||
let extra = gtk::Box::builder()
|
||||
.orientation(gtk::Orientation::Vertical)
|
||||
.spacing(8)
|
||||
.margin_top(12)
|
||||
.build();
|
||||
|
||||
let access_label = gtk::Label::builder()
|
||||
.label(&i18n("This app will have access to:"))
|
||||
.xalign(0.0)
|
||||
.build();
|
||||
access_label.add_css_class("heading");
|
||||
extra.append(&access_label);
|
||||
|
||||
let items = [
|
||||
"Your home directory and files",
|
||||
"Network and internet access",
|
||||
"Display server (Wayland/X11)",
|
||||
"System D-Bus and services",
|
||||
];
|
||||
for item in &items {
|
||||
let label = gtk::Label::builder()
|
||||
.label(&format!(" - {}", i18n(item)))
|
||||
.xalign(0.0)
|
||||
.build();
|
||||
extra.append(&label);
|
||||
}
|
||||
|
||||
// Show firejail option if available
|
||||
if launcher::has_firejail() {
|
||||
let sandbox_note = gtk::Label::builder()
|
||||
.label(&i18n(
|
||||
"Firejail is available on your system. You can configure sandboxing in the app's system tab.",
|
||||
))
|
||||
.wrap(true)
|
||||
.xalign(0.0)
|
||||
.margin_top(8)
|
||||
.build();
|
||||
sandbox_note.add_css_class("dim-label");
|
||||
extra.append(&sandbox_note);
|
||||
}
|
||||
|
||||
dialog.set_extra_child(Some(&extra));
|
||||
|
||||
dialog.add_response("cancel", &i18n("Cancel"));
|
||||
dialog.add_response("proceed", &i18n("Launch"));
|
||||
dialog.set_response_appearance("proceed", adw::ResponseAppearance::Suggested);
|
||||
dialog.set_default_response(Some("proceed"));
|
||||
dialog.set_close_response("cancel");
|
||||
|
||||
let db_ref = db.clone();
|
||||
dialog.connect_response(Some("proceed"), move |_dlg, _response| {
|
||||
// Mark as prompted so we don't show again
|
||||
db_ref.set_first_run_prompted(record_id, true).ok();
|
||||
on_proceed();
|
||||
});
|
||||
|
||||
dialog.present(Some(parent));
|
||||
}
|
||||
Reference in New Issue
Block a user