diff options
-rw-r--r-- | icons.toml | 2 | ||||
-rw-r--r-- | po/bowl.pot | 17 | ||||
-rw-r--r-- | po/ru.po | 17 | ||||
-rw-r--r-- | src/components/preferences.rs | 90 | ||||
-rw-r--r-- | src/lib.rs | 14 |
5 files changed, 138 insertions, 2 deletions
diff --git a/icons.toml b/icons.toml index e594704..61797c1 100644 --- a/icons.toml +++ b/icons.toml @@ -4,4 +4,4 @@ # List of icon names you found (shipped with this crate) # Note: the file ending `-symbolic.svg` isn't part of the icon name. -icons = ["menu"] +icons = ["menu", "magic-wand"] diff --git a/po/bowl.pot b/po/bowl.pot index 92da214..8034d1d 100644 --- a/po/bowl.pot +++ b/po/bowl.pot @@ -179,3 +179,20 @@ msgstr "" #: data/xyz.vikanezrimaya.kittybox.Bowl.gschema.xml.in:48 msgid "Append this to the prompt after the article text." msgstr "" + +#: src/components/preferences.rs:21 +msgid "Language Models" +msgstr "" + +#: src/components/preferences.rs:22 +msgid "Settings for the language model integrations." +msgstr "" + +#: src/components/preferences.rs:26 +msgid "General" +msgstr "" + +#: src/components/preferences.rs:33 +msgid "Smart Summary" +msgstr "" + diff --git a/po/ru.po b/po/ru.po index 8ce26e5..b6df217 100644 --- a/po/ru.po +++ b/po/ru.po @@ -192,3 +192,20 @@ msgstr "Суффикс вводной Умной Выжимки" #: data/xyz.vikanezrimaya.kittybox.Bowl.gschema.xml.in:48 msgid "Append this to the prompt after the article text." msgstr "Что приписывается к вводной после текста статьи." + +#: src/components/preferences.rs:21 +msgid "Language Models" +msgstr "Языковые модели" + +#: src/components/preferences.rs:22 +msgid "Settings for the language model integrations." +msgstr "Настройки интеграции языковых моделей." + +#: src/components/preferences.rs:26 +msgid "General" +msgstr "Общее" + +#: src/components/preferences.rs:33 +msgid "Smart Summary" +msgstr "Умная Выжимка" + diff --git a/src/components/preferences.rs b/src/components/preferences.rs new file mode 100644 index 0000000..9bbc313 --- /dev/null +++ b/src/components/preferences.rs @@ -0,0 +1,90 @@ +use gettextrs::*; +use gio::prelude::*; +use adw::prelude::*; +use relm4::prelude::*; + +pub struct Preferences { + settings: gio::Settings, +} + +#[relm4::component(pub)] +impl Component for Preferences { + type CommandOutput = (); + type Input = Option<gtk::Widget>; + type Output = (); + type Init = (); + + view! { + #[root] + adw::PreferencesDialog { + add = &adw::PreferencesPage { + set_title: &gettext("Language Models"), + set_description: &gettext("Settings for the language model integrations."), + set_icon_name: Some("magic-wand"), + + adw::PreferencesGroup { + set_title: &gettext("General"), + + #[name = "llm_endpoint"] + adw::EntryRow {}, + }, + + adw::PreferencesGroup { + set_title: &gettext("Smart Summary"), + + #[name = "smart_summary_model"] adw::EntryRow {}, + #[name = "smart_summary_system_prompt"] adw::EntryRow {}, + #[name = "smart_summary_prompt_prefix"] adw::EntryRow {}, + #[name = "smart_summary_prompt_suffix"] adw::EntryRow {}, + } + } + } + } + + fn init( + _: Self::Init, + root: Self::Root, + _sender: ComponentSender<Self>, + ) -> ComponentParts<Self> { + let model = Self { + settings: gio::Settings::new(crate::APPLICATION_ID), + }; + + model.settings.delay(); + let schema = model.settings.settings_schema().unwrap(); + + let widgets = view_output!(); + + for (row, key) in [ + (&widgets.llm_endpoint, "llm-endpoint"), + (&widgets.smart_summary_model, "smart-summary-model"), + (&widgets.smart_summary_system_prompt, "smart-summary-system-prompt"), + (&widgets.smart_summary_prompt_prefix, "smart-summary-prompt-prefix"), + (&widgets.smart_summary_prompt_suffix, "smart-summary-prompt-suffix"), + ] { + model.settings.bind(key, row, "text") + .get() + .set() + .build(); + row.set_title(&gettext(schema.key(key).summary().unwrap())); + } + + root.connect_closed(glib::clone!( + #[strong(rename_to = settings)] + model.settings, + move |_| { + settings.apply() + } + )); + + ComponentParts { model, widgets } + } + + fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>, root: &Self::Root) { + root.present(msg.as_ref()); + } + + fn shutdown(&mut self, _: &mut Self::Widgets, _: relm4::Sender<()>) { + self.settings.apply() + } +} diff --git a/src/lib.rs b/src/lib.rs index 30cba6f..6421560 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,9 @@ pub mod components { pub mod signin; pub use signin::{SignIn, Output as SignInOutput}; + + pub mod preferences; + pub use preferences::Preferences; } use components::{post_editor::Post, PostEditorInput}; @@ -274,8 +277,17 @@ impl AsyncComponent for App { let about_action: RelmAction<AboutAction> = RelmAction::new_stateless(move |_| { App::about().present(weak_window.upgrade().as_ref()); }); + let weak_window = window.downgrade(); let preferences_action: RelmAction<PreferencesAction> = RelmAction::new_stateless(move |_| { - log::warn!("Ain't implemented yet!"); + // This could be built as an action that sends an input to open preferences. + // + // But I find this an acceptable alternative. + let mut prefs = components::Preferences::builder() + .launch(()) + .detach(); + + prefs.emit(weak_window.upgrade().map(|w| w.upcast())); + prefs.detach_runtime(); }); let sign_out_action: RelmAction<SignOutAction> = RelmAction::new_stateless(move |_| { input_sender.emit(Input::SignOut) |