Files
Psychotoxical-psysonic/src-tauri/crates/psysonic-syncfs/src/lib.rs
T
Frank Stellmacher b4c8ed4b65 fix(offline): cancellable downloads + stable sidebar progress toast (#694)
* fix(sidebar): keep offline-download toast from squishing in a short window

The toast lives in the sidebar nav flex column; without flex-shrink: 0 the
column compressed it vertically when the main window was small. The label
now also ellipsis-truncates instead of overflowing on a narrow sidebar.

* fix(offline): make offline downloads cancellable down to the Rust transfer

A running offline download could not be stopped — the sidebar X button only
dropped not-yet-started tracks between batches of 8, and the Rust transfer had
no cancellation path at all, so in-flight HTTP streams always ran to completion.

Add an offline_cancel_flags() registry (mirroring sync_cancel_flags for the
device-sync side) plus additive cancel_offline_downloads / clear_offline_cancel
commands. download_track_offline takes an optional download_id, checks the flag
right after acquiring its semaphore slot, and threads it through
finalize_streamed_download / stream_to_file so an in-flight stream aborts at the
next chunk — the partial .part file is cleaned up by the existing error path.

* fix(offline): cancel per-track and clear the sidebar toast immediately

downloadAlbum tags each run with a downloadId, checks for cancellation before
every track instead of once per 8-track batch (which never re-ran for albums of
8 or fewer tracks), and persists tracks that finished before the cancel so they
are not orphaned on disk. cancelDownload / cancelAllDownloads drop every job for
the album and call cancel_offline_downloads so Rust aborts the in-flight
transfers — the toast disappears at once instead of lingering on stuck rows.

Adds offlineJobStore cancellation tests.

* docs(changelog): offline download cancel button + toast sizing fixes
2026-05-14 20:08:08 +02:00

39 lines
1.6 KiB
Rust

//! `psysonic-syncfs` — offline / hot-cache, device sync, and the shared HTTP
//! download helpers used by both.
//!
//! This crate hosts the Tauri commands that read/write the on-disk caches
//! (`offline_*`, `hot_cache_*`) and that copy tracks to mounted USB / SD-card
//! devices (`sync_*`).
use std::collections::HashMap;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Mutex, OnceLock};
// Re-export logging facade so submodules can keep `crate::app_eprintln!()`.
pub use psysonic_core::{app_deprintln, app_eprintln, logging};
pub mod cache;
pub mod file_transfer;
pub mod sync;
/// Shared semaphore that caps simultaneous `download_track_offline` executions.
pub type DownloadSemaphore = Arc<tokio::sync::Semaphore>;
/// Per-job cancellation flags for `sync_batch_to_device`.
/// Each running sync registers an `Arc<AtomicBool>` here; `cancel_device_sync`
/// flips it.
pub fn sync_cancel_flags() -> &'static Mutex<HashMap<String, Arc<AtomicBool>>> {
static FLAGS: OnceLock<Mutex<HashMap<String, Arc<AtomicBool>>>> = OnceLock::new();
FLAGS.get_or_init(|| Mutex::new(HashMap::new()))
}
/// Per-download cancellation flags for offline album/playlist downloads,
/// keyed by the frontend-supplied download id. Each `download_track_offline`
/// call checks its flag (once after acquiring a slot, then on every chunk
/// while streaming); `cancel_offline_downloads` flips it. Mirrors
/// [`sync_cancel_flags`] for the device-sync side.
pub fn offline_cancel_flags() -> &'static Mutex<HashMap<String, Arc<AtomicBool>>> {
static FLAGS: OnceLock<Mutex<HashMap<String, Arc<AtomicBool>>>> = OnceLock::new();
FLAGS.get_or_init(|| Mutex::new(HashMap::new()))
}