offline mode fixes
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 4m39s
Traceability Validation / Check Requirement Traces (push) Successful in 24s
🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 5m11s

This commit is contained in:
2026-07-07 16:22:12 +02:00
parent acb7e5f221
commit 36be192d44
5 changed files with 102 additions and 7 deletions
+37 -4
View File
@@ -32,6 +32,13 @@ pub struct SessionPollerManager {
jellyfin_client: Arc<Mutex<Option<JellyfinClient>>>,
playback_mode_manager: Arc<PlaybackModeManager>,
event_emitter: Arc<Mutex<Option<Arc<dyn PlayerEventEmitter>>>>,
/// Optional connectivity reporter. The session poller is the one piece of
/// server traffic that runs continuously even when the user is idle (not
/// browsing the library), so feeding its poll outcomes into the reporter is
/// what lets the app detect going offline — and, crucially, recover when the
/// server returns — without any user interaction. Repository traffic alone
/// can't do this because it only happens while browsing.
connectivity_reporter: Arc<Mutex<Option<crate::connectivity::ConnectivityReporter>>>,
// Polling state
is_running: Arc<AtomicBool>,
@@ -52,6 +59,7 @@ impl SessionPollerManager {
jellyfin_client,
playback_mode_manager,
event_emitter: Arc::new(Mutex::new(None)),
connectivity_reporter: Arc::new(Mutex::new(None)),
is_running: Arc::new(AtomicBool::new(false)),
current_hint: Arc::new(RwLock::new(PollingHint::Normal)),
current_interval_ms: Arc::new(AtomicU64::new(10000)), // Default 10s
@@ -64,6 +72,13 @@ impl SessionPollerManager {
*self.event_emitter.lock_safe() = Some(emitter);
}
/// Wire the connectivity reporter so each poll outcome updates reachability.
/// A successful poll recovers the app to online instantly; sustained poll
/// failures flip it offline (subject to the reporter's debounce window).
pub fn set_connectivity_reporter(&self, reporter: crate::connectivity::ConnectivityReporter) {
*self.connectivity_reporter.lock_safe() = Some(reporter);
}
/// Start the background polling thread
pub fn start(&self) {
if self.is_running.swap(true, Ordering::Relaxed) {
@@ -77,6 +92,7 @@ impl SessionPollerManager {
let client = self.jellyfin_client.clone();
let mode_manager = self.playback_mode_manager.clone();
let emitter = self.event_emitter.clone();
let connectivity_reporter = self.connectivity_reporter.clone();
let is_running = self.is_running.clone();
let hint = self.current_hint.clone();
let interval_ms = self.current_interval_ms.clone();
@@ -96,18 +112,35 @@ impl SessionPollerManager {
debug!("[SessionPoller] Polling with interval: {}ms", new_interval);
// Fetch sessions
let sessions_result = rt.block_on(async {
// Fetch sessions. `had_client` distinguishes "server didn't
// answer" from "no client configured" so we only feed real
// request outcomes into the connectivity reporter.
let (sessions_result, had_client) = rt.block_on(async {
let client_opt = client.lock_safe().clone();
match client_opt {
Some(c) => c.get_sessions().await,
Some(c) => (c.get_sessions().await, true),
None => {
debug!("[SessionPoller] Jellyfin client not configured, skipping poll");
Ok(Vec::new())
(Ok(Vec::new()), false)
}
}
});
// Drive the connectivity reporter from this poll's outcome. This
// is what recovers the app to online when the server returns
// while the user is idle, and detects going offline when no
// library browsing is happening. See connectivity/mod.rs.
if had_client {
if let Some(reporter) = connectivity_reporter.lock_safe().clone() {
rt.block_on(async {
match &sessions_result {
Ok(_) => reporter.report_success().await,
Err(e) => reporter.report_network_failure(Some(e.clone())).await,
}
});
}
}
// Emit event if successful
match sessions_result {
Ok(sessions) => {