mirror of
https://gitlab.gnome.org/World/Authenticator.git
synced 2025-03-04 00:34:40 +01:00
Drop usage of gtk-macros
This commit is contained in:
parent
a8607acea9
commit
ed01da7f0c
6 changed files with 146 additions and 139 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -235,7 +235,6 @@ dependencies = [
|
|||
"gettext-rs",
|
||||
"gst-plugin-gtk4",
|
||||
"gstreamer",
|
||||
"gtk-macros",
|
||||
"gtk4",
|
||||
"hex",
|
||||
"image 0.24.5",
|
||||
|
@ -1571,12 +1570,6 @@ dependencies = [
|
|||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gtk-macros"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da5bf7748fd4cd0b2490df8debcc911809dbcbee4ece9531b96c29a9c729de5a"
|
||||
|
||||
[[package]]
|
||||
name = "gtk4"
|
||||
version = "0.6.4"
|
||||
|
|
|
@ -14,7 +14,6 @@ gettext-rs = {version = "0.7", features = ["gettext-system"]}
|
|||
gst = {package = "gstreamer", version = "0.20"}
|
||||
gst4gtk = { package = "gst-plugin-gtk4", version = "0.10", features = ["wayland", "x11egl", "x11glx"]}
|
||||
gtk = {package = "gtk4", version = "0.6", features = ["v4_10"]}
|
||||
gtk-macros = "0.3"
|
||||
search-provider = "0.5"
|
||||
hex = { version = "0.4.3", features = [ "serde" ] }
|
||||
tracing = "0.1"
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
<interface>
|
||||
<template parent="AdwBin" class="CameraPage">
|
||||
<property name="child">
|
||||
<object class="Camera" id="camera"/>
|
||||
<object class="Camera" id="camera">
|
||||
<signal name="close" handler="on_camera_close" swapped="true" />
|
||||
</object>
|
||||
</property>
|
||||
<child>
|
||||
<object class="GtkShortcutController">
|
||||
|
|
|
@ -20,9 +20,11 @@ use crate::{utils::spawn_tokio, widgets::Camera};
|
|||
mod imp {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, CompositeTemplate)]
|
||||
#[derive(Debug, Default, CompositeTemplate, glib::Properties)]
|
||||
#[template(resource = "/com/belmoussaoui/Authenticator/preferences_camera_page.ui")]
|
||||
#[properties(wrapper_type = super::CameraPage)]
|
||||
pub struct CameraPage {
|
||||
#[property(get, set, construct_only)]
|
||||
pub actions: OnceCell<gio::SimpleActionGroup>,
|
||||
#[template_child]
|
||||
pub camera: TemplateChild<Camera>,
|
||||
|
@ -36,6 +38,7 @@ mod imp {
|
|||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
klass.bind_template();
|
||||
klass.bind_template_instance_callbacks();
|
||||
}
|
||||
|
||||
fn instance_init(obj: &InitializingObject<Self>) {
|
||||
|
@ -43,7 +46,19 @@ mod imp {
|
|||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for CameraPage {}
|
||||
impl ObjectImpl for CameraPage {
|
||||
fn properties() -> &'static [glib::ParamSpec] {
|
||||
Self::derived_properties()
|
||||
}
|
||||
|
||||
fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
|
||||
self.derived_set_property(id, value, pspec)
|
||||
}
|
||||
|
||||
fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value {
|
||||
self.derived_property(id, pspec)
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetImpl for CameraPage {}
|
||||
impl BinImpl for CameraPage {}
|
||||
|
@ -54,12 +69,10 @@ glib::wrapper! {
|
|||
@extends gtk::Widget, adw::Bin;
|
||||
}
|
||||
|
||||
#[gtk::template_callbacks]
|
||||
impl CameraPage {
|
||||
pub fn new(actions: gio::SimpleActionGroup) -> Self {
|
||||
let page = glib::Object::new::<Self>();
|
||||
page.imp().actions.set(actions).unwrap();
|
||||
page.setup_widget();
|
||||
page
|
||||
pub fn new(actions: &gio::SimpleActionGroup) -> Self {
|
||||
glib::Object::builder().property("actions", actions).build()
|
||||
}
|
||||
|
||||
pub async fn scan_from_camera(&self) -> Result<String> {
|
||||
|
@ -171,12 +184,8 @@ impl CameraPage {
|
|||
}
|
||||
}
|
||||
|
||||
fn setup_widget(&self) {
|
||||
let imp = self.imp();
|
||||
let actions = imp.actions.get().unwrap();
|
||||
|
||||
imp.camera.connect_close(clone!(@weak actions => move |_| {
|
||||
actions.activate_action("close_page", None);
|
||||
}));
|
||||
#[template_callback]
|
||||
fn on_camera_close(&self) {
|
||||
self.actions().activate_action("close_page", None);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,15 +3,15 @@ use std::cell::{Cell, RefCell};
|
|||
use gettextrs::gettext;
|
||||
use gtk::{
|
||||
gio,
|
||||
glib::{self, clone, subclass::InitializingObject},
|
||||
glib::{self, clone},
|
||||
prelude::*,
|
||||
subclass::prelude::*,
|
||||
};
|
||||
use gtk_macros::{action, get_action};
|
||||
|
||||
use crate::{config, models::keyring, utils::spawn_tokio, widgets::ErrorRevealer};
|
||||
|
||||
mod imp {
|
||||
use glib::subclass::InitializingObject;
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
use super::*;
|
||||
|
@ -20,6 +20,7 @@ mod imp {
|
|||
#[properties(wrapper_type = super::PasswordPage)]
|
||||
#[template(resource = "/com/belmoussaoui/Authenticator/preferences_password_page.ui")]
|
||||
pub struct PasswordPage {
|
||||
#[property(get, set, construct_only)]
|
||||
pub actions: OnceCell<gio::SimpleActionGroup>,
|
||||
#[property(get, set, construct)]
|
||||
pub has_set_password: Cell<bool>,
|
||||
|
@ -68,6 +69,7 @@ mod imp {
|
|||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
let page = self.obj();
|
||||
page.setup_actions();
|
||||
self.status_page.set_icon_name(Some(config::APP_ID));
|
||||
page.reset_validation();
|
||||
// Reset the validation whenever the password state changes
|
||||
|
@ -94,11 +96,8 @@ glib::wrapper! {
|
|||
|
||||
#[gtk::template_callbacks]
|
||||
impl PasswordPage {
|
||||
pub fn new(actions: gio::SimpleActionGroup) -> Self {
|
||||
let page = glib::Object::new::<Self>();
|
||||
page.imp().actions.set(actions).unwrap();
|
||||
page.setup_actions();
|
||||
page
|
||||
pub fn new(actions: &gio::SimpleActionGroup) -> Self {
|
||||
glib::Object::builder().property("actions", actions).build()
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
|
@ -115,7 +114,12 @@ impl PasswordPage {
|
|||
password_repeat == password && password != ""
|
||||
};
|
||||
|
||||
get_action!(imp.actions.get().unwrap(), @save_password).set_enabled(is_valid);
|
||||
let save_password_action = self
|
||||
.actions()
|
||||
.lookup_action("save_password")
|
||||
.and_downcast::<gio::SimpleAction>()
|
||||
.unwrap();
|
||||
save_password_action.set_enabled(is_valid);
|
||||
}
|
||||
|
||||
// Called when either the user sets/resets the password to bind/unbind the
|
||||
|
@ -131,39 +135,35 @@ impl PasswordPage {
|
|||
}
|
||||
|
||||
fn setup_actions(&self) {
|
||||
let imp = self.imp();
|
||||
|
||||
let actions = imp.actions.get().unwrap();
|
||||
action!(
|
||||
actions,
|
||||
"save_password",
|
||||
clone!(@weak self as page => move |_, _| {
|
||||
let actions = self.actions();
|
||||
let save_password = gio::ActionEntry::builder("save_password")
|
||||
.activate(clone!(@weak self as page => move |_, _, _| {
|
||||
let ctx = glib::MainContext::default();
|
||||
ctx.spawn_local(clone!(@weak page => async move {
|
||||
page.save().await;
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
action!(
|
||||
actions,
|
||||
"reset_password",
|
||||
clone!(@weak self as page => move |_,_| {
|
||||
}))
|
||||
.build();
|
||||
let reset_password = gio::ActionEntry::builder("reset_password")
|
||||
.activate(clone!(@weak self as page => move |_, _, _| {
|
||||
let ctx = glib::MainContext::default();
|
||||
ctx.spawn_local(clone!(@weak page => async move {
|
||||
page.reset_password().await;
|
||||
}));
|
||||
})
|
||||
);
|
||||
get_action!(actions, @save_password).set_enabled(false);
|
||||
}))
|
||||
.build();
|
||||
actions.add_action_entries([save_password, reset_password]);
|
||||
|
||||
self.bind_property(
|
||||
"has-set-password",
|
||||
&get_action!(actions, @reset_password),
|
||||
"enabled",
|
||||
)
|
||||
.sync_create()
|
||||
.build();
|
||||
let save_password_action = actions
|
||||
.lookup_action("save_password")
|
||||
.and_downcast::<gio::SimpleAction>()
|
||||
.unwrap();
|
||||
save_password_action.set_enabled(false);
|
||||
|
||||
let reset_password_action = actions.lookup_action("reset_password").unwrap();
|
||||
self.bind_property("has-set-password", &reset_password_action, "enabled")
|
||||
.sync_create()
|
||||
.build();
|
||||
}
|
||||
|
||||
async fn reset_password(&self) {
|
||||
|
@ -183,11 +183,15 @@ impl PasswordPage {
|
|||
spawn_tokio(async move { keyring::reset_password().await.is_ok() }).await;
|
||||
|
||||
if password_was_reset {
|
||||
let imp = self.imp();
|
||||
let actions = imp.actions.get().unwrap();
|
||||
let actions = self.actions();
|
||||
actions.activate_action("close_page", None);
|
||||
|
||||
get_action!(actions, @close_page).activate(None);
|
||||
get_action!(actions, @save_password).set_enabled(false);
|
||||
let save_password_action = actions
|
||||
.lookup_action("save_password")
|
||||
.and_downcast::<gio::SimpleAction>()
|
||||
.unwrap();
|
||||
|
||||
save_password_action.set_enabled(false);
|
||||
self.set_has_set_password(false);
|
||||
}
|
||||
}
|
||||
|
@ -202,7 +206,7 @@ impl PasswordPage {
|
|||
|
||||
async fn save(&self) {
|
||||
let imp = self.imp();
|
||||
let actions = imp.actions.get().unwrap();
|
||||
let actions = self.actions();
|
||||
|
||||
let current_password = imp.current_password_entry.text();
|
||||
let password = imp.password_entry.text();
|
||||
|
@ -221,9 +225,14 @@ impl PasswordPage {
|
|||
spawn_tokio(async move { keyring::set_password(&password).await.is_ok() }).await;
|
||||
if password_was_set {
|
||||
self.reset();
|
||||
get_action!(actions, @save_password).set_enabled(false);
|
||||
let save_password_action = actions
|
||||
.lookup_action("save_password")
|
||||
.and_downcast::<gio::SimpleAction>()
|
||||
.unwrap();
|
||||
|
||||
save_password_action.set_enabled(false);
|
||||
self.set_has_set_password(true);
|
||||
get_action!(actions, @close_page).activate(None);
|
||||
actions.activate_action("close_page", None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ use adw::prelude::*;
|
|||
use gettextrs::gettext;
|
||||
use glib::clone;
|
||||
use gtk::{gio, glib, subclass::prelude::*};
|
||||
use gtk_macros::{action, get_action, spawn};
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
use super::{camera_page::CameraPage, password_page::PasswordPage};
|
||||
|
@ -69,8 +68,8 @@ mod imp {
|
|||
|
||||
Self {
|
||||
has_set_password: Cell::default(), // Synced from the application
|
||||
camera_page: CameraPage::new(actions.clone()),
|
||||
password_page: PasswordPage::new(actions.clone()),
|
||||
camera_page: CameraPage::new(&actions),
|
||||
password_page: PasswordPage::new(&actions),
|
||||
actions,
|
||||
model: OnceCell::default(),
|
||||
backup_actions: gio::SimpleActionGroup::new(),
|
||||
|
@ -249,13 +248,11 @@ impl PreferencesWindow {
|
|||
imp.backup_group.add(&row);
|
||||
}
|
||||
|
||||
let model = imp.model.get().unwrap().clone();
|
||||
action!(
|
||||
imp.backup_actions,
|
||||
&T::identifier(),
|
||||
clone!(@weak self as win, @weak model => move |_, _| {
|
||||
let action = gio::ActionEntry::builder(&T::identifier())
|
||||
.activate(clone!(@weak self as win => move |_, _,_| {
|
||||
let ctx = glib::MainContext::default();
|
||||
ctx.spawn_local(clone!(@weak win, @weak model => async move {
|
||||
ctx.spawn_local(clone!(@weak win => async move {
|
||||
let model = win.model();
|
||||
if let Ok(file) = win.select_file(filters, Operation::Backup).await {
|
||||
let key = T::ENCRYPTABLE.then(|| {
|
||||
win.encyption_key(Operation::Backup, &T::identifier())
|
||||
|
@ -265,8 +262,9 @@ impl PreferencesWindow {
|
|||
}
|
||||
}
|
||||
}));
|
||||
})
|
||||
);
|
||||
}))
|
||||
.build();
|
||||
imp.backup_actions.add_action_entries([action]);
|
||||
}
|
||||
|
||||
fn register_restore<T: Restorable>(&self, filters: &'static [&str]) {
|
||||
|
@ -351,13 +349,12 @@ impl PreferencesWindow {
|
|||
imp.restore_group.add(&row);
|
||||
}
|
||||
if T::SCANNABLE {
|
||||
action!(
|
||||
imp.restore_actions,
|
||||
&format!("{}.camera", T::identifier()),
|
||||
clone!(@weak self as win, @weak imp.camera_page as camera_page => move |_, _| {
|
||||
get_action!(win.imp().actions, @show_camera_page).activate(None);
|
||||
spawn!(async move {
|
||||
match camera_page.scan_from_camera().await {
|
||||
let camera_action = gio::ActionEntry::builder(&format!("{}.camera", T::identifier()))
|
||||
.activate(clone!(@weak self as win=> move |_, _, _| {
|
||||
win.imp().actions.activate_action("show_camera_page", None);
|
||||
let ctx = glib::MainContext::default();
|
||||
ctx.spawn_local(clone!(@weak win => async move {
|
||||
match win.imp().camera_page.scan_from_camera().await {
|
||||
Ok(code) => match T::restore_from_data(code.as_bytes(), None) {
|
||||
Ok(items) => win.restore_items::<T, T::Item>(items),
|
||||
Err(error) => {
|
||||
|
@ -366,7 +363,7 @@ impl PreferencesWindow {
|
|||
"scanned QR code: {}",
|
||||
), error);
|
||||
|
||||
get_action!(win.imp().actions, @close_page).activate(None);
|
||||
win.imp().actions.activate_action("close_page", None);
|
||||
|
||||
win.add_toast(adw::Toast::new(&gettext("Unable to restore accounts")));
|
||||
},
|
||||
|
@ -377,47 +374,44 @@ impl PreferencesWindow {
|
|||
error,
|
||||
);
|
||||
|
||||
get_action!(win.imp().actions, @close_page).activate(None);
|
||||
win.imp().actions.activate_action("close_page", None);
|
||||
|
||||
win.add_toast(adw::Toast::new(&gettext("Something went wrong")));
|
||||
},
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
action!(
|
||||
imp.restore_actions,
|
||||
&format!("{}.screenshot", T::identifier()),
|
||||
clone!(@weak self as win, @weak imp.camera_page as camera_page => move |_, _| {
|
||||
spawn!(async move {
|
||||
match camera_page.scan_from_screenshot().await {
|
||||
Ok(code) => match T::restore_from_data(code.as_bytes(), None) {
|
||||
Ok(items) => {
|
||||
win.restore_items::<T, T::Item>(items);
|
||||
},
|
||||
Err(error) => {
|
||||
tracing::error!(concat!(
|
||||
"Encountered an error while trying to restore from a ",
|
||||
"scanned QR code: {}",
|
||||
), error);
|
||||
|
||||
win.add_toast(adw::Toast::new(&gettext("Unable to restore accounts")));
|
||||
},
|
||||
}));
|
||||
})).build();
|
||||
let screenshot_action = gio::ActionEntry::builder(&format!("{}.screenshot", T::identifier()))
|
||||
.activate(clone!(@weak self as win => move |_, _, _| {
|
||||
let ctx = glib::MainContext::default();
|
||||
ctx.spawn_local(clone!(@weak win => async move {
|
||||
match win.imp().camera_page.scan_from_screenshot().await {
|
||||
Ok(code) => match T::restore_from_data(code.as_bytes(), None) {
|
||||
Ok(items) => {
|
||||
win.restore_items::<T, T::Item>(items);
|
||||
},
|
||||
Err(error) => {
|
||||
tracing::error!("Encountered an error while trying to scan from the screenshot: {}", error);
|
||||
tracing::error!(concat!(
|
||||
"Encountered an error while trying to restore from a ",
|
||||
"scanned QR code: {}",
|
||||
), error);
|
||||
|
||||
win.add_toast(adw::Toast::new(&gettext("Couldn't find a QR code")));
|
||||
win.add_toast(adw::Toast::new(&gettext("Unable to restore accounts")));
|
||||
},
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
},
|
||||
Err(error) => {
|
||||
tracing::error!("Encountered an error while trying to scan from the screenshot: {}", error);
|
||||
|
||||
win.add_toast(adw::Toast::new(&gettext("Couldn't find a QR code")));
|
||||
},
|
||||
}
|
||||
}));
|
||||
})).build();
|
||||
imp.restore_actions
|
||||
.add_action_entries([camera_action, screenshot_action]);
|
||||
} else {
|
||||
action!(
|
||||
imp.restore_actions,
|
||||
&T::identifier(),
|
||||
clone!(@weak self as win => move |_, _| {
|
||||
let action = gio::ActionEntry::builder(&T::identifier())
|
||||
.activate(clone!(@weak self as win => move |_, _, _| {
|
||||
let ctx = glib::MainContext::default();
|
||||
ctx.spawn_local(clone!(@weak win => async move {
|
||||
if let Ok(file) = win.select_file(filters, Operation::Restore).await {
|
||||
|
@ -435,9 +429,11 @@ impl PreferencesWindow {
|
|||
}
|
||||
}
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
}))
|
||||
.build();
|
||||
|
||||
imp.restore_actions.add_action_entries([action]);
|
||||
};
|
||||
}
|
||||
|
||||
fn encyption_key(&self, mode: Operation, identifier: &str) -> Option<glib::GString> {
|
||||
|
@ -453,10 +449,10 @@ impl PreferencesWindow {
|
|||
}
|
||||
|
||||
fn restore_items<T: Restorable<Item = Q>, Q: RestorableItem>(&self, items: Vec<Q>) {
|
||||
let model = self.imp().model.get().unwrap();
|
||||
let model = self.model();
|
||||
items
|
||||
.iter()
|
||||
.map(move |item| item.restore(model))
|
||||
.map(move |item| item.restore(&model))
|
||||
.for_each(|item| {
|
||||
if let Err(err) = item {
|
||||
tracing::warn!("Failed to restore item {}", err);
|
||||
|
@ -522,28 +518,27 @@ impl PreferencesWindow {
|
|||
win.set_search_enabled(true);
|
||||
}));
|
||||
|
||||
action!(
|
||||
imp.actions,
|
||||
"show_camera_page",
|
||||
clone!(@weak self as win, @weak imp.camera_page as camera_page => move |_, _| {
|
||||
win.present_subpage(&camera_page);
|
||||
})
|
||||
);
|
||||
action!(
|
||||
imp.actions,
|
||||
"show_password_page",
|
||||
clone!(@weak self as win, @weak imp.password_page as password_page => move |_, _| {
|
||||
win.present_subpage(&password_page);
|
||||
})
|
||||
);
|
||||
action!(
|
||||
imp.actions,
|
||||
"close_page",
|
||||
clone!(@weak self as win, @weak imp.camera_page as camera_page => move |_, _| {
|
||||
let show_camera_page = gio::ActionEntry::builder("show_camera_page")
|
||||
.activate(clone!(@weak self as win => move |_, _, _| {
|
||||
win.present_subpage(&win.imp().camera_page);
|
||||
}))
|
||||
.build();
|
||||
|
||||
let show_password_page = gio::ActionEntry::builder("show_password_page")
|
||||
.activate(clone!(@weak self as win => move |_, _, _| {
|
||||
win.present_subpage(&win.imp().password_page);
|
||||
}))
|
||||
.build();
|
||||
|
||||
let close_page = gio::ActionEntry::builder("close_page")
|
||||
.activate(clone!(@weak self as win => move |_, _, _| {
|
||||
win.close_subpage();
|
||||
camera_page.imp().camera.stop();
|
||||
})
|
||||
);
|
||||
win.imp().camera_page.imp().camera.stop();
|
||||
}))
|
||||
.build();
|
||||
|
||||
imp.actions
|
||||
.add_action_entries([show_camera_page, show_password_page, close_page]);
|
||||
|
||||
self.insert_action_group("preferences", Some(&imp.actions));
|
||||
self.insert_action_group("backup", Some(&imp.backup_actions));
|
||||
|
|
Loading…
Add table
Reference in a new issue