feat(gui): now directories can be reordered using drag and drop

This commit is contained in:
2026-01-28 02:10:36 +03:00
parent d385e5356e
commit 4499b1d3aa
7 changed files with 97 additions and 15 deletions
+13 -7
View File
@@ -3,10 +3,11 @@ use egui::{
Align, AtomExt, Button, CollapsingHeader, Color32, ComboBox, CursorIcon, FontFamily, Label,
Layout, RichText, ScrollArea, Sense, Slider, TextEdit, Ui, Vec2,
};
use egui_dnd::dnd;
use egui_material_icons::icons;
use pwsp::types::audio_player::TrackInfo;
use pwsp::utils::gui::format_time_pair;
use std::{error::Error, path::PathBuf, time::Instant};
use std::{error::Error, time::Instant};
use pwsp::types::gui::AppState;
@@ -301,10 +302,14 @@ impl SoundpadGui {
ScrollArea::vertical().id_salt(0).show(ui, |ui| {
ui.set_min_width(area_size.x);
let mut dirs: Vec<PathBuf> = self.app_state.dirs.iter().cloned().collect();
dirs.sort();
for path in dirs.iter() {
let mut dirs = self.app_state.dirs.clone();
dnd(ui, "dnd_directories").show_vec(&mut dirs, |ui, item, handle, _state| {
let path = item.clone();
ui.horizontal(|ui| {
handle.ui(ui, |ui| {
ui.label(icons::ICON_DRAG_INDICATOR);
});
let name = path
.file_name()
.map(|s| s.to_string_lossy().to_string())
@@ -312,7 +317,7 @@ impl SoundpadGui {
let mut dir_button_text = RichText::new(name.clone());
if let Some(current_dir) = &self.app_state.current_dir {
if current_dir.eq(path) {
if current_dir.eq(&path) {
dir_button_text = dir_button_text.color(Color32::WHITE);
}
}
@@ -322,7 +327,7 @@ impl SoundpadGui {
let dir_button_response = ui.add(dir_button);
if dir_button_response.clicked() {
self.open_dir(path);
self.open_dir(&path);
}
let delete_dir_button = Button::new(icons::ICON_DELETE).frame(false);
@@ -332,7 +337,8 @@ impl SoundpadGui {
self.remove_dir(&path.clone());
}
});
}
});
self.app_state.dirs = dirs;
ui.horizontal(|ui| {
let add_dirs_button = Button::new(icons::ICON_ADD).frame(false);
+4 -2
View File
@@ -4,6 +4,7 @@ mod update;
use eframe::{HardwareAcceleration, NativeOptions, icon_data::from_png_bytes, run_native};
use egui::{Context, Vec2, ViewportBuilder};
use itertools::Itertools;
use pwsp::{
types::{
audio_player::PlayerState,
@@ -87,15 +88,16 @@ impl SoundpadGui {
let file_dialog = FileDialog::new();
if let Some(paths) = file_dialog.pick_folders() {
for path in paths {
self.app_state.dirs.insert(path);
self.app_state.dirs.push(path);
}
self.app_state.dirs = self.app_state.dirs.iter().unique().cloned().collect();
self.config.dirs = self.app_state.dirs.clone();
self.config.save_to_file().ok();
}
}
pub fn remove_dir(&mut self, path: &PathBuf) {
self.app_state.dirs.remove(path);
self.app_state.dirs.retain(|x| x != path);
if let Some(current_dir) = &self.app_state.current_dir
&& current_dir == path
{
+12
View File
@@ -9,6 +9,13 @@ use std::time::{Duration, Instant};
impl App for SoundpadGui {
fn update(&mut self, ctx: &Context, _frame: &mut EFrame) {
// Save directories if changed
if !self.config.dirs.eq(&self.app_state.dirs) {
self.config.dirs = self.app_state.dirs.clone();
self.config.save_to_file().ok();
}
// Seek and volume requests
let mut seek_requests = vec![];
let mut volume_requests = vec![];
@@ -57,11 +64,13 @@ impl App for SoundpadGui {
}
}
// Sync audio player state
{
let guard = self.audio_player_state_shared.lock().unwrap();
self.audio_player_state = guard.clone();
}
// Handle scale factor changes
let old_scale_factor = self.config.scale_factor;
let new_scale_factor = ctx.zoom_factor().clamp(0.5, 2.0);
@@ -72,8 +81,10 @@ impl App for SoundpadGui {
self.config.save_to_file().ok();
}
// Handle input
self.handle_input(ctx);
// Draw UI
CentralPanel::default().show(ctx, |ui| {
if !self.audio_player_state.is_daemon_running {
self.draw_waiting_for_daemon(ui);
@@ -88,6 +99,7 @@ impl App for SoundpadGui {
self.draw(ui).ok();
});
// Request repaint
ctx.request_repaint_after_secs(1.0 / 60.0);
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
use crate::utils::config::get_config_path;
use serde::{Deserialize, Serialize};
use std::{collections::HashSet, error::Error, fs, path::PathBuf};
use std::{error::Error, fs, path::PathBuf};
#[derive(Default, Clone, Serialize, Deserialize)]
#[serde(default)]
@@ -41,7 +41,7 @@ pub struct GuiConfig {
pub save_scale_factor: bool,
pub pause_on_exit: bool,
pub dirs: HashSet<PathBuf>,
pub dirs: Vec<PathBuf>,
}
impl Default for GuiConfig {
@@ -55,7 +55,7 @@ impl Default for GuiConfig {
save_scale_factor: false,
pause_on_exit: false,
dirs: HashSet::default(),
dirs: vec![],
}
}
}
+1 -1
View File
@@ -37,7 +37,7 @@ pub struct AppState {
pub ignore_volume_update_until: Option<Instant>,
pub current_dir: Option<PathBuf>,
pub dirs: HashSet<PathBuf>,
pub dirs: Vec<PathBuf>,
pub selected_file: Option<PathBuf>,
pub files: HashSet<PathBuf>,