//! Tauri commands for playback reporting operations //! //! These commands provide frontend access to the Rust playback reporting system, //! replacing the TypeScript implementation with native Rust reporting. //! //! Commands are registered but not yet called from the frontend. //! Dead code warnings are suppressed until frontend migration is complete. #![allow(dead_code)] use std::sync::Arc; use tauri::State; use tokio::sync::Mutex as TokioMutex; use crate::commands::connectivity::ConnectivityMonitorWrapper; use crate::commands::storage::DatabaseWrapper; use crate::jellyfin::client::JellyfinClient; use crate::jellyfin::JellyfinConfig; use crate::playback_reporting::{PlaybackReporter, PlaybackOperation, PlaybackContext}; use crate::utils::conversions::seconds_to_ticks; /// Tauri state wrapper for PlaybackReporter pub struct PlaybackReporterWrapper(pub Arc>>); /// Initialize playback reporter (called after login) #[tauri::command] pub async fn playback_reporter_init( reporter_wrapper: State<'_, PlaybackReporterWrapper>, db: State<'_, DatabaseWrapper>, server_url: String, user_id: String, access_token: String, device_id: String, ) -> Result<(), String> { log::info!("[PlaybackReporter] Initializing for user: {}", user_id); // Get database service let db_service = { let database = db.0.lock().map_err(|e| e.to_string())?; Arc::new(database.service()) }; // Create JellyfinClient let jellyfin_config = JellyfinConfig { server_url, access_token, device_id, }; let jellyfin_client = JellyfinClient::new(jellyfin_config) .map_err(|e| format!("Failed to create JellyfinClient: {}", e))?; // Create PlaybackReporter let reporter = PlaybackReporter::new( db_service, Arc::new(TokioMutex::new(Some(jellyfin_client))), user_id.clone(), ); // Store in wrapper *reporter_wrapper.0.lock().await = Some(reporter); log::info!("[PlaybackReporter] Initialized successfully for user: {}", user_id); Ok(()) } /// Destroy playback reporter (called on logout) #[tauri::command] pub async fn playback_reporter_destroy( reporter_wrapper: State<'_, PlaybackReporterWrapper>, ) -> Result<(), String> { log::info!("[PlaybackReporter] Destroying reporter"); *reporter_wrapper.0.lock().await = None; Ok(()) } /// Report playback start #[tauri::command] pub async fn playback_report_start( reporter: State<'_, PlaybackReporterWrapper>, connectivity: State<'_, ConnectivityMonitorWrapper>, item_id: String, position_seconds: f64, context_type: Option, context_id: Option, ) -> Result<(), String> { let reporter_guard = reporter.0.lock().await; let reporter_instance = reporter_guard .as_ref() .ok_or("PlaybackReporter not initialized")?; let position_ticks = seconds_to_ticks(position_seconds); let context = context_type.map(|ct| PlaybackContext { context_type: ct, context_id, }); let operation = PlaybackOperation::Start { item_id, position_ticks, context, }; let monitor = connectivity.0.lock().await; let is_online = monitor.get_status().await.is_server_reachable; drop(monitor); reporter_instance.report(operation, is_online).await } /// Report playback progress #[tauri::command] pub async fn playback_report_progress( reporter: State<'_, PlaybackReporterWrapper>, connectivity: State<'_, ConnectivityMonitorWrapper>, item_id: String, position_seconds: f64, is_paused: bool, ) -> Result<(), String> { let reporter_guard = reporter.0.lock().await; let reporter_instance = reporter_guard .as_ref() .ok_or("PlaybackReporter not initialized")?; let position_ticks = seconds_to_ticks(position_seconds); let operation = PlaybackOperation::Progress { item_id, position_ticks, is_paused, }; let monitor = connectivity.0.lock().await; let is_online = monitor.get_status().await.is_server_reachable; drop(monitor); reporter_instance.report(operation, is_online).await } /// Report playback stopped #[tauri::command] pub async fn playback_report_stopped( reporter: State<'_, PlaybackReporterWrapper>, connectivity: State<'_, ConnectivityMonitorWrapper>, item_id: String, position_seconds: f64, ) -> Result<(), String> { let reporter_guard = reporter.0.lock().await; let reporter_instance = reporter_guard .as_ref() .ok_or("PlaybackReporter not initialized")?; let position_ticks = seconds_to_ticks(position_seconds); let operation = PlaybackOperation::Stopped { item_id, position_ticks, }; let monitor = connectivity.0.lock().await; let is_online = monitor.get_status().await.is_server_reachable; drop(monitor); reporter_instance.report(operation, is_online).await } /// Mark item as played #[tauri::command] pub async fn playback_mark_played( reporter: State<'_, PlaybackReporterWrapper>, connectivity: State<'_, ConnectivityMonitorWrapper>, item_id: String, ) -> Result<(), String> { let reporter_guard = reporter.0.lock().await; let reporter_instance = reporter_guard .as_ref() .ok_or("PlaybackReporter not initialized")?; let operation = PlaybackOperation::MarkPlayed { item_id }; let monitor = connectivity.0.lock().await; let is_online = monitor.get_status().await.is_server_reachable; drop(monitor); reporter_instance.report(operation, is_online).await }