notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 5848f1c355a24a8a2a84936bda7c889667825ea7
parent 0dcf70bc15c04ee22a665587bafba97725e6c799
Author: Fernando López Guevara <fernando.lguevara@gmail.com>
Date:   Tue, 29 Jul 2025 21:09:33 -0300

refactor(settings): add settings sections methods

Diffstat:
Mcrates/notedeck_columns/src/ui/settings.rs | 605+++++++++++++++++++++++++++++++++++++++----------------------------------------
1 file changed, 298 insertions(+), 307 deletions(-)

diff --git a/crates/notedeck_columns/src/ui/settings.rs b/crates/notedeck_columns/src/ui/settings.rs @@ -130,6 +130,29 @@ pub struct SettingsView<'a> { img_cache: &'a mut Images, } +fn small_richtext(i18n: &'_ mut Localization, text: &str, comment: &str) -> RichText { + RichText::new(tr!(i18n, text, comment)).text_style(NotedeckTextStyle::Small.text_style()) +} + +fn settings_group<S>(ui: &mut egui::Ui, title: S, contents: impl FnOnce(&mut egui::Ui)) +where + S: Into<String>, +{ + Frame::group(ui.style()) + .fill(ui.style().visuals.widgets.open.bg_fill) + .inner_margin(10.0) + .show(ui, |ui| { + ui.label(RichText::new(title).text_style(NotedeckTextStyle::Body.text_style())); + ui.separator(); + + ui.vertical(|ui| { + ui.spacing_mut().item_spacing = vec2(10.0, 10.0); + + contents(ui) + }); + }); +} + impl<'a> SettingsView<'a> { pub fn new( img_cache: &'a mut Images, @@ -180,328 +203,296 @@ impl<'a> SettingsView<'a> { }.to_string() } - pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<SettingsAction> { + pub fn appearance_section(&mut self, ui: &mut egui::Ui) -> Option<SettingsAction> { + let mut action = None; + let title = tr!( + self.i18n, + "Appearance", + "Label for appearance settings section", + ); + settings_group(ui, title, |ui| { + let current_zoom = ui.ctx().zoom_factor(); + + ui.horizontal(|ui| { + ui.label(small_richtext( + self.i18n, + "Zoom Level:", + "Label for zoom level, Appearance settings section", + )); + + if ui + .button(RichText::new("-").text_style(NotedeckTextStyle::Small.text_style())) + .clicked() + { + let new_zoom = (current_zoom - 0.1).max(0.1); + action = Some(SettingsAction::SetZoomFactor(new_zoom)); + }; + + ui.label( + RichText::new(format!("{:.0}%", current_zoom * 100.0)) + .text_style(NotedeckTextStyle::Small.text_style()), + ); + + if ui + .button(RichText::new("+").text_style(NotedeckTextStyle::Small.text_style())) + .clicked() + { + let new_zoom = (current_zoom + 0.1).min(10.0); + action = Some(SettingsAction::SetZoomFactor(new_zoom)); + }; + + if ui + .button(small_richtext( + self.i18n, + "Reset", + "Label for reset zoom level, Appearance settings section", + )) + .clicked() + { + action = Some(SettingsAction::SetZoomFactor(1.0)); + } + }); + + ui.horizontal(|ui| { + ui.label(small_richtext( + self.i18n, + "Language:", + "Label for language, Appearance settings section", + )); + + ComboBox::from_label("") + .selected_text(self.get_selected_language_name()) + .show_ui(ui, |ui| { + for lang in self.i18n.get_available_locales() { + let name = self + .i18n + .get_locale_native_name(lang) + .map(|s| s.to_owned()) + .unwrap_or_else(|| lang.to_string()); + if ui + .selectable_value(self.selected_language, lang.to_string(), name) + .clicked() + { + action = Some(SettingsAction::SetLocale(lang.to_owned())) + } + } + }) + }); + + ui.horizontal(|ui| { + ui.label(small_richtext( + self.i18n, + "Theme:", + "Label for theme, Appearance settings section", + )); + if ui + .selectable_value( + self.theme, + "Light".into(), + small_richtext( + self.i18n, + "Light", + "Label for Theme Light, Appearance settings section", + ), + ) + .clicked() + { + action = Some(SettingsAction::SetTheme(ThemePreference::Light)); + } + if ui + .selectable_value( + self.theme, + "Dark".into(), + small_richtext( + self.i18n, + "Dark", + "Label for Theme Dark, Appearance settings section", + ), + ) + .clicked() + { + action = Some(SettingsAction::SetTheme(ThemePreference::Dark)); + } + }); + }); + + action + } + + pub fn storage_section(&mut self, ui: &mut egui::Ui) -> Option<SettingsAction> { let id = ui.id(); + let mut action: Option<SettingsAction> = None; + let title = tr!(self.i18n, "Storage", "Label for storage settings section"); + settings_group(ui, title, |ui| { + ui.horizontal_wrapped(|ui| { + let static_imgs_size = self.img_cache.static_imgs.cache_size.lock().unwrap(); + + let gifs_size = self.img_cache.gifs.cache_size.lock().unwrap(); + + ui.label( + RichText::new(format!( + "{} {}", + tr!( + self.i18n, + "Image cache size:", + "Label for Image cache size, Storage settings section" + ), + format_size( + [static_imgs_size, gifs_size] + .iter() + .fold(0_u64, |acc, cur| acc + cur.unwrap_or_default()) + ) + )) + .text_style(NotedeckTextStyle::Small.text_style()), + ); + + ui.end_row(); + + if !notedeck::ui::is_compiled_as_mobile() + && ui + .button(small_richtext( + self.i18n, + "View folder", + "Label for view folder button, Storage settings section", + )) + .clicked() + { + action = Some(SettingsAction::OpenCacheFolder); + } + + let clearcache_resp = ui.button( + small_richtext( + self.i18n, + "Clear cache", + "Label for clear cache button, Storage settings section", + ) + .color(Color32::LIGHT_RED), + ); + + let id_clearcache = id.with("clear_cache"); + if clearcache_resp.clicked() { + ui.data_mut(|d| d.insert_temp(id_clearcache, true)); + } + + if ui.data_mut(|d| *d.get_temp_mut_or_default(id_clearcache)) { + let mut confirm_pressed = false; + clearcache_resp.show_tooltip_ui(|ui| { + let confirm_resp = ui.button(tr!( + self.i18n, + "Confirm", + "Label for confirm clear cache, Storage settings section" + )); + if confirm_resp.clicked() { + confirm_pressed = true; + } + + if confirm_resp.clicked() + || ui + .button(tr!( + self.i18n, + "Cancel", + "Label for cancel clear cache, Storage settings section" + )) + .clicked() + { + ui.data_mut(|d| d.insert_temp(id_clearcache, false)); + } + }); + + if confirm_pressed { + action = Some(SettingsAction::ClearCacheFolder); + } else if !confirm_pressed && clearcache_resp.clicked_elsewhere() { + ui.data_mut(|d| d.insert_temp(id_clearcache, false)); + } + }; + }); + }); + + action + } + + fn other_options_section(&mut self, ui: &mut egui::Ui) -> Option<SettingsAction> { let mut action = None; + let title = tr!(self.i18n, "Others", "Label for others settings section"); + settings_group(ui, title, |ui| { + ui.horizontal_wrapped(|ui| { + ui.label(small_richtext( + self.i18n, + "Show source client", + "Label for Show source client, others settings section", + )); + + for option in [ + ShowSourceClientOption::Hide, + ShowSourceClientOption::Top, + ShowSourceClientOption::Bottom, + ] { + let label = self.get_show_note_client_label(option); + + if ui + .selectable_value( + self.show_note_client, + option, + RichText::new(label).text_style(NotedeckTextStyle::Small.text_style()), + ) + .changed() + { + action = Some(SettingsAction::SetShowSourceClient(option)); + } + } + }); + }); + + action + } + + fn manage_relays_section(&mut self, ui: &mut egui::Ui) -> Option<SettingsAction> { + let mut action = None; + + if ui + .add_sized( + [ui.available_width(), 30.0], + Button::new(small_richtext( + self.i18n, + "Configure relays", + "Label for configure relays, settings section", + )), + ) + .clicked() + { + action = Some(SettingsAction::OpenRelays); + } + + action + } + + pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<SettingsAction> { + let mut action: Option<SettingsAction> = None; + Frame::default() .inner_margin(Margin::symmetric(10, 10)) .show(ui, |ui| { - Frame::group(ui.style()) - .fill(ui.style().visuals.widgets.open.bg_fill) - .inner_margin(10.0) - .show(ui, |ui| { - ui.vertical(|ui| { - ui.label( - RichText::new(tr!( - self.i18n, - "Appearance", - "Label for appearance settings section" - )) - .text_style(NotedeckTextStyle::Body.text_style()), - ); - ui.separator(); - ui.spacing_mut().item_spacing = vec2(10.0, 10.0); - - let current_zoom = ui.ctx().zoom_factor(); - - ui.horizontal(|ui| { - ui.label( - RichText::new(tr!( - self.i18n, - "Zoom Level:", - "Label for zoom level, Appearance settings section" - )) - .text_style(NotedeckTextStyle::Small.text_style()), - ); - - if ui - .button( - RichText::new("-") - .text_style(NotedeckTextStyle::Small.text_style()), - ) - .clicked() - { - let new_zoom = (current_zoom - 0.1).max(0.1); - action = Some(SettingsAction::SetZoomFactor(new_zoom)); - }; - - ui.label( - RichText::new(format!("{:.0}%", current_zoom * 100.0)) - .text_style(NotedeckTextStyle::Small.text_style()), - ); - - if ui - .button( - RichText::new("+") - .text_style(NotedeckTextStyle::Small.text_style()), - ) - .clicked() - { - let new_zoom = (current_zoom + 0.1).min(10.0); - action = Some(SettingsAction::SetZoomFactor(new_zoom)); - }; - - if ui - .button( - RichText::new(tr!( - self.i18n, - "Reset", - "Label for reset zoom level, Appearance settings section" - )) - .text_style(NotedeckTextStyle::Small.text_style()), - ) - .clicked() - { - action = Some(SettingsAction::SetZoomFactor(1.0)); - } - }); - - ui.horizontal(|ui| { - ui.label( - RichText::new(tr!( - self.i18n, - "Language:", - "Label for language, Appearance settings section" - )) - .text_style(NotedeckTextStyle::Small.text_style()), - ); - ComboBox::from_label("") - .selected_text(self.get_selected_language_name()) - .show_ui(ui, |ui| { - for lang in self.i18n.get_available_locales() { - let name = self.i18n - .get_locale_native_name(lang) - .map(|s| s.to_owned()) - .unwrap_or_else(|| lang.to_string()); - if ui - .selectable_value( - self.selected_language, - lang.to_string(), - name, - ) - .clicked() - { - action = Some(SettingsAction::SetLocale(lang.to_owned())) - } - } - }) - }); - - ui.horizontal(|ui| { - ui.label( - RichText::new(tr!( - self.i18n, - "Theme:", - "Label for theme, Appearance settings section" - )) - .text_style(NotedeckTextStyle::Small.text_style()), - ); - if ui - .selectable_value( - self.theme, - "Light".into(), - RichText::new(tr!( - self.i18n, - "Light", - "Label for Theme Light, Appearance settings section" - )) - .text_style(NotedeckTextStyle::Small.text_style()), - ) - .clicked() - { - action = Some(SettingsAction::SetTheme(ThemePreference::Light)); - } - if ui - .selectable_value( - self.theme, - "Dark".into(), - RichText::new(tr!( - self.i18n, - "Dark", - "Label for Theme Dark, Appearance settings section" - )) - .text_style(NotedeckTextStyle::Small.text_style()), - ) - .clicked() - { - action = Some(SettingsAction::SetTheme(ThemePreference::Dark)); - } - }); - }); - }); + if let Some(new_action) = self.appearance_section(ui) { + action = Some(new_action); + } ui.add_space(5.0); - Frame::group(ui.style()) - .fill(ui.style().visuals.widgets.open.bg_fill) - .inner_margin(10.0) - .show(ui, |ui| { - ui.label( - RichText::new(tr!( - self.i18n, - "Storage", - "Label for storage settings section" - )) - .text_style(NotedeckTextStyle::Body.text_style()), - ); - ui.separator(); - - ui.vertical(|ui| { - ui.spacing_mut().item_spacing = vec2(10.0, 10.0); - - ui.horizontal_wrapped(|ui| { - let static_imgs_size = self - .img_cache - .static_imgs - .cache_size - .lock() - .unwrap(); - - let gifs_size = self.img_cache.gifs.cache_size.lock().unwrap(); - - ui.label( - RichText::new(format!("{} {}", - tr!( - self.i18n, - "Image cache size:", - "Label for Image cache size, Storage settings section" - ), - format_size( - [static_imgs_size, gifs_size] - .iter() - .fold(0_u64, |acc, cur| acc - + cur.unwrap_or_default()) - ) - )) - .text_style(NotedeckTextStyle::Small.text_style()), - ); - - ui.end_row(); - - if !notedeck::ui::is_compiled_as_mobile() && - ui.button(RichText::new(tr!(self.i18n, "View folder", "Label for view folder button, Storage settings section")) - .text_style(NotedeckTextStyle::Small.text_style())).clicked() { - action = Some(SettingsAction::OpenCacheFolder); - } - - let clearcache_resp = ui.button( - RichText::new(tr!( - self.i18n, - "Clear cache", - "Label for clear cache button, Storage settings section" - )) - .text_style(NotedeckTextStyle::Small.text_style()) - .color(Color32::LIGHT_RED), - ); - - let id_clearcache = id.with("clear_cache"); - if clearcache_resp.clicked() { - ui.data_mut(|d| d.insert_temp(id_clearcache, true)); - } - - if ui.data_mut(|d| *d.get_temp_mut_or_default(id_clearcache)) { - let mut confirm_pressed = false; - clearcache_resp.show_tooltip_ui(|ui| { - let confirm_resp = ui.button(tr!( - self.i18n, - "Confirm", - "Label for confirm clear cache, Storage settings section" - )); - if confirm_resp.clicked() { - confirm_pressed = true; - } - - if confirm_resp.clicked() || ui.button(tr!( - self.i18n, - "Cancel", - "Label for cancel clear cache, Storage settings section" - )).clicked() { - ui.data_mut(|d| d.insert_temp(id_clearcache, false)); - } - }); - - if confirm_pressed { - action = Some(SettingsAction::ClearCacheFolder); - } else if !confirm_pressed - && clearcache_resp.clicked_elsewhere() - { - ui.data_mut(|d| d.insert_temp(id_clearcache, false)); - } - }; - }); - }); - }); + if let Some(new_action) = self.storage_section(ui) { + action = Some(new_action); + } ui.add_space(5.0); - Frame::group(ui.style()) - .fill(ui.style().visuals.widgets.open.bg_fill) - .inner_margin(10.0) - .show(ui, |ui| { - ui.label( - RichText::new(tr!( - self.i18n, - "Others", - "Label for others settings section" - )) - .text_style(NotedeckTextStyle::Body.text_style()), - ); - ui.separator(); - ui.vertical(|ui| { - ui.spacing_mut().item_spacing = vec2(10.0, 10.0); - - ui.horizontal_wrapped(|ui| { - ui.label( - RichText::new( - tr!( - self.i18n, - "Show source client", - "Label for Show source client, others settings section" - )) - .text_style(NotedeckTextStyle::Small.text_style()), - ); - - for option in [ - ShowSourceClientOption::Hide, - ShowSourceClientOption::Top, - ShowSourceClientOption::Bottom, - ] { - let label = self.get_show_note_client_label(option); - - if ui - .selectable_value( - self.show_note_client, - option, - RichText::new(label) - .text_style(NotedeckTextStyle::Small.text_style()), - ) - .changed() - { - action = Some(SettingsAction::SetShowSourceClient(option)); - } - } - }); - }); - }); + if let Some(new_action) = self.other_options_section(ui) { + action = Some(new_action); + } ui.add_space(10.0); - if ui - .add_sized( - [ui.available_width(), 30.0], - Button::new( - RichText::new(tr!( - self.i18n, - "Configure relays", - "Label for configure relays, settings section" - )) - .text_style(NotedeckTextStyle::Small.text_style()), - ), - ) - .clicked() - { - action = Some(SettingsAction::OpenRelays); + if let Some(new_action) = self.manage_relays_section(ui) { + action = Some(new_action); } });