jellytau/src-tauri/src/commands/playback_reporting.rs

185 lines
5.5 KiB
Rust

//! 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<TokioMutex<Option<PlaybackReporter>>>);
/// 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<String>,
context_id: Option<String>,
) -> 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
}