diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/post_editor.rs | 36 | ||||
-rw-r--r-- | src/components/preferences.rs | 61 | ||||
-rw-r--r-- | src/lib.rs | 14 | ||||
-rw-r--r-- | src/meson.build | 1 |
4 files changed, 90 insertions, 22 deletions
diff --git a/src/components/post_editor.rs b/src/components/post_editor.rs index 25069be..863e515 100644 --- a/src/components/post_editor.rs +++ b/src/components/post_editor.rs @@ -32,40 +32,52 @@ pub struct Post { pub visibility: Visibility } -impl From<Post> for microformats::types::Item { - fn from(post: Post) -> Self { - use microformats::types::{Item, Class, KnownClass, PropertyValue}; +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct PostConversionSettings { + pub send_html_directly: bool, +} + +impl Post { + pub fn into_mf2(self, settings: PostConversionSettings) -> microformats::types::Item { + use microformats::types::{Item, Class, KnownClass, PropertyValue, Fragment}; let mut mf2 = Item::new(vec![Class::Known(KnownClass::Entry)]); - if let Some(name) = post.name { + if let Some(name) = self.name { mf2.properties.insert( "name".to_owned(), vec![PropertyValue::Plain(name)] ); } - if let Some(summary) = post.summary { + if let Some(summary) = self.summary { mf2.properties.insert( "summary".to_owned(), vec![PropertyValue::Plain(summary)] ); } - if !post.tags.is_empty() { + if !self.tags.is_empty() { mf2.properties.insert( "category".to_string(), - post.tags.into_iter().map(PropertyValue::Plain).collect() + self.tags.into_iter().map(PropertyValue::Plain).collect() ); } mf2.properties.insert( "visibility".to_string(), - vec![PropertyValue::Plain(post.visibility.to_string())] + vec![PropertyValue::Plain(self.visibility.to_string())] ); - mf2.properties.insert( - "content".to_string(), - vec![PropertyValue::Plain(post.content)] - ); + let content = if settings.send_html_directly { + PropertyValue::Fragment(Fragment { + html: self.content.clone(), + value: self.content, + lang: None + }) + } else { + PropertyValue::Plain(self.content) + }; + + mf2.properties.insert("content".to_string(), vec![content]); mf2 } diff --git a/src/components/preferences.rs b/src/components/preferences.rs index f1f37f9..67075a2 100644 --- a/src/components/preferences.rs +++ b/src/components/preferences.rs @@ -1,3 +1,5 @@ +use gettextrs::*; + use gio::prelude::*; use adw::prelude::*; use relm4::prelude::*; @@ -6,6 +8,52 @@ pub struct Preferences { settings: gio::Settings, } +#[allow(dead_code)] +struct ComposerPreferencesWidgets { + page: adw::PreferencesPage, + general_group: adw::PreferencesGroup, + send_html_directly: adw::SwitchRow, +} + +impl ComposerPreferencesWidgets { + fn new(settings: &gio::Settings) -> Self { + let page = adw::PreferencesPage::builder() + .title(gettext("Post composer")) + .description(gettext("Settings for composing new posts and editing existing ones.")) + .icon_name("editor-symbolic") + .build(); + let general_group = adw::PreferencesGroup::builder() + .title(gettext("General")) + .build(); + let send_html_directly = adw::SwitchRow::new(); + general_group.add(&send_html_directly); + page.add(&general_group); + + let widgets = Self { + page, + general_group, + send_html_directly + }; + + let schema = settings.settings_schema().unwrap(); + + #[expect(clippy::single_element_loop)] + for (row, key, property) in [ + (widgets.send_html_directly.upcast_ref::<adw::PreferencesRow>(), "send-html-directly", "active"), + ] { + let key_data = schema.key(key); + settings.bind(key, row, property) + .get() + .set() + .build(); + row.set_title(&gettext(key_data.summary().unwrap())); + row.set_tooltip_markup(key_data.description().map(gettext).as_deref()); + } + + widgets + } +} + #[cfg(feature = "smart-summary")] #[allow(dead_code)] struct LanguageModelPreferencesWidgets { @@ -25,10 +73,8 @@ struct LanguageModelPreferencesWidgets { #[cfg(feature = "smart-summary")] impl LanguageModelPreferencesWidgets { fn new(settings: &gio::Settings) -> Self { - use gettextrs::*; - let page = adw::PreferencesPage::builder() - .title(gettext("Language Models")) + .title(gettext("Language models")) .description(gettext("Settings for the language model integrations.")) .icon_name("brain-augemnted") // sic! .build(); @@ -79,11 +125,13 @@ impl LanguageModelPreferencesWidgets { (widgets.smart_summary_prompt_prefix.upcast_ref::<_>(), "smart-summary-prompt-prefix", "text"), (widgets.smart_summary_prompt_suffix.upcast_ref::<_>(), "smart-summary-prompt-suffix", "text"), ] { + let key_data = schema.key(key); settings.bind(key, row, property) .get() .set() .build(); - row.set_title(&gettext(schema.key(key).summary().unwrap())); + row.set_title(&gettext(key_data.summary().unwrap())); + row.set_tooltip_markup(key_data.description().map(gettext).as_deref()); } widgets @@ -91,8 +139,9 @@ impl LanguageModelPreferencesWidgets { } pub struct PreferencesWidgets { + composer: ComposerPreferencesWidgets, #[cfg(feature = "smart-summary")] - llm: LanguageModelPreferencesWidgets + llm: LanguageModelPreferencesWidgets, } impl Component for Preferences { @@ -119,9 +168,11 @@ impl Component for Preferences { model.settings.delay(); let widgets = PreferencesWidgets { + composer: ComposerPreferencesWidgets::new(&model.settings), #[cfg(feature = "smart-summary")] llm: LanguageModelPreferencesWidgets::new(&model.settings), }; + root.add(&widgets.composer.page); #[cfg(feature = "smart-summary")] root.add(&widgets.llm.page); diff --git a/src/lib.rs b/src/lib.rs index bdc3682..fd4b51c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,13 +29,13 @@ pub mod components { pub use preferences::Preferences; } -use components::{post_editor::Post, PostEditorInput}; +use components::{post_editor::{Post, PostConversionSettings}, PostEditorInput}; use soup::prelude::SessionExt; pub mod secrets; pub mod micropub; pub mod util; -pub const APPLICATION_ID: &str = "xyz.vikanezrimaya.kittybox.Bowl"; +pub const APPLICATION_ID: &str = env!("APP_ID"); pub const CLIENT_ID_STR: &str = "https://kittybox.fireburn.ru/bowl/"; #[derive(Debug)] @@ -43,6 +43,7 @@ pub struct App { secret_schema: libsecret::Schema, http: soup::Session, submit_busy_guard: Option<gtk::gio::ApplicationBusyGuard>, + settings: gio::Settings, // TODO: make this support multiple users micropub: Option<micropub::Client>, @@ -415,10 +416,10 @@ impl AsyncComponent for App { set_popover = >k::PopoverMenu::from_model(Some(&main_menu)) {}, #[watch] set_visible: model.micropub.is_some(), - set_icon_name: "menu", + set_icon_name: "menu-symbolic", }, pack_end = >k::Button { - set_icon_name: "document-send-symbolic", + set_icon_name: "paper-plane", set_tooltip: &gettext("Publish"), #[watch] set_visible: model.micropub.is_some(), @@ -473,6 +474,7 @@ impl AsyncComponent for App { http: http.clone(), micropub: state, secret_schema, + settings: gio::Settings::new(crate::APPLICATION_ID), post_editor: { #[cfg(feature = "smart-summary")] @@ -561,7 +563,9 @@ impl AsyncComponent for App { } Input::PostEditor(Some(post)) => { if let Some(micropub) = self.micropub.as_ref() { - let mf2 = post.into(); + let mf2 = post.into_mf2(PostConversionSettings { + send_html_directly: self.settings.get("send-html-directly") + }); log::debug!("Submitting post: {:#}", serde_json::to_string(&mf2).unwrap()); match micropub.send_post(mf2).await { Ok(uri) => { diff --git a/src/meson.build b/src/meson.build index 3bc0c3f..d9adfb7 100644 --- a/src/meson.build +++ b/src/meson.build @@ -20,6 +20,7 @@ cargo_env = [ 'CARGO_HOME=' + meson.project_build_root() / 'cargo-home', 'PKGDATADIR=' + pkgdatadir, 'LOCALEDIR=' + localedir, + 'APP_ID=' + application_id, ] cargo_build = custom_target( |