Wire up playback reporting, fix duration flash, hide video from audio mini player
Playback reporting (position sync / resume-on-another-device): - player_configure_jellyfin now builds a PlaybackReporter sharing the player controller's Arc, so Start/Progress/Stopped actually reach Jellyfin on every auth path (login/restore/reauth); previously they never did. - The PlaybackReporterWrapper now shares the same Arc the controller and MPV progress loop report through, instead of a dead parallel Option. - Android position callbacks now emit throttled progress reports (30s/item), mirroring the MPV backend. Duration flash on pause: - resolveDuration() prefers the live store duration for the already-loaded track over the runTimeTicks estimate, so pausing no longer clobbers the slider's max to 0 when runTimeTicks is missing. Video leaking into audio mini player: - isVideoItem() also checks the backend PlayerMediaItem mediaType discriminator, so a video started via player_play_item (no Jellyfin `type`, mediaType "video") no longer surfaces in the audio mini player. Middle-truncation of long media names: - New truncateMiddle util applied to track/episode/card/mini-player titles so distinguishing tails (episode numbers, suffixes) stay visible. Adds regression tests for the duration and mini-player fixes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1826,9 +1826,10 @@ pub async fn player_get_cache_config(
|
||||
#[specta::specta]
|
||||
pub async fn player_configure_jellyfin(
|
||||
player: State<'_, PlayerStateWrapper>,
|
||||
db: State<'_, DatabaseWrapper>,
|
||||
server_url: String,
|
||||
access_token: String,
|
||||
_user_id: String,
|
||||
user_id: String,
|
||||
device_id: String,
|
||||
) -> Result<(), String> {
|
||||
log::info!("[PlayerCommand] Configuring Jellyfin client for playback reporting");
|
||||
@@ -1839,12 +1840,31 @@ pub async fn player_configure_jellyfin(
|
||||
device_id,
|
||||
};
|
||||
|
||||
let client = JellyfinClient::new(config)?;
|
||||
// Legacy client (used for remote session control / casting).
|
||||
let client = JellyfinClient::new(config.clone())?;
|
||||
|
||||
// Build the PlaybackReporter the player and backends (MPV + ExoPlayer)
|
||||
// actually report through. Without this, Start/Progress/Stopped never reach
|
||||
// Jellyfin, so playback position never syncs and you can't resume on another
|
||||
// device. The reporter shares the player controller's Arc, so populating it
|
||||
// here lights up reporting on both desktop and Android, on every auth path
|
||||
// that configures the player (login / restore / reauth).
|
||||
let db_service = {
|
||||
let database = db.0.lock().map_err(|e| e.to_string())?;
|
||||
Arc::new(database.service())
|
||||
};
|
||||
let reporter_client = JellyfinClient::new(config)?;
|
||||
let reporter = crate::playback_reporting::PlaybackReporter::new(
|
||||
db_service,
|
||||
Arc::new(TokioMutex::new(Some(reporter_client))),
|
||||
user_id,
|
||||
);
|
||||
|
||||
let controller = player.0.lock().await;
|
||||
controller.set_jellyfin_client(Some(client));
|
||||
controller.set_playback_reporter(Some(reporter)).await;
|
||||
|
||||
log::info!("[PlayerCommand] Jellyfin client configured successfully");
|
||||
log::info!("[PlayerCommand] Jellyfin client and playback reporter configured successfully");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1858,8 +1878,9 @@ pub async fn player_disable_jellyfin(
|
||||
|
||||
let controller = player.0.lock().await;
|
||||
controller.set_jellyfin_client(None);
|
||||
controller.set_playback_reporter(None).await;
|
||||
|
||||
log::info!("[PlayerCommand] Jellyfin client disabled");
|
||||
log::info!("[PlayerCommand] Jellyfin client and playback reporter disabled");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user