settings: use timed serializer, handle zoom properly, use custom text style for note body font size, added font size slider, added preview note
This commit is contained in:
@@ -18,9 +18,13 @@ use egui_extras::{Size, StripBuilder};
|
||||
use enostr::{ClientMessage, PoolRelay, Pubkey, RelayEvent, RelayMessage, RelayPool};
|
||||
use nostrdb::Transaction;
|
||||
use notedeck::{
|
||||
tr, ui::is_narrow, Accounts, AppAction, AppContext, DataPath, DataPathType, FilterState, Images, JobsCache, Localization, SettingsHandler, UnknownIds
|
||||
tr, ui::is_narrow, Accounts, AppAction, AppContext, DataPath, DataPathType, FilterState,
|
||||
Images, JobsCache, Localization, SettingsHandler, UnknownIds,
|
||||
};
|
||||
use notedeck_ui::{
|
||||
media::{MediaViewer, MediaViewerFlags, MediaViewerState},
|
||||
NoteOptions,
|
||||
};
|
||||
use notedeck_ui::{media::{MediaViewer, MediaViewerFlags, MediaViewerState}, NoteOptions};
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
@@ -487,11 +491,11 @@ impl Damus {
|
||||
// cache.add_deck_default(*pk);
|
||||
//}
|
||||
};
|
||||
let settings_handler = &app_context.settings_handler;
|
||||
let settings = &app_context.settings;
|
||||
|
||||
let support = Support::new(app_context.path);
|
||||
|
||||
let note_options = get_note_options(parsed_args, settings_handler);
|
||||
let note_options = get_note_options(parsed_args, settings);
|
||||
|
||||
let jobs = JobsCache::default();
|
||||
|
||||
|
||||
@@ -485,13 +485,9 @@ fn process_render_nav_action(
|
||||
.process_relay_action(ui.ctx(), ctx.pool, action);
|
||||
None
|
||||
}
|
||||
RenderNavAction::SettingsAction(action) => action.process_settings_action(
|
||||
app,
|
||||
ctx.settings_handler,
|
||||
ctx.i18n,
|
||||
ctx.img_cache,
|
||||
ui.ctx(),
|
||||
),
|
||||
RenderNavAction::SettingsAction(action) => {
|
||||
action.process_settings_action(app, ctx.settings, ctx.i18n, ctx.img_cache, ui.ctx())
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(action) = router_action {
|
||||
@@ -585,13 +581,14 @@ fn render_nav_body(
|
||||
.ui(ui)
|
||||
.map(RenderNavAction::RelayAction),
|
||||
|
||||
Route::Settings => {
|
||||
let mut settings = ctx.settings_handler.get_settings_mut();
|
||||
|
||||
SettingsView::new(ctx.i18n, ctx.img_cache, &mut settings)
|
||||
.ui(ui)
|
||||
.map(RenderNavAction::SettingsAction)
|
||||
}
|
||||
Route::Settings => SettingsView::new(
|
||||
&mut ctx.settings.get_settings_mut(),
|
||||
&mut note_context,
|
||||
&mut app.note_options,
|
||||
&mut app.jobs,
|
||||
)
|
||||
.ui(ui)
|
||||
.map(RenderNavAction::SettingsAction),
|
||||
Route::Reply(id) => {
|
||||
let txn = if let Ok(txn) = Transaction::new(ctx.ndb) {
|
||||
txn
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
use egui::{vec2, Button, Color32, ComboBox, Frame, Margin, RichText, ScrollArea, ThemePreference};
|
||||
use notedeck::{
|
||||
tr, Images, LanguageIdentifier, Localization, NotedeckTextStyle, Settings, SettingsHandler,
|
||||
use egui::{
|
||||
vec2, Button, Color32, ComboBox, FontId, Frame, Margin, RichText, ScrollArea, ThemePreference,
|
||||
};
|
||||
use notedeck_ui::NoteOptions;
|
||||
use enostr::NoteId;
|
||||
use nostrdb::Transaction;
|
||||
use notedeck::{
|
||||
tr,
|
||||
ui::{is_narrow, richtext_small},
|
||||
Images, JobsCache, LanguageIdentifier, Localization, NoteContext, NotedeckTextStyle, Settings,
|
||||
SettingsHandler, DEFAULT_NOTE_BODY_FONT_SIZE,
|
||||
};
|
||||
use notedeck_ui::{NoteOptions, NoteView};
|
||||
use strum::Display;
|
||||
|
||||
use crate::{nav::RouterAction, Damus, Route};
|
||||
|
||||
const PREVIEW_NOTE_ID: &str = "note1edjc8ggj07hwv77g2405uh6j2jkk5aud22gktxrvc2wnre4vdwgqzlv2gw";
|
||||
|
||||
const THEME_LIGHT: &str = "Light";
|
||||
const THEME_DARK: &str = "Dark";
|
||||
|
||||
@@ -88,6 +97,7 @@ pub enum SettingsAction {
|
||||
SetShowSourceClient(ShowSourceClientOption),
|
||||
SetLocale(LanguageIdentifier),
|
||||
SetRepliestNewestFirst(bool),
|
||||
SetNoteBodyFontSize(f32),
|
||||
OpenRelays,
|
||||
OpenCacheFolder,
|
||||
ClearCacheFolder,
|
||||
@@ -97,7 +107,7 @@ impl SettingsAction {
|
||||
pub fn process_settings_action<'a>(
|
||||
self,
|
||||
app: &mut Damus,
|
||||
settings_handler: &'a mut SettingsHandler,
|
||||
settings: &'a mut SettingsHandler,
|
||||
i18n: &'a mut Localization,
|
||||
img_cache: &mut Images,
|
||||
ctx: &egui::Context,
|
||||
@@ -110,26 +120,25 @@ impl SettingsAction {
|
||||
}
|
||||
Self::SetZoomFactor(zoom_factor) => {
|
||||
ctx.set_zoom_factor(zoom_factor);
|
||||
settings_handler.set_zoom_factor(zoom_factor);
|
||||
settings.set_zoom_factor(zoom_factor);
|
||||
}
|
||||
Self::SetShowSourceClient(option) => {
|
||||
option.set_note_options(&mut app.note_options);
|
||||
|
||||
settings_handler.set_show_source_client(option);
|
||||
settings.set_show_source_client(option);
|
||||
}
|
||||
Self::SetTheme(theme) => {
|
||||
ctx.set_theme(theme);
|
||||
settings_handler.set_theme(theme);
|
||||
settings.set_theme(theme);
|
||||
}
|
||||
Self::SetLocale(language) => {
|
||||
if i18n.set_locale(language.clone()).is_ok() {
|
||||
settings_handler.set_locale(language.to_string());
|
||||
settings.set_locale(language.to_string());
|
||||
}
|
||||
}
|
||||
Self::SetRepliestNewestFirst(value) => {
|
||||
app.note_options.set(NoteOptions::RepliesNewestFirst, value);
|
||||
settings_handler.set_show_replies_newest_first(value);
|
||||
settings_handler.save();
|
||||
settings.set_show_replies_newest_first(value);
|
||||
}
|
||||
Self::OpenCacheFolder => {
|
||||
use opener;
|
||||
@@ -138,20 +147,26 @@ impl SettingsAction {
|
||||
Self::ClearCacheFolder => {
|
||||
let _ = img_cache.clear_folder_contents();
|
||||
}
|
||||
Self::SetNoteBodyFontSize(size) => {
|
||||
let mut style = (*ctx.style()).clone();
|
||||
style.text_styles.insert(
|
||||
NotedeckTextStyle::NoteBody.text_style(),
|
||||
FontId::proportional(size),
|
||||
);
|
||||
ctx.set_style(style);
|
||||
|
||||
settings.set_note_body_font_size(size);
|
||||
}
|
||||
}
|
||||
settings_handler.save();
|
||||
route_action
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SettingsView<'a> {
|
||||
settings: &'a mut Settings,
|
||||
i18n: &'a mut Localization,
|
||||
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())
|
||||
note_context: &'a mut NoteContext<'a>,
|
||||
note_options: &'a mut NoteOptions,
|
||||
jobs: &'a mut JobsCache,
|
||||
}
|
||||
|
||||
fn settings_group<S>(ui: &mut egui::Ui, title: S, contents: impl FnOnce(&mut egui::Ui))
|
||||
@@ -175,21 +190,24 @@ where
|
||||
|
||||
impl<'a> SettingsView<'a> {
|
||||
pub fn new(
|
||||
i18n: &'a mut Localization,
|
||||
img_cache: &'a mut Images,
|
||||
settings: &'a mut Settings,
|
||||
note_context: &'a mut NoteContext<'a>,
|
||||
note_options: &'a mut NoteOptions,
|
||||
jobs: &'a mut JobsCache,
|
||||
) -> Self {
|
||||
Self {
|
||||
settings,
|
||||
img_cache,
|
||||
i18n,
|
||||
note_context,
|
||||
note_options,
|
||||
jobs,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the localized name for a language identifier
|
||||
fn get_selected_language_name(&mut self) -> String {
|
||||
if let Ok(lang_id) = self.settings.locale.parse::<LanguageIdentifier>() {
|
||||
self.i18n
|
||||
self.note_context
|
||||
.i18n
|
||||
.get_locale_native_name(&lang_id)
|
||||
.map(|s| s.to_owned())
|
||||
.unwrap_or_else(|| lang_id.to_string())
|
||||
@@ -201,19 +219,76 @@ impl<'a> SettingsView<'a> {
|
||||
pub fn appearance_section(&mut self, ui: &mut egui::Ui) -> Option<SettingsAction> {
|
||||
let mut action = None;
|
||||
let title = tr!(
|
||||
self.i18n,
|
||||
self.note_context.i18n,
|
||||
"Appearance",
|
||||
"Label for appearance settings section",
|
||||
);
|
||||
settings_group(ui, title, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(richtext_small(tr!(
|
||||
self.note_context.i18n,
|
||||
"Font size:",
|
||||
"Label for font size, Appearance settings section",
|
||||
)));
|
||||
|
||||
if ui
|
||||
.add(
|
||||
egui::Slider::new(&mut self.settings.note_body_font_size, 8.0..=32.0)
|
||||
.text(""),
|
||||
)
|
||||
.changed()
|
||||
{
|
||||
action = Some(SettingsAction::SetNoteBodyFontSize(
|
||||
self.settings.note_body_font_size,
|
||||
));
|
||||
};
|
||||
|
||||
if ui
|
||||
.button(richtext_small(tr!(
|
||||
self.note_context.i18n,
|
||||
"Reset",
|
||||
"Label for reset note body font size, Appearance settings section",
|
||||
)))
|
||||
.clicked()
|
||||
{
|
||||
action = Some(SettingsAction::SetNoteBodyFontSize(
|
||||
DEFAULT_NOTE_BODY_FONT_SIZE,
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
let txn = Transaction::new(self.note_context.ndb).unwrap();
|
||||
if let Some(note_id) = NoteId::from_bech(PREVIEW_NOTE_ID) {
|
||||
if let Ok(preview_note) =
|
||||
self.note_context.ndb.get_note_by_id(&txn, ¬e_id.bytes())
|
||||
{
|
||||
notedeck_ui::padding(8.0, ui, |ui| {
|
||||
if is_narrow(ui.ctx()) {
|
||||
ui.set_max_width(ui.available_width());
|
||||
}
|
||||
|
||||
NoteView::new(
|
||||
self.note_context,
|
||||
&preview_note,
|
||||
self.note_options.clone(),
|
||||
self.jobs,
|
||||
)
|
||||
.actionbar(false)
|
||||
.options_button(false)
|
||||
.show(ui);
|
||||
});
|
||||
ui.separator();
|
||||
}
|
||||
}
|
||||
|
||||
let current_zoom = ui.ctx().zoom_factor();
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(small_richtext(
|
||||
self.i18n,
|
||||
ui.label(richtext_small(tr!(
|
||||
self.note_context.i18n,
|
||||
"Zoom Level:",
|
||||
"Label for zoom level, Appearance settings section",
|
||||
));
|
||||
)));
|
||||
|
||||
let min_reached = current_zoom <= MIN_ZOOM;
|
||||
let max_reached = current_zoom >= MAX_ZOOM;
|
||||
@@ -250,11 +325,11 @@ impl<'a> SettingsView<'a> {
|
||||
};
|
||||
|
||||
if ui
|
||||
.button(small_richtext(
|
||||
self.i18n,
|
||||
.button(richtext_small(tr!(
|
||||
self.note_context.i18n,
|
||||
"Reset",
|
||||
"Label for reset zoom level, Appearance settings section",
|
||||
))
|
||||
)))
|
||||
.clicked()
|
||||
{
|
||||
action = Some(SettingsAction::SetZoomFactor(RESET_ZOOM));
|
||||
@@ -262,18 +337,19 @@ impl<'a> SettingsView<'a> {
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(small_richtext(
|
||||
self.i18n,
|
||||
ui.label(richtext_small(tr!(
|
||||
self.note_context.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() {
|
||||
for lang in self.note_context.i18n.get_available_locales() {
|
||||
let name = self
|
||||
.note_context
|
||||
.i18n
|
||||
.get_locale_native_name(lang)
|
||||
.map(|s| s.to_owned())
|
||||
@@ -289,21 +365,21 @@ impl<'a> SettingsView<'a> {
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(small_richtext(
|
||||
self.i18n,
|
||||
ui.label(richtext_small(tr!(
|
||||
self.note_context.i18n,
|
||||
"Theme:",
|
||||
"Label for theme, Appearance settings section",
|
||||
));
|
||||
)));
|
||||
|
||||
if ui
|
||||
.selectable_value(
|
||||
&mut self.settings.theme,
|
||||
ThemePreference::Light,
|
||||
small_richtext(
|
||||
self.i18n,
|
||||
THEME_LIGHT.into(),
|
||||
richtext_small(tr!(
|
||||
self.note_context.i18n,
|
||||
THEME_LIGHT,
|
||||
"Label for Theme Light, Appearance settings section",
|
||||
),
|
||||
)),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
@@ -314,11 +390,11 @@ impl<'a> SettingsView<'a> {
|
||||
.selectable_value(
|
||||
&mut self.settings.theme,
|
||||
ThemePreference::Dark,
|
||||
small_richtext(
|
||||
self.i18n,
|
||||
THEME_DARK.into(),
|
||||
richtext_small(tr!(
|
||||
self.note_context.i18n,
|
||||
THEME_DARK,
|
||||
"Label for Theme Dark, Appearance settings section",
|
||||
),
|
||||
)),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
@@ -333,18 +409,28 @@ impl<'a> SettingsView<'a> {
|
||||
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");
|
||||
let title = tr!(
|
||||
self.note_context.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 static_imgs_size = self
|
||||
.note_context
|
||||
.img_cache
|
||||
.static_imgs
|
||||
.cache_size
|
||||
.lock()
|
||||
.unwrap();
|
||||
|
||||
let gifs_size = self.img_cache.gifs.cache_size.lock().unwrap();
|
||||
let gifs_size = self.note_context.img_cache.gifs.cache_size.lock().unwrap();
|
||||
|
||||
ui.label(
|
||||
RichText::new(format!(
|
||||
"{} {}",
|
||||
tr!(
|
||||
self.i18n,
|
||||
self.note_context.i18n,
|
||||
"Image cache size:",
|
||||
"Label for Image cache size, Storage settings section"
|
||||
),
|
||||
@@ -361,22 +447,22 @@ impl<'a> SettingsView<'a> {
|
||||
|
||||
if !notedeck::ui::is_compiled_as_mobile()
|
||||
&& ui
|
||||
.button(small_richtext(
|
||||
self.i18n,
|
||||
.button(richtext_small(tr!(
|
||||
self.note_context.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,
|
||||
richtext_small(tr!(
|
||||
self.note_context.i18n,
|
||||
"Clear cache",
|
||||
"Label for clear cache button, Storage settings section",
|
||||
)
|
||||
))
|
||||
.color(Color32::LIGHT_RED),
|
||||
);
|
||||
|
||||
@@ -389,7 +475,7 @@ impl<'a> SettingsView<'a> {
|
||||
let mut confirm_pressed = false;
|
||||
clearcache_resp.show_tooltip_ui(|ui| {
|
||||
let confirm_resp = ui.button(tr!(
|
||||
self.i18n,
|
||||
self.note_context.i18n,
|
||||
"Confirm",
|
||||
"Label for confirm clear cache, Storage settings section"
|
||||
));
|
||||
@@ -400,7 +486,7 @@ impl<'a> SettingsView<'a> {
|
||||
if confirm_resp.clicked()
|
||||
|| ui
|
||||
.button(tr!(
|
||||
self.i18n,
|
||||
self.note_context.i18n,
|
||||
"Cancel",
|
||||
"Label for cancel clear cache, Storage settings section"
|
||||
))
|
||||
@@ -425,19 +511,23 @@ impl<'a> SettingsView<'a> {
|
||||
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");
|
||||
let title = tr!(
|
||||
self.note_context.i18n,
|
||||
"Others",
|
||||
"Label for others settings section"
|
||||
);
|
||||
settings_group(ui, title, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(small_richtext(
|
||||
self.i18n,
|
||||
ui.label(richtext_small(tr!(
|
||||
self.note_context.i18n,
|
||||
"Sort replies newest first",
|
||||
"Label for Sort replies newest first, others settings section",
|
||||
));
|
||||
)));
|
||||
|
||||
if ui
|
||||
.toggle_value(
|
||||
&mut self.settings.show_replies_newest_first,
|
||||
RichText::new(tr!(self.i18n, "ON", "ON"))
|
||||
RichText::new(tr!(self.note_context.i18n, "ON", "ON"))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
)
|
||||
.changed()
|
||||
@@ -449,11 +539,11 @@ impl<'a> SettingsView<'a> {
|
||||
});
|
||||
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
ui.label(small_richtext(
|
||||
self.i18n,
|
||||
ui.label(richtext_small(tr!(
|
||||
self.note_context.i18n,
|
||||
"Source client",
|
||||
"Label for Source client, others settings section",
|
||||
));
|
||||
)));
|
||||
|
||||
for option in [
|
||||
ShowSourceClientOption::Hide,
|
||||
@@ -467,7 +557,7 @@ impl<'a> SettingsView<'a> {
|
||||
.selectable_value(
|
||||
&mut current,
|
||||
option,
|
||||
RichText::new(option.label(self.i18n))
|
||||
RichText::new(option.label(self.note_context.i18n))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
)
|
||||
.changed()
|
||||
@@ -487,11 +577,11 @@ impl<'a> SettingsView<'a> {
|
||||
if ui
|
||||
.add_sized(
|
||||
[ui.available_width(), 30.0],
|
||||
Button::new(small_richtext(
|
||||
self.i18n,
|
||||
Button::new(richtext_small(tr!(
|
||||
self.note_context.i18n,
|
||||
"Configure relays",
|
||||
"Label for configure relays, settings section",
|
||||
)),
|
||||
))),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user