summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs64
1 files changed, 60 insertions, 4 deletions
diff --git a/src/lib.rs b/src/lib.rs
index b5ceccd..751a3ea 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,6 @@
 use adw::prelude::*;
 use libsecret::prelude::{RetrievableExtManual, RetrievableExt};
-use relm4::{gtk, loading_widgets::LoadingWidgets, prelude::{AsyncComponent, AsyncComponentController, AsyncComponentParts, AsyncController, ComponentController, Controller}, AsyncComponentSender, Component, RelmWidgetExt};
+use relm4::{actions::{RelmAction, RelmActionGroup}, gtk, loading_widgets::LoadingWidgets, prelude::{AsyncComponent, AsyncComponentController, AsyncComponentParts, AsyncController, ComponentController, Controller}, AsyncComponentSender, Component, RelmWidgetExt};
 
 pub mod components {
     pub(crate) mod smart_summary;
@@ -124,6 +124,16 @@ impl App {
             Ok(None)
         }
     }
+
+    fn about() -> adw::AboutDialog {
+        adw::AboutDialog::builder()
+            .application_name("Bowl for Kittybox")
+            .developer_name("Vika Shleina")
+            .version(env!("CARGO_PKG_VERSION"))
+            .website("https://kittybox.fireburn.ru/bowl/")
+            .developers(vec!["Vika https://fireburn.ru"])
+            .build()
+    }
 }
 
 #[derive(Debug)]
@@ -131,9 +141,15 @@ impl App {
 pub enum Input {
     SubmitButtonPressed,
     Authorize(Box<components::SignInOutput>),
-    PostEditor(Option<Post>)
+    SignOut,
+    PostEditor(Option<Post>),
 }
 
+relm4::new_action_group!(AppActionGroup, "app");
+relm4::new_stateless_action!(AboutAction, AppActionGroup, "about");
+relm4::new_stateless_action!(SignOutAction, AppActionGroup, "sign-out");
+relm4::new_stateless_action!(PreferencesAction, AppActionGroup, "preferences");
+
 #[relm4::component(pub async)]
 impl AsyncComponent for App {
     /// The type of the messages that this component can receive.
@@ -145,9 +161,17 @@ impl AsyncComponent for App {
     /// The type of the command outputs that this component can receive.
     type CommandOutput = ();
 
+    menu! {
+        main_menu: {
+            "Sign out" => SignOutAction,
+            "Preferences" => PreferencesAction,
+            "About" => AboutAction,
+        }
+    }
+
     view! {
         #[root]
-        adw::ApplicationWindow {
+        root = adw::ApplicationWindow {
             #[iterate]
             add_css_class: [
                 #[cfg(debug_assertions)] "devel"
@@ -162,6 +186,12 @@ impl AsyncComponent for App {
 
             adw::ToolbarView {
                 add_top_bar = &adw::HeaderBar {
+                    pack_end = &gtk::MenuButton {
+                        #[wrap(Some)]
+                        set_popover = &gtk::PopoverMenu::from_model(Some(&main_menu)) {},
+                        #[watch]
+                        set_visible: model.micropub.is_some(),
+                    },
                     pack_end = &gtk::Button {
                         set_icon_name: "document-send-symbolic",
                         set_tooltip: "Send post",
@@ -179,7 +209,7 @@ impl AsyncComponent for App {
                     None => model.signin.widget().clone(),
                 }
             },
-        }
+        },
     }
 
     fn init_loading_widgets(root: Self::Root) -> Option<relm4::loading_widgets::LoadingWidgets> {
@@ -235,6 +265,23 @@ impl AsyncComponent for App {
 
         let widgets = view_output!();
 
+        let input_sender = sender.input_sender().clone();
+        let weak_window = window.downgrade();
+        let about_action: RelmAction<AboutAction> = RelmAction::new_stateless(move |_| {
+            App::about().present(weak_window.upgrade().as_ref());
+        });
+        let preferences_action: RelmAction<PreferencesAction> = RelmAction::new_stateless(move |_| {
+            log::warn!("Ain't implemented yet!");
+        });
+        let sign_out_action: RelmAction<SignOutAction> = RelmAction::new_stateless(move |_| {
+            input_sender.emit(Input::SignOut)
+        });
+        let mut action_group: RelmActionGroup<AppActionGroup> = RelmActionGroup::new();
+        action_group.add_action(about_action);
+        action_group.add_action(preferences_action);
+        action_group.add_action(sign_out_action);
+        action_group.register_for_widget(&window);
+
         AsyncComponentParts { model, widgets }
     }
 
@@ -246,6 +293,15 @@ impl AsyncComponent for App {
         _root: &Self::Root
     ) {
         match message {
+            Input::SignOut => {
+                if self.micropub.take().is_some() {
+                    libsecret::password_clear_future(
+                        Some(&self.secret_schema),
+                        Default::default(),
+                    ).await;
+                    self.micropub = None;
+                }
+            },
             Input::Authorize(data) => {
                 let mut attributes = std::collections::HashMap::new();
                 let _me = data.me.to_string();