Filter out empty directories during library scan
All checks were successful
Build and Release / build-and-release (push) Successful in 54s
All checks were successful
Build and Release / build-and-release (push) Successful in 54s
Skip directories that contain no media files or non-empty subdirectories. This prevents empty folders from appearing in the file list, which can occur when NFS cache is stale or when directories are emptied.
This commit is contained in:
parent
b438065c23
commit
7c083cfb0e
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "cm-player"
|
||||
version = "0.1.29"
|
||||
version = "0.1.31"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
21
src/main.rs
21
src/main.rs
@ -661,14 +661,29 @@ fn handle_key_event<B: ratatui::backend::Backend>(terminal: &mut Terminal<B>, st
|
||||
state.show_refresh_confirm = false;
|
||||
state.is_refreshing = true;
|
||||
terminal.draw(|f| { let _ = ui::render(f, state, player); })?; // Show "Refreshing library..." immediately
|
||||
tracing::info!("Rescanning...");
|
||||
|
||||
let cache_dir = cache::get_cache_dir()?;
|
||||
|
||||
// Delete old cache files to ensure fresh scan
|
||||
let _ = std::fs::remove_file(cache_dir.join("file_tree.json"));
|
||||
let _ = std::fs::remove_file(cache_dir.join("metadata.json"));
|
||||
|
||||
// Perform fresh scan
|
||||
let new_cache = scanner::scan_paths(&state.config.scan_paths.paths)?;
|
||||
new_cache.save(&cache_dir)?;
|
||||
|
||||
// Replace old cache completely
|
||||
state.cache = new_cache;
|
||||
state.refresh_flattened_items();
|
||||
state.refresh_flattened_items(); // This also cleans up playlist and expanded_dirs
|
||||
|
||||
// If current file was removed, stop playback
|
||||
if state.current_file.is_none() {
|
||||
player.stop()?;
|
||||
state.current_position = 0.0;
|
||||
state.current_duration = 0.0;
|
||||
}
|
||||
|
||||
state.is_refreshing = false;
|
||||
tracing::info!("Rescan complete");
|
||||
}
|
||||
KeyCode::Char('n') | KeyCode::Char('N') | KeyCode::Esc => {
|
||||
state.show_refresh_confirm = false;
|
||||
|
||||
@ -63,7 +63,10 @@ pub fn scan_directory(root_path: &Path) -> Result<FileTreeNode> {
|
||||
if entry.file_type().is_dir() {
|
||||
// Recursively scan subdirectories
|
||||
if let Ok(child_node) = scan_directory(path) {
|
||||
node.children.push(child_node);
|
||||
// Only add directory if it contains media files or non-empty subdirectories
|
||||
if !child_node.children.is_empty() {
|
||||
node.children.push(child_node);
|
||||
}
|
||||
}
|
||||
} else if is_media_file(path) {
|
||||
// Add media file
|
||||
|
||||
@ -587,8 +587,84 @@ impl AppState {
|
||||
}
|
||||
|
||||
pub fn refresh_flattened_items(&mut self) {
|
||||
// Keep current expanded state after rescan
|
||||
// Clean up expanded_dirs - remove paths that no longer exist in new cache
|
||||
self.cleanup_expanded_dirs();
|
||||
|
||||
// Rebuild view with cleaned expanded state
|
||||
self.rebuild_flattened_items();
|
||||
|
||||
// Clean up playlist - remove files that no longer exist in cache
|
||||
self.cleanup_playlist();
|
||||
}
|
||||
|
||||
fn cleanup_expanded_dirs(&mut self) {
|
||||
// Build a set of valid directory paths from the cache
|
||||
let mut valid_dirs = std::collections::HashSet::new();
|
||||
fn collect_dirs(node: &crate::cache::FileTreeNode, dirs: &mut std::collections::HashSet<std::path::PathBuf>) {
|
||||
if node.is_dir {
|
||||
dirs.insert(node.path.clone());
|
||||
}
|
||||
for child in &node.children {
|
||||
collect_dirs(child, dirs);
|
||||
}
|
||||
}
|
||||
for root in &self.cache.file_tree {
|
||||
collect_dirs(root, &mut valid_dirs);
|
||||
}
|
||||
|
||||
// Remove invalid paths from expanded_dirs
|
||||
let original_len = self.expanded_dirs.len();
|
||||
self.expanded_dirs.retain(|path| valid_dirs.contains(path));
|
||||
|
||||
if self.expanded_dirs.len() < original_len {
|
||||
tracing::info!("Cleaned up expanded_dirs: removed {} invalid paths", original_len - self.expanded_dirs.len());
|
||||
}
|
||||
}
|
||||
|
||||
fn cleanup_playlist(&mut self) {
|
||||
// Build a set of valid paths from the cache for fast lookup
|
||||
let mut valid_paths = std::collections::HashSet::new();
|
||||
fn collect_paths(node: &crate::cache::FileTreeNode, paths: &mut std::collections::HashSet<std::path::PathBuf>) {
|
||||
if !node.is_dir {
|
||||
paths.insert(node.path.clone());
|
||||
}
|
||||
for child in &node.children {
|
||||
collect_paths(child, paths);
|
||||
}
|
||||
}
|
||||
for root in &self.cache.file_tree {
|
||||
collect_paths(root, &mut valid_paths);
|
||||
}
|
||||
|
||||
// Check if current file is invalid
|
||||
let current_file_invalid = if let Some(ref current) = self.current_file {
|
||||
!valid_paths.contains(current)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if current_file_invalid {
|
||||
self.current_file = None;
|
||||
tracing::info!("Current playing file was deleted, cleared current_file");
|
||||
}
|
||||
|
||||
// Remove files from playlist that don't exist in cache
|
||||
let original_len = self.playlist.len();
|
||||
self.playlist.retain(|path| valid_paths.contains(path));
|
||||
|
||||
// Adjust indices if playlist was modified
|
||||
if self.playlist.len() < original_len {
|
||||
// Ensure playlist_index is valid
|
||||
if self.playlist_index >= self.playlist.len() && !self.playlist.is_empty() {
|
||||
self.playlist_index = self.playlist.len() - 1;
|
||||
}
|
||||
// Ensure selected_playlist_index is valid
|
||||
if self.selected_playlist_index >= self.playlist.len() && !self.playlist.is_empty() {
|
||||
self.selected_playlist_index = self.playlist.len() - 1;
|
||||
}
|
||||
|
||||
tracing::info!("Cleaned up playlist: removed {} deleted files", original_len - self.playlist.len());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rebuild_flattened_items(&mut self) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user