feat(settings): allow sorting thread replies newest first
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
use egui::{vec2, Button, Color32, ComboBox, Frame, Margin, RichText, ThemePreference};
|
||||
use notedeck::{tr, Images, LanguageIdentifier, Localization, NotedeckTextStyle, SettingsHandler};
|
||||
use egui::{vec2, Button, Color32, ComboBox, Frame, Margin, RichText, ScrollArea, ThemePreference};
|
||||
use notedeck::{
|
||||
tr, Images, LanguageIdentifier, Localization, NotedeckTextStyle, Settings, SettingsHandler,
|
||||
};
|
||||
use notedeck_ui::NoteOptions;
|
||||
use strum::Display;
|
||||
|
||||
@@ -97,6 +99,7 @@ pub enum SettingsAction {
|
||||
SetTheme(ThemePreference),
|
||||
SetShowSourceClient(ShowSourceClientOption),
|
||||
SetLocale(LanguageIdentifier),
|
||||
SetRepliestNewestFirst(bool),
|
||||
OpenRelays,
|
||||
OpenCacheFolder,
|
||||
ClearCacheFolder,
|
||||
@@ -135,6 +138,11 @@ impl SettingsAction {
|
||||
settings_handler.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();
|
||||
}
|
||||
Self::OpenCacheFolder => {
|
||||
use opener;
|
||||
let _ = opener::open(img_cache.base_path.clone());
|
||||
@@ -149,9 +157,7 @@ impl SettingsAction {
|
||||
}
|
||||
|
||||
pub struct SettingsView<'a> {
|
||||
theme: &'a mut String,
|
||||
selected_language: &'a mut String,
|
||||
show_note_client: &'a mut ShowSourceClientOption,
|
||||
settings: &'a mut Settings,
|
||||
i18n: &'a mut Localization,
|
||||
img_cache: &'a mut Images,
|
||||
}
|
||||
@@ -181,30 +187,30 @@ where
|
||||
|
||||
impl<'a> SettingsView<'a> {
|
||||
pub fn new(
|
||||
img_cache: &'a mut Images,
|
||||
selected_language: &'a mut String,
|
||||
theme: &'a mut String,
|
||||
show_note_client: &'a mut ShowSourceClientOption,
|
||||
i18n: &'a mut Localization,
|
||||
img_cache: &'a mut Images,
|
||||
settings: &'a mut Settings,
|
||||
// theme: &'a mut String,
|
||||
// show_note_client: &'a mut ShowSourceClientOption,
|
||||
// show_wide: &'a mut bool,
|
||||
// show_replies_newest_first: &'a mut bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
show_note_client,
|
||||
theme,
|
||||
settings,
|
||||
img_cache,
|
||||
selected_language,
|
||||
i18n,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the localized name for a language identifier
|
||||
fn get_selected_language_name(&mut self) -> String {
|
||||
if let Ok(lang_id) = self.selected_language.parse::<LanguageIdentifier>() {
|
||||
if let Ok(lang_id) = self.settings.locale.parse::<LanguageIdentifier>() {
|
||||
self.i18n
|
||||
.get_locale_native_name(&lang_id)
|
||||
.map(|s| s.to_owned())
|
||||
.unwrap_or_else(|| lang_id.to_string())
|
||||
} else {
|
||||
self.selected_language.clone()
|
||||
self.settings.locale.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +295,7 @@ impl<'a> SettingsView<'a> {
|
||||
.map(|s| s.to_owned())
|
||||
.unwrap_or_else(|| lang.to_string());
|
||||
if ui
|
||||
.selectable_value(self.selected_language, lang.to_string(), name)
|
||||
.selectable_value(&mut self.settings.locale, lang.to_string(), name)
|
||||
.clicked()
|
||||
{
|
||||
action = Some(SettingsAction::SetLocale(lang.to_owned()))
|
||||
@@ -304,10 +310,11 @@ impl<'a> SettingsView<'a> {
|
||||
"Theme:",
|
||||
"Label for theme, Appearance settings section",
|
||||
));
|
||||
|
||||
if ui
|
||||
.selectable_value(
|
||||
self.theme,
|
||||
THEME_LIGHT.into(),
|
||||
&mut self.settings.theme,
|
||||
ThemePreference::Light,
|
||||
small_richtext(
|
||||
self.i18n,
|
||||
THEME_LIGHT.into(),
|
||||
@@ -318,10 +325,11 @@ impl<'a> SettingsView<'a> {
|
||||
{
|
||||
action = Some(SettingsAction::SetTheme(ThemePreference::Light));
|
||||
}
|
||||
|
||||
if ui
|
||||
.selectable_value(
|
||||
self.theme,
|
||||
THEME_DARK.into(),
|
||||
&mut self.settings.theme,
|
||||
ThemePreference::Dark,
|
||||
small_richtext(
|
||||
self.i18n,
|
||||
THEME_DARK.into(),
|
||||
@@ -435,11 +443,32 @@ impl<'a> SettingsView<'a> {
|
||||
|
||||
let title = tr!(self.i18n, "Others", "Label for others settings section");
|
||||
settings_group(ui, title, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(small_richtext(
|
||||
self.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"))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
)
|
||||
.changed()
|
||||
{
|
||||
action = Some(SettingsAction::SetRepliestNewestFirst(
|
||||
self.settings.show_replies_newest_first,
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
ui.label(small_richtext(
|
||||
self.i18n,
|
||||
"Show source client",
|
||||
"Label for Show source client, others settings section",
|
||||
"Source client",
|
||||
"Label for Source client, others settings section",
|
||||
));
|
||||
|
||||
for option in [
|
||||
@@ -447,9 +476,12 @@ impl<'a> SettingsView<'a> {
|
||||
ShowSourceClientOption::Top,
|
||||
ShowSourceClientOption::Bottom,
|
||||
] {
|
||||
let mut current: ShowSourceClientOption =
|
||||
self.settings.show_source_client.clone().into();
|
||||
|
||||
if ui
|
||||
.selectable_value(
|
||||
self.show_note_client,
|
||||
&mut current,
|
||||
option,
|
||||
RichText::new(option.label(self.i18n))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
@@ -491,27 +523,29 @@ impl<'a> SettingsView<'a> {
|
||||
Frame::default()
|
||||
.inner_margin(Margin::symmetric(10, 10))
|
||||
.show(ui, |ui| {
|
||||
if let Some(new_action) = self.appearance_section(ui) {
|
||||
action = Some(new_action);
|
||||
}
|
||||
ScrollArea::vertical().show(ui, |ui| {
|
||||
if let Some(new_action) = self.appearance_section(ui) {
|
||||
action = Some(new_action);
|
||||
}
|
||||
|
||||
ui.add_space(5.0);
|
||||
ui.add_space(5.0);
|
||||
|
||||
if let Some(new_action) = self.storage_section(ui) {
|
||||
action = Some(new_action);
|
||||
}
|
||||
if let Some(new_action) = self.storage_section(ui) {
|
||||
action = Some(new_action);
|
||||
}
|
||||
|
||||
ui.add_space(5.0);
|
||||
ui.add_space(5.0);
|
||||
|
||||
if let Some(new_action) = self.other_options_section(ui) {
|
||||
action = Some(new_action);
|
||||
}
|
||||
if let Some(new_action) = self.other_options_section(ui) {
|
||||
action = Some(new_action);
|
||||
}
|
||||
|
||||
ui.add_space(10.0);
|
||||
ui.add_space(10.0);
|
||||
|
||||
if let Some(new_action) = self.manage_relays_section(ui) {
|
||||
action = Some(new_action);
|
||||
}
|
||||
if let Some(new_action) = self.manage_relays_section(ui) {
|
||||
action = Some(new_action);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
action
|
||||
|
||||
@@ -115,7 +115,10 @@ impl<'a, 'd> ThreadView<'a, 'd> {
|
||||
.unwrap()
|
||||
.list;
|
||||
|
||||
let notes = note_builder.into_notes(&mut self.threads.seen_flags);
|
||||
let notes = note_builder.into_notes(
|
||||
self.note_options.contains(NoteOptions::RepliesNewestFirst),
|
||||
&mut self.threads.seen_flags,
|
||||
);
|
||||
|
||||
if !full_chain {
|
||||
// TODO(kernelkind): insert UI denoting we don't have the full chain yet
|
||||
@@ -223,7 +226,11 @@ impl<'a> ThreadNoteBuilder<'a> {
|
||||
self.replies.push(note);
|
||||
}
|
||||
|
||||
pub fn into_notes(mut self, seen_flags: &mut NoteSeenFlags) -> ThreadNotes<'a> {
|
||||
pub fn into_notes(
|
||||
mut self,
|
||||
replies_newer_first: bool,
|
||||
seen_flags: &mut NoteSeenFlags,
|
||||
) -> ThreadNotes<'a> {
|
||||
let mut notes = Vec::new();
|
||||
|
||||
let selected_is_root = self.chain.is_empty();
|
||||
@@ -246,6 +253,11 @@ impl<'a> ThreadNoteBuilder<'a> {
|
||||
unread_and_have_replies: false,
|
||||
});
|
||||
|
||||
if replies_newer_first {
|
||||
self.replies
|
||||
.sort_by(|a, b| b.created_at().cmp(&a.created_at()));
|
||||
}
|
||||
|
||||
for reply in self.replies {
|
||||
notes.push(ThreadNote {
|
||||
unread_and_have_replies: *seen_flags.get(reply.id()).unwrap_or(&false),
|
||||
|
||||
Reference in New Issue
Block a user