All 17 #[tauri::command] entries in offline_cache/commands.rs are unregistered (V2 owns the live cache commands) and uncalled. The only surviving consumer was session_lifecycle.rs reaching for purge_all_cached_files (a non-command helper). - Move purge_all_cached_files to a new offline_cache/purge.rs module (drops the LibraryState path through library::commands; uses the canonical crate::library::LibraryState directly) - Delete offline_cache/commands.rs along with its dead siblings: cache_track_for_offline + post_process_cached_track, is_track_cached, get_cached_track_path, get_cached_track, get_cached_tracks, get_offline_cache_stats, remove_cached_track, clear_offline_cache + cleanup_empty_folder, set_offline_cache_limit + evict_if_needed, open_offline_cache_folder, open_album_folder, open_track_folder, check_offline_root_mounted, validate_offline_path, move_offline_cache_to_path, detect_legacy_cached_files (the command shim — the helper of the same name lives in migration.rs and is still consumed by V2), start_legacy_migration, sync_offline_cache_to_library + SyncResult. - Update session_lifecycle.rs to import from offline_cache::purge. cc
100 lines
3.8 KiB
Rust
100 lines
3.8 KiB
Rust
//! Offline cache purge helper.
|
|
//!
|
|
//! Used by `session_lifecycle` to clear all cached audio when the active
|
|
//! session is torn down. Not a Tauri command — pure helper.
|
|
|
|
use crate::library::LibraryState;
|
|
use crate::offline_cache::OfflineCacheState;
|
|
|
|
/// Clear entire offline cache (internal helper)
|
|
pub async fn purge_all_cached_files(
|
|
cache_state: &OfflineCacheState,
|
|
library_state: &LibraryState,
|
|
) -> Result<(), String> {
|
|
let paths = {
|
|
let guard__ = cache_state.db.lock().await;
|
|
let db = guard__
|
|
.as_ref()
|
|
.ok_or("No active session - please log in")?;
|
|
db.clear_all()?
|
|
};
|
|
|
|
// Delete all files. For v1 entries `file_path` is the plain FLAC;
|
|
// for v2 entries it's `<dir>/segments.bin` — we remove the enclosing
|
|
// track directory so init.mp4 + manifest.json + segments.bin all go
|
|
// in one step. Plain files still work because remove_dir_all on a
|
|
// file path fails silently and we fall through to remove_file.
|
|
for path in paths {
|
|
let p = std::path::Path::new(&path);
|
|
if !p.exists() {
|
|
continue;
|
|
}
|
|
// Heuristic: the v2 layout puts everything inside `tracks-cmaf/<id>/`.
|
|
// If the parent directory matches that shape, remove the directory.
|
|
let looks_like_v2 = p
|
|
.parent()
|
|
.and_then(|parent| parent.parent())
|
|
.and_then(|root| root.file_name())
|
|
.and_then(|n| n.to_str())
|
|
== Some("tracks-cmaf");
|
|
if looks_like_v2 {
|
|
if let Some(track_dir) = p.parent() {
|
|
let _ = std::fs::remove_dir_all(track_dir);
|
|
continue;
|
|
}
|
|
}
|
|
let _ = std::fs::remove_file(p);
|
|
}
|
|
|
|
// Also clear the tracks directory (legacy unorganized files)
|
|
let cache_dir = cache_state.cache_dir.read().unwrap().clone();
|
|
let tracks_dir = cache_dir.join("tracks");
|
|
if tracks_dir.exists() {
|
|
if let Ok(entries) = std::fs::read_dir(&tracks_dir) {
|
|
for entry in entries.flatten() {
|
|
let _ = std::fs::remove_file(entry.path());
|
|
}
|
|
}
|
|
}
|
|
|
|
// And the tracks-cmaf directory (v2 bundles) — belt-and-suspenders
|
|
// so orphan bundles from corrupt DB rows get cleaned up too.
|
|
let tracks_cmaf_dir = cache_dir.join("tracks-cmaf");
|
|
if tracks_cmaf_dir.exists() {
|
|
let _ = std::fs::remove_dir_all(&tracks_cmaf_dir);
|
|
log::info!("[OfflineCache/Purge] Removed tracks-cmaf/ directory");
|
|
}
|
|
|
|
// Clear organized artist/album folders
|
|
// Look for any subdirectories in cache_dir that are not "tracks" or system files
|
|
if let Ok(entries) = std::fs::read_dir(&cache_dir) {
|
|
for entry in entries.flatten() {
|
|
let path = entry.path();
|
|
if path.is_dir() {
|
|
let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
|
|
// Skip the tracks directory and database files
|
|
if name != "tracks" && !name.ends_with(".db") && !name.ends_with(".db-journal") {
|
|
// This is likely an artist folder, delete it recursively
|
|
if let Err(e) = std::fs::remove_dir_all(&path) {
|
|
log::warn!("Failed to remove folder {:?}: {}", path, e);
|
|
} else {
|
|
log::info!("Removed artist folder: {:?}", path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove all Qobuz cached tracks from library
|
|
let guard__ = library_state.db.lock().await;
|
|
let library_db = guard__
|
|
.as_ref()
|
|
.ok_or("No active session - please log in")?;
|
|
let removed_count = library_db
|
|
.remove_all_qobuz_cached_tracks()
|
|
.map_err(|e| format!("Failed to remove cached tracks from library: {}", e))?;
|
|
log::info!("Removed {} Qobuz cached tracks from library", removed_count);
|
|
|
|
Ok(())
|
|
}
|