feat(qt): module-OFF results fallback and search service teardown
Two gaps that both made the port quietly lose a capability. Turning Intelligent Search off is a SWAP in the reference, not a removal: typing live-navigates to the full results page on a 300ms debounce instead of opening a dropdown. Here it returned, so with the module off typing did nothing at all until the user pressed Enter - the kill switch removed the feature rather than exchanging it. The per-user search service had no teardown on logout, so the next account inherited the previous one's learned ranking: top_for_query would promote a stranger's most-clicked result and the interaction store would keep accumulating under their buckets. The reference tears it down for exactly this reason. The version counter and both payload snapshots are cleared with it, so a load still in flight at logout cannot publish into the next session. auth_qt's asymmetry note is updated rather than left claiming a gap that is now closed. Contract: qbz-nix-docs/qt-frontend/2026-08-03-cortinilla-parity, commit C10 (J5, J7, R7-5). Gate: build clean, 258/258 tests, both QML audits OK, offscreen smoke 0 complaints + home published. cc
This commit is contained in:
2 files changed
+36
-7
No files matched your search
@@ -409,10 +409,10 @@ where
|
||||
/// STILL ASYMMETRIC (an `init_for_user` above with no teardown here, because
|
||||
/// the module exposes none — each needs its own file changed, so it is not
|
||||
/// done from this side): `local_plex`, `library_qt::init_local_favorites`,
|
||||
/// `sidebar_qt::init_pinned`, `search_qt::init`, `playlist_qt::set_user_id`.
|
||||
/// The reference DOES tear the last three down (`pinned::teardown`,
|
||||
/// `local_favorites::teardown`, `search_service::teardown` —
|
||||
/// `qbz/src/auth.rs:349-352`).
|
||||
/// `sidebar_qt::init_pinned`, `playlist_qt::set_user_id`. The reference DOES
|
||||
/// tear the first three down (`pinned::teardown`,
|
||||
/// `local_favorites::teardown` — `qbz/src/auth.rs:349-352`).
|
||||
/// `search_qt::teardown` was the fourth and is now WIRED below.
|
||||
pub async fn logout<A>(runtime: &Arc<AppRuntime<A>>) -> Result<(), String>
|
||||
where
|
||||
A: FrontendAdapter + Send + Sync + 'static,
|
||||
@@ -420,6 +420,10 @@ where
|
||||
let _ = qbz_credentials::clear_oauth_token();
|
||||
let _ = runtime.core().logout().await;
|
||||
crate::fav_cache_qt::teardown();
|
||||
// Intelligent Search: the LEARNED ranking is per-user. Without this the
|
||||
// next account inherits a stranger's most-clicked results as its promoted
|
||||
// top result, and keeps writing into their buckets.
|
||||
crate::search_qt::teardown();
|
||||
// MyQBZ: grids + branding/view-prefs binding, then the detail page's
|
||||
// caches and the two modal documents.
|
||||
crate::myqbz_qt::teardown();
|
||||
|
||||
@@ -87,6 +87,24 @@ pub fn is_enabled() -> bool {
|
||||
with_service(false, |s| s.enabled())
|
||||
}
|
||||
|
||||
/// Drop the per-user search service on logout.
|
||||
///
|
||||
/// Without this the NEXT account inherits the previous one's learned ranking:
|
||||
/// `top_for_query` would promote a stranger's most-clicked result, and the
|
||||
/// interaction store would keep accumulating under their bucket. The reference
|
||||
/// tears it down for the same reason.
|
||||
///
|
||||
/// The version counters and payload snapshots are cleared with it, so a load
|
||||
/// still in flight at logout cannot publish into the next session.
|
||||
pub fn teardown() {
|
||||
if let Ok(mut guard) = SERVICE.lock() {
|
||||
*guard = None;
|
||||
}
|
||||
next_cort_version();
|
||||
*LAST_CORT.lock().unwrap_or_else(|e| e.into_inner()) = None;
|
||||
*LAST_CORT_LOCAL.lock().unwrap_or_else(|e| e.into_inner()) = Vec::new();
|
||||
}
|
||||
|
||||
pub fn set_enabled(on: bool) {
|
||||
with_service((), |s| s.set_enabled(on));
|
||||
}
|
||||
@@ -755,9 +773,16 @@ pub async fn live(runtime: &Arc<AppRuntime<LoggingAdapter>>, query: &str) {
|
||||
return;
|
||||
}
|
||||
if !is_enabled() {
|
||||
// Module OFF: the reference live-navigates to the results page
|
||||
// instead (300 ms debounce). Not wired here yet — Enter still
|
||||
// reaches the page via submit().
|
||||
// Module OFF is a SWAP, not a removal: the reference live-navigates
|
||||
// to the full results page on a 300 ms debounce instead of showing a
|
||||
// dropdown. Returning here made the kill switch remove a capability
|
||||
// rather than exchange it — typing did nothing at all until Enter.
|
||||
let version = next_cort_version();
|
||||
tokio::time::sleep(std::time::Duration::from_millis(300)).await;
|
||||
if !is_current_cort_version(version) {
|
||||
return;
|
||||
}
|
||||
submit(runtime, &q, None).await;
|
||||
return;
|
||||
}
|
||||
set_selected(-1, 0.0);
|
||||
|
||||
Reference in new issue
Block a user