feat(gui): sorting options (#134)

* feat(gui): added an ability to copy ```pwsp-cli action play``` command for every sound

* feat(gui): added files sorting options
This commit is contained in:
Tarasov Aleksandr
2026-06-04 20:14:28 +03:00
committed by GitHub
parent c173e602ad
commit 410a2c7959
4 changed files with 209 additions and 6 deletions
+22 -1
View File
@@ -159,6 +159,13 @@ impl SoundpadGui {
pub fn get_filtered_files(&self) -> Vec<PathBuf> {
let mut files: Vec<PathBuf> = self.app_state.listed_files.iter().cloned().collect();
let sort_order = self
.app_state
.current_dir
.as_ref()
.map(|d| self.config.get_sort_order(d))
.unwrap_or_default();
files.sort_by(|a, b| {
let a_is_dir = a.is_dir();
let b_is_dir = b.is_dir();
@@ -167,7 +174,7 @@ impl SoundpadGui {
} else if !a_is_dir && b_is_dir {
Ordering::Greater
} else {
a.cmp(b)
sort_order.compare(a, b)
}
});
@@ -334,5 +341,19 @@ mod tests {
let filtered_search = gui.get_filtered_files();
assert_eq!(filtered_search.len(), 1);
assert_eq!(filtered_search[0], file_c);
// Test sort order descending
gui.app_state.current_dir = Some(PathBuf::from("dummy_dir"));
gui.config.dirs_settings.insert(
PathBuf::from("dummy_dir"),
pwsp_lib::types::config::DirSettings {
sort_order: pwsp_lib::types::config::SortOrder::AlphabeticalDesc,
},
);
gui.app_state.search_query = String::new();
let filtered_desc = gui.get_filtered_files();
assert_eq!(filtered_desc.len(), 2);
assert_eq!(filtered_desc[0], file_c);
assert_eq!(filtered_desc[1], file_b);
}
}
+70 -4
View File
@@ -5,7 +5,10 @@ use egui::{
};
use egui_dnd::dnd;
use egui_material_icons::icons::*;
use pwsp_lib::types::{gui::AppState, gui::AudioPlayerState};
use pwsp_lib::types::{
config::{GuiConfig, SortOrder},
gui::{AppState, AudioPlayerState},
};
use rust_i18n::t;
use std::{cmp::Ordering, path::Path, path::PathBuf};
@@ -135,6 +138,65 @@ impl SoundpadGui {
{
self.app_state.dirs_to_remove.insert(path.clone());
}
ui.separator();
ui.label(t!("gui.context.dirs.sort_by"));
let current_order = self
.config
.dirs_settings
.get(path)
.map(|s| s.sort_order)
.unwrap_or_default();
let mut new_order = None;
if ui
.radio(
current_order == SortOrder::AlphabeticalAsc,
t!("gui.sort.alpha_asc"),
)
.clicked()
{
new_order = Some(SortOrder::AlphabeticalAsc);
}
if ui
.radio(
current_order == SortOrder::AlphabeticalDesc,
t!("gui.sort.alpha_desc"),
)
.clicked()
{
new_order = Some(SortOrder::AlphabeticalDesc);
}
if ui
.radio(
current_order == SortOrder::DateModifiedNewest,
t!("gui.sort.date_newest"),
)
.clicked()
{
new_order = Some(SortOrder::DateModifiedNewest);
}
if ui
.radio(
current_order == SortOrder::DateModifiedOldest,
t!("gui.sort.date_oldest"),
)
.clicked()
{
new_order = Some(SortOrder::DateModifiedOldest);
}
if let Some(order) = new_order {
self.config
.dirs_settings
.entry(path.clone())
.or_default()
.sort_order = order;
self.config.save_to_file().ok();
self.app_state.dir_cache.remove(path);
self.open_dir(path);
}
});
});
});
@@ -192,6 +254,7 @@ impl SoundpadGui {
Self::draw_tree_node(
ui,
entry_path,
&self.config,
&mut self.app_state,
&self.audio_player_state,
&mut actions,
@@ -226,6 +289,7 @@ impl SoundpadGui {
fn draw_tree_node_dir(
ui: &mut Ui,
path: std::path::PathBuf,
config: &GuiConfig,
app_state: &mut AppState,
audio_player_state: &AudioPlayerState,
actions: &mut Vec<FileAction>,
@@ -247,6 +311,7 @@ impl SoundpadGui {
read.push(entry.path());
}
}
let sort_order = config.get_sort_order(&path);
read.sort_by(|a, b| {
let a_is_dir = a.is_dir();
let b_is_dir = b.is_dir();
@@ -255,7 +320,7 @@ impl SoundpadGui {
} else if !a_is_dir && b_is_dir {
Ordering::Greater
} else {
a.cmp(b)
sort_order.compare(a, b)
}
});
app_state.dir_cache.insert(path.clone(), read.clone());
@@ -287,7 +352,7 @@ impl SoundpadGui {
}
}
}
Self::draw_tree_node(ui, child, app_state, audio_player_state, actions);
Self::draw_tree_node(ui, child, config, app_state, audio_player_state, actions);
}
});
}
@@ -437,12 +502,13 @@ impl SoundpadGui {
fn draw_tree_node(
ui: &mut Ui,
path: std::path::PathBuf,
config: &GuiConfig,
app_state: &mut AppState,
audio_player_state: &AudioPlayerState,
actions: &mut Vec<FileAction>,
) {
if path.is_dir() {
Self::draw_tree_node_dir(ui, path, app_state, audio_player_state, actions);
Self::draw_tree_node_dir(ui, path, config, app_state, audio_player_state, actions);
} else {
Self::draw_tree_node_file(ui, path, app_state, audio_player_state, actions);
}