refactor: apply limit on the number of persisted sort names
This commit is contained in:
parent
84b73b0bdc
commit
e4ffec63a1
5 changed files with 61 additions and 16 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
|
@ -1512,6 +1512,7 @@ dependencies = [
|
||||||
"notify-rust",
|
"notify-rust",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"open",
|
"open",
|
||||||
|
"ordermap",
|
||||||
"paste",
|
"paste",
|
||||||
"procfs",
|
"procfs",
|
||||||
"recently-used-xbel",
|
"recently-used-xbel",
|
||||||
|
|
@ -5326,6 +5327,16 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordermap"
|
||||||
|
version = "0.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d6bff06e4a5dc6416bead102d3e63c480dd852ffbb278bf8cfeb4966b329609"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap 2.10.0",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_pipe"
|
name = "os_pipe"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,11 @@ xdg = { version = "2.5.2", optional = true }
|
||||||
# https://github.com/ebassi/xdg-mime-rs/pull/31
|
# https://github.com/ebassi/xdg-mime-rs/pull/31
|
||||||
xdg-mime = { git = "https://github.com/ellieplayswow/xdg-mime-rs", branch = "feature/get-same-as" }
|
xdg-mime = { git = "https://github.com/ellieplayswow/xdg-mime-rs", branch = "feature/get-same-as" }
|
||||||
# Compression
|
# Compression
|
||||||
bzip2 = { version = "0.5", optional = true } #TODO: replace with pure Rust crate
|
bzip2 = { version = "0.5", optional = true } #TODO: replace with pure Rust crate
|
||||||
flate2 = "1.0"
|
flate2 = "1.0"
|
||||||
tar = "0.4.43"
|
tar = "0.4.43"
|
||||||
xz2 = { version = "0.1", optional = true } #TODO: replace with pure Rust crate
|
xz2 = { version = "0.1", optional = true } #TODO: replace with pure Rust crate
|
||||||
|
ordermap = { version = "0.5.8", features = ["serde"] }
|
||||||
# Internationalization
|
# Internationalization
|
||||||
i18n-embed = { version = "0.15", features = [
|
i18n-embed = { version = "0.15", features = [
|
||||||
"fluent-system",
|
"fluent-system",
|
||||||
|
|
|
||||||
51
src/app.rs
51
src/app.rs
|
|
@ -86,7 +86,9 @@ use crate::{
|
||||||
ReplaceResult,
|
ReplaceResult,
|
||||||
},
|
},
|
||||||
spawn_detached::spawn_detached,
|
spawn_detached::spawn_detached,
|
||||||
tab::{self, HeadingOptions, ItemMetadata, Location, Tab, HOVER_DURATION},
|
tab::{
|
||||||
|
self, HeadingOptions, ItemMetadata, Location, Tab, HOVER_DURATION, SORT_OPTION_FALLBACK,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use crate::{config::State, dialog::DialogSettings};
|
use crate::{config::State, dialog::DialogSettings};
|
||||||
|
|
||||||
|
|
@ -3602,10 +3604,35 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tab::Command::SetSort(location, heading_options, direction) => {
|
tab::Command::SetSort(location, heading_options, direction) => {
|
||||||
self.state
|
let default_sort = tab::SORT_OPTION_FALLBACK
|
||||||
.sort_names
|
.get(&location)
|
||||||
.insert(location, (heading_options, direction));
|
.cloned()
|
||||||
if !self.must_save_sort_names {
|
.unwrap_or((HeadingOptions::Name, true));
|
||||||
|
let changed = if default_sort == (heading_options, direction) {
|
||||||
|
self.state.sort_names.remove(&location).is_some()
|
||||||
|
} else {
|
||||||
|
// force reordering of inserted values so new settings are not dropped in the truncation step
|
||||||
|
_ = self.state.sort_names.remove(&location);
|
||||||
|
_ = self
|
||||||
|
.state
|
||||||
|
.sort_names
|
||||||
|
.insert(location, (heading_options, direction))
|
||||||
|
.is_none_or(|old| old != (heading_options, direction));
|
||||||
|
|
||||||
|
const MAX_SORT_NAMES: usize = 999;
|
||||||
|
// TODO potentially configurable limit on max size?
|
||||||
|
if self.state.sort_names.len() > MAX_SORT_NAMES {
|
||||||
|
// truncate is not a good fit because it drops the items at the end, which are newest...
|
||||||
|
self.state.sort_names = self
|
||||||
|
.state
|
||||||
|
.sort_names
|
||||||
|
.split_off(self.state.sort_names.len() - MAX_SORT_NAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
|
if !self.must_save_sort_names & changed {
|
||||||
self.must_save_sort_names = true;
|
self.must_save_sort_names = true;
|
||||||
return cosmic::Task::perform(
|
return cosmic::Task::perform(
|
||||||
async move {
|
async move {
|
||||||
|
|
@ -3635,10 +3662,12 @@ impl Application for App {
|
||||||
if location == tab.location {
|
if location == tab.location {
|
||||||
tab.parent_item_opt = parent_item_opt;
|
tab.parent_item_opt = parent_item_opt;
|
||||||
tab.set_items(items);
|
tab.set_items(items);
|
||||||
|
let location_str = location.to_string();
|
||||||
let sort = self
|
let sort = self
|
||||||
.state
|
.state
|
||||||
.sort_names
|
.sort_names
|
||||||
.get(&location.to_string())
|
.get(&location_str)
|
||||||
|
.or_else(|| SORT_OPTION_FALLBACK.get(&location_str))
|
||||||
.unwrap_or_else(|| &(HeadingOptions::Name, true));
|
.unwrap_or_else(|| &(HeadingOptions::Name, true));
|
||||||
|
|
||||||
tab.sort_name = sort.0;
|
tab.sort_name = sort.0;
|
||||||
|
|
@ -4237,10 +4266,12 @@ impl Application for App {
|
||||||
Message::SaveSortNames => {
|
Message::SaveSortNames => {
|
||||||
self.must_save_sort_names = false;
|
self.must_save_sort_names = false;
|
||||||
if let Some(state_handler) = self.state_handler.as_ref() {
|
if let Some(state_handler) = self.state_handler.as_ref() {
|
||||||
if let Err(err) = state_handler.set::<HashMap<String, (HeadingOptions, bool)>>(
|
if let Err(err) =
|
||||||
"sort_names",
|
state_handler.set::<ordermap::OrderMap<String, (HeadingOptions, bool)>>(
|
||||||
self.state.sort_names.clone(),
|
"sort_names",
|
||||||
) {
|
self.state.sort_names.clone(),
|
||||||
|
)
|
||||||
|
{
|
||||||
log::warn!("Failed to save sort names: {:?}", err);
|
log::warn!("Failed to save sort names: {:?}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use cosmic::{
|
||||||
iced::Subscription,
|
iced::Subscription,
|
||||||
theme, Application,
|
theme, Application,
|
||||||
};
|
};
|
||||||
|
use ordermap::OrderMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -107,13 +108,13 @@ pub enum TypeToSearch {
|
||||||
#[derive(Clone, CosmicConfigEntry, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
#[derive(Clone, CosmicConfigEntry, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub sort_names: HashMap<String, (HeadingOptions, bool)>,
|
pub sort_names: ordermap::OrderMap<String, (HeadingOptions, bool)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for State {
|
impl Default for State {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
sort_names: HashMap::from_iter(dirs::download_dir().into_iter().map(|dir| {
|
sort_names: OrderMap::from_iter(dirs::download_dir().into_iter().map(|dir| {
|
||||||
(
|
(
|
||||||
Location::Path(dir).normalize().to_string(),
|
Location::Path(dir).normalize().to_string(),
|
||||||
(HeadingOptions::Modified, false),
|
(HeadingOptions::Modified, false),
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ use icu::datetime::{
|
||||||
};
|
};
|
||||||
use mime_guess::{mime, Mime};
|
use mime_guess::{mime, Mime};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use ordermap::OrderMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
|
|
@ -91,7 +92,7 @@ const THUMBNAIL_SIZE: u32 = (ICON_SIZE_GRID as u32) * (ICON_SCALE_MAX as u32);
|
||||||
|
|
||||||
const DRAG_SCROLL_DISTANCE: f32 = 15.0;
|
const DRAG_SCROLL_DISTANCE: f32 = 15.0;
|
||||||
|
|
||||||
static SORT_OPTION_FALLBACK: LazyLock<HashMap<String, (HeadingOptions, bool)>> =
|
pub(crate) static SORT_OPTION_FALLBACK: LazyLock<HashMap<String, (HeadingOptions, bool)>> =
|
||||||
LazyLock::new(|| {
|
LazyLock::new(|| {
|
||||||
HashMap::from_iter(dirs::download_dir().into_iter().map(|dir| {
|
HashMap::from_iter(dirs::download_dir().into_iter().map(|dir| {
|
||||||
(
|
(
|
||||||
|
|
@ -2366,7 +2367,7 @@ impl Tab {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
location: Location,
|
location: Location,
|
||||||
config: TabConfig,
|
config: TabConfig,
|
||||||
sorting_options: Option<&HashMap<String, (HeadingOptions, bool)>>,
|
sorting_options: Option<&OrderMap<String, (HeadingOptions, bool)>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let location_str = location.to_string();
|
let location_str = location.to_string();
|
||||||
let (sort_name, sort_direction) = sorting_options
|
let (sort_name, sort_direction) = sorting_options
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue