fix(local): refresh availability after source changes
Reject stale availability probes across first-folder and last-folder mutations. Refs #723 cx
This commit is contained in:
2 files changed
+45
-17
No files matched your search
@@ -24,7 +24,7 @@ use cxx_qt_lib::QString;
|
||||
|
||||
use crate::local_bridge_ops::{
|
||||
emit_artwork, emit_artwork_one, invalidate_artists, load_tab_impl, load_tracks,
|
||||
publish_plex_state, publish_tree, reload_browse, run_sync,
|
||||
publish_availability, publish_plex_state, publish_tree, reload_browse, run_sync,
|
||||
};
|
||||
use crate::local_library_qt as lib;
|
||||
use crate::local_plex as plex;
|
||||
@@ -929,21 +929,16 @@ impl qbz_local::QbzLocal {
|
||||
let sort = lib::tracks_sort();
|
||||
let group = lib::tracks_group();
|
||||
let tracks_filter = lib::tracks_filter();
|
||||
crate::spawn(async move {
|
||||
let available = tokio::task::spawn_blocking(lib::has_library)
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
ui(move |mut b| {
|
||||
b.as_mut().set_local_available(available);
|
||||
b.as_mut()
|
||||
.set_local_album_mode(QString::from(mode.as_str()));
|
||||
b.as_mut()
|
||||
.set_local_tracks_sort(QString::from(sort.as_str()));
|
||||
b.as_mut()
|
||||
.set_local_tracks_group(QString::from(group.as_str()));
|
||||
b.as_mut()
|
||||
.set_local_tracks_filter(QString::from(tracks_filter.as_str()));
|
||||
});
|
||||
publish_availability();
|
||||
ui(move |mut b| {
|
||||
b.as_mut()
|
||||
.set_local_album_mode(QString::from(mode.as_str()));
|
||||
b.as_mut()
|
||||
.set_local_tracks_sort(QString::from(sort.as_str()));
|
||||
b.as_mut()
|
||||
.set_local_tracks_group(QString::from(group.as_str()));
|
||||
b.as_mut()
|
||||
.set_local_tracks_filter(QString::from(tracks_filter.as_str()));
|
||||
});
|
||||
publish_plex_state();
|
||||
crate::local_album_actions::publish_track_artwork();
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
//! Every loader publishes its own tab's document + the shared badges; the
|
||||
//! Plex helpers publish the gates and drive the manual sync.
|
||||
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use cxx_qt_lib::QString;
|
||||
|
||||
use crate::local_bridge::ui;
|
||||
use crate::local_library_qt as lib;
|
||||
use crate::local_plex as plex;
|
||||
|
||||
/// Republish the tab badges + availability after any load.
|
||||
/// Republish the tab badges after any load.
|
||||
pub(crate) fn publish_counts() {
|
||||
let counts = lib::to_json(&lib::counts());
|
||||
ui(move |mut b| {
|
||||
@@ -26,6 +28,34 @@ pub(crate) fn publish_counts() {
|
||||
});
|
||||
}
|
||||
|
||||
/// Republish whether any browse source currently makes Local Library usable.
|
||||
///
|
||||
/// `localAvailable` gates the entire Local Library surface, but it used to be
|
||||
/// seeded only once during bridge boot. Adding the first folder (or removing
|
||||
/// the last one) then refreshed every document behind the gate without ever
|
||||
/// changing the gate itself. Keep this asynchronous because `has_library`
|
||||
/// opens the per-user SQLite database.
|
||||
///
|
||||
/// A generation prevents a slower, older database read from overwriting the
|
||||
/// answer from a newer source mutation.
|
||||
static AVAILABILITY_GENERATION: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
pub(crate) fn publish_availability() {
|
||||
let generation = AVAILABILITY_GENERATION
|
||||
.fetch_add(1, Ordering::AcqRel)
|
||||
.wrapping_add(1);
|
||||
crate::spawn(async move {
|
||||
let available = tokio::task::spawn_blocking(lib::has_library)
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
if AVAILABILITY_GENERATION.load(Ordering::Acquire) != generation {
|
||||
log::debug!("[qbz-qt] discarded stale local availability generation {generation}");
|
||||
return;
|
||||
}
|
||||
ui(move |mut b| b.as_mut().set_local_available(available));
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn publish_tree(nodes_json: String) {
|
||||
ui(move |mut b| {
|
||||
b.as_mut()
|
||||
@@ -144,6 +174,9 @@ fn pruned_albums_filter(has_jellyfin: bool, has_subsonic: bool) -> String {
|
||||
|
||||
pub(crate) fn reload_browse() {
|
||||
publish_media_gates();
|
||||
// This is the shared mutation chokepoint for folders and remote sources.
|
||||
// Republish the gate as well as the documents it controls (#723).
|
||||
publish_availability();
|
||||
// The cortinilla's instant-paint cache embeds LOCAL rows and their artwork
|
||||
// paths, so anything that reaches here has just made those rows possibly
|
||||
// wrong. This is the single chokepoint for local-library mutations, which
|
||||
|
||||
Reference in new issue
Block a user