Revert https://gitlab.gnome.org/World/Authenticator/-/commit/87dd3b224385
until x11-toolkits/gtk40 >= 4.10.

[gtk4-sys 0.5.4] Package dependency requirement 'gtk4 >= 4.9' could not be satisfied.
[gtk4-sys 0.5.4] Package 'gtk4' has version '4.8.3', required version is '>= 4.9'

--- Cargo.toml.orig	2022-12-27 13:51:14 UTC
+++ Cargo.toml
@@ -13,7 +13,7 @@ gst4gtk = { package = "gst-plugin-gtk4", version = "0.
 gettext-rs = {version = "0.7", features = ["gettext-system"]}
 gst = {package = "gstreamer", version = "0.19"}
 gst4gtk = { package = "gst-plugin-gtk4", version = "0.9", features = ["wayland", "x11egl", "x11glx"]}
-gtk = {package = "gtk4", version = "0.5", features = ["v4_10"]}
+gtk = {package = "gtk4", version = "0.5"}
 gtk-macros = "0.3"
 search-provider = "0.4"
 hex = { version = "0.4.3", features = [ "serde" ] }
--- src/widgets/accounts/details.rs.orig	2022-12-27 13:51:14 UTC
+++ src/widgets/accounts/details.rs
@@ -1,8 +1,8 @@
-use adw::prelude::*;
 use gettextrs::gettext;
 use gtk::{
     gdk,
     glib::{self, clone},
+    prelude::*,
     subclass::prelude::*,
     CompositeTemplate,
 };
@@ -161,24 +161,21 @@ impl AccountDetailsPage {
     fn delete_account(&self) {
         let parent = self.root().unwrap().downcast::<gtk::Window>().unwrap();
 
-        let dialog = adw::MessageDialog::builder()
-            .heading(&gettext("Are you sure you want to delete the account?"))
-            .body(&gettext("This action is irreversible"))
+        let dialog = gtk::MessageDialog::builder()
+            .message_type(gtk::MessageType::Warning)
+            .buttons(gtk::ButtonsType::YesNo)
+            .text(&gettext("Are you sure you want to delete the account?"))
+            .secondary_text(&gettext("This action is irreversible"))
             .modal(true)
             .transient_for(&parent)
             .build();
-        dialog.add_responses(&[("no", &gettext("No")), ("yes", &gettext("Yes"))]);
-        dialog.set_response_appearance("yes", adw::ResponseAppearance::Destructive);
-        dialog.connect_response(
-            None,
-            clone!(@weak self as page => move |dialog, response| {
-                if response == "yes" {
-                    let account = page.imp().account.borrow().as_ref().unwrap().clone();
-                    page.emit_by_name::<()>("removed", &[&account]);
-                }
-                dialog.close();
-            }),
-        );
+        dialog.connect_response(clone!(@weak self as page => move |dialog, response| {
+            if response == gtk::ResponseType::Yes {
+                let account = page.imp().account.borrow().as_ref().unwrap().clone();
+                page.emit_by_name::<()>("removed", &[&account]);
+            }
+            dialog.close();
+        }));
 
         dialog.show();
     }
--- src/widgets/preferences/window.rs.orig	2022-12-27 13:51:14 UTC
+++ src/widgets/preferences/window.rs
@@ -37,6 +37,7 @@ mod imp {
         pub actions: gio::SimpleActionGroup,
         pub backup_actions: gio::SimpleActionGroup,
         pub restore_actions: gio::SimpleActionGroup,
+        pub file_chooser: RefCell<Option<gtk::FileChooserNative>>,
         pub camera_page: CameraPage,
         pub password_page: PasswordPage,
         #[template_child]
@@ -83,6 +84,7 @@ mod imp {
                 backup_group: TemplateChild::default(),
                 restore_group: TemplateChild::default(),
                 dark_mode_group: TemplateChild::default(),
+                file_chooser: RefCell::default(),
                 key_entries: RefCell::default(),
             }
         }
@@ -289,16 +291,17 @@ impl PreferencesWindow {
             imp.backup_actions,
             &T::identifier(),
             clone!(@weak self as win, @weak model => move |_, _| {
-                let ctx = glib::MainContext::default();
-                ctx.spawn_local(clone!(@weak win, @weak model => async move {
-                    if let Ok(Some(file)) = win.select_file(filters, Operation::Backup).await {
+                let dialog = win.select_file(filters, Operation::Backup);
+                dialog.connect_response(clone!(@weak model, @weak win => move |d, response| {
+                    if response == gtk::ResponseType::Accept {
                         let key = T::ENCRYPTABLE.then(|| {
                             win.encyption_key(Operation::Backup, &T::identifier())
                         }).flatten();
-                        if let Err(err) = T::backup(&model, &file, key.as_deref()) {
+                        if let Err(err) = T::backup(&model, &d.file().unwrap(), key.as_deref()) {
                             tracing::warn!("Failed to create a backup {}", err);
                         }
                     }
+                    d.destroy();
                 }));
             })
         );
@@ -453,14 +456,14 @@ impl PreferencesWindow {
                 imp.restore_actions,
                 &T::identifier(),
                 clone!(@weak self as win => move |_, _| {
-                    let ctx = glib::MainContext::default();
-                    ctx.spawn_local(clone!(@weak win => async move {
-                        if let Ok(Some(file)) = win.select_file(filters, Operation::Restore).await {
+                    let dialog = win.select_file(filters, Operation::Restore);
+                    dialog.connect_response(clone!(@weak win => move |d, response| {
+                        if response == gtk::ResponseType::Accept {
                             let key = T::ENCRYPTABLE.then(|| {
                                 win.encyption_key(Operation::Restore, &T::identifier())
                             }).flatten();
 
-                            match T::restore_from_file(&file, key.as_deref()) {
+                            match T::restore_from_file(&d.file().unwrap(), key.as_deref()) {
                                 Ok(items) => {
                                     win.restore_items::<T, T::Item>(items);
                                 },
@@ -469,6 +472,7 @@ impl PreferencesWindow {
                                 }
                             }
                         }
+                        d.destroy();
                     }));
                 })
             );
@@ -501,37 +505,42 @@ impl PreferencesWindow {
         self.close();
     }
 
-    async fn select_file(
+    fn select_file(
         &self,
         filters: &'static [&str],
         operation: Operation,
-    ) -> Result<Option<gio::File>, glib::Error> {
-        let filters_model = gio::ListStore::new(gtk::FileFilter::static_type());
+    ) -> gtk::FileChooserNative {
+        let native = match operation {
+            Operation::Backup => gtk::FileChooserNative::new(
+                Some(&gettext("Backup")),
+                gtk::Window::NONE,
+                gtk::FileChooserAction::Save,
+                Some(&gettext("Select")),
+                Some(&gettext("Cancel")),
+            ),
+            Operation::Restore => gtk::FileChooserNative::new(
+                Some(&gettext("Restore")),
+                gtk::Window::NONE,
+                gtk::FileChooserAction::Open,
+                Some(&gettext("Select")),
+                Some(&gettext("Cancel")),
+            ),
+        };
+
+        native.set_modal(true);
+        native.set_transient_for(Some(self));
+
         filters.iter().for_each(|f| {
             let filter = gtk::FileFilter::new();
             filter.add_mime_type(f);
             filter.set_name(Some(f));
-            filters_model.append(&filter);
+            native.add_filter(&filter);
         });
 
-        match operation {
-            Operation::Backup => {
-                let dialog = gtk::FileDialog::builder()
-                    .modal(true)
-                    .filters(&filters_model)
-                    .title(&gettext("Backup"))
-                    .build();
-                dialog.save_future(Some(self), gio::File::NONE, None).await
-            }
-            Operation::Restore => {
-                let dialog = gtk::FileDialog::builder()
-                    .modal(true)
-                    .filters(&filters_model)
-                    .title(&gettext("Restore"))
-                    .build();
-                dialog.open_future(Some(self), gio::File::NONE).await
-            }
-        }
+        // Hold a reference to the file chooser
+        self.imp().file_chooser.replace(Some(native.clone()));
+        native.show();
+        native
     }
 
     fn setup_actions(&self) {
--- src/widgets/providers/page.rs.orig	2022-12-27 13:51:14 UTC
+++ src/widgets/providers/page.rs
@@ -1,6 +1,6 @@ use gettextrs::gettext;
 use adw::prelude::*;
 use gettextrs::gettext;
-use glib::translate::IntoGlib;
+use glib::{clone, translate::IntoGlib};
 use gtk::{gdk_pixbuf, gio, glib, subclass::prelude::*, CompositeTemplate};
 
 use crate::{
@@ -55,6 +55,8 @@ mod imp {
         #[template_child]
         pub delete_button: TemplateChild<gtk::Button>,
         pub selected_provider: RefCell<Option<Provider>>,
+        // We need to hold a reference to the native file chooser
+        pub file_chooser: RefCell<Option<gtk::FileChooserNative>>,
         pub selected_image: RefCell<Option<gio::File>>,
         #[template_child]
         pub back_btn: TemplateChild<gtk::Button>,
@@ -92,6 +94,7 @@ mod imp {
                 methods_model,
                 algorithms_model,
                 selected_provider: RefCell::default(),
+                file_chooser: RefCell::default(),
                 selected_image: RefCell::default(),
             }
         }
@@ -116,8 +119,8 @@ mod imp {
             klass.install_action("providers.reset_image", None, move |page, _, _| {
                 page.reset_image();
             });
-            klass.install_action_async("providers.select_image", None, |page, _, _| async move {
-                page.open_select_image().await;
+            klass.install_action("providers.select_image", None, move |page, _, _| {
+                page.open_select_image();
             });
         }
 
@@ -301,26 +304,34 @@ impl ProviderPage {
         Ok(())
     }
 
-    async fn open_select_image(&self) {
+    fn open_select_image(&self) {
+        let imp = self.imp();
         let parent = self.root().unwrap().downcast::<gtk::Window>().unwrap();
 
+        let file_chooser = gtk::FileChooserNative::builder()
+            .accept_label(&gettext("Select"))
+            .cancel_label(&gettext("Cancel"))
+            .modal(true)
+            .action(gtk::FileChooserAction::Open)
+            .transient_for(&parent)
+            .build();
+
         let images_filter = gtk::FileFilter::new();
         images_filter.set_name(Some(&gettext("Image")));
         images_filter.add_pixbuf_formats();
-        let model = gio::ListStore::new(gtk::FileFilter::static_type());
-        model.append(&images_filter);
+        file_chooser.add_filter(&images_filter);
 
-        let file_chooser = gtk::FileDialog::builder()
-            .modal(true)
-            .filters(&model)
-            .build();
+        file_chooser.connect_response(clone!(@weak self as page => move |dialog, response| {
+            if response == gtk::ResponseType::Accept {
+                let file = dialog.file().unwrap();
+                page.set_image(file);
+            }
+            page.imp().file_chooser.replace(None);
+            dialog.destroy();
+        }));
 
-        if let Ok(Some(file)) = file_chooser
-            .open_future(Some(&parent), gio::File::NONE)
-            .await
-        {
-            self.set_image(file);
-        };
+        file_chooser.show();
+        imp.file_chooser.replace(Some(file_chooser));
     }
 
     fn set_image(&self, file: gio::File) {
@@ -356,7 +367,7 @@ impl ProviderPage {
     // save action Note that we don't validate the urls other than: does `url`
     // crate can parse it or not
     #[template_callback]
-    fn entry_validate(&self, _entry: adw::EntryRow) {
+    fn entry_validate(&self, _entry: gtk::Entry) {
         let imp = self.imp();
 
         let provider_name = imp.name_entry.text();
--- src/widgets/window.rs.orig	2022-12-27 13:51:14 UTC
+++ src/widgets/window.rs
@@ -150,7 +150,7 @@ impl Window {
         app.add_window(&window);
 
         if config::PROFILE == "Devel" {
-            window.add_css_class("devel");
+            window.style_context().add_class("devel");
         }
         window.init(model, app);
         window.setup_actions(app);
