use crate::models::{ExportConfig, ExportScope}; use crate::services::clip_exporter; use serde::Serialize; use tauri::ipc::Channel; #[derive(Clone, Serialize)] #[serde(rename_all = "camelCase", tag = "event", content = "data")] pub enum ExportEvent { Progress { current: usize, total: usize, label: String, }, Finished { paths: Vec, }, Error { message: String, }, } #[tauri::command] pub async fn export_clips( config: ExportConfig, on_event: Channel, ) -> Result, String> { tokio::task::spawn_blocking(move || { let ext = clip_exporter::get_extension(&config.source_file_path, &config.cut_mode); match config.export_scope { ExportScope::Individual => { let total = config.clips.len(); let mut output_paths = Vec::new(); for (i, clip) in config.clips.iter().enumerate() { let _ = on_event.send(ExportEvent::Progress { current: i + 1, total, label: clip.label.clone(), }); let output = clip_exporter::generate_output_path( &config.output_directory, &config.video_title, &clip.label, &ext, ); clip_exporter::export_single_clip( clip, &config.source_file_path, &output, &config.cut_mode, )?; output_paths.push(output); } let _ = on_event.send(ExportEvent::Finished { paths: output_paths.clone(), }); Ok(output_paths) } ExportScope::Merged => { let _ = on_event.send(ExportEvent::Progress { current: 1, total: 1, label: "Merging clips".to_string(), }); let output = clip_exporter::generate_output_path( &config.output_directory, &config.video_title, "Merged", &ext, ); let temp_dir = std::env::temp_dir() .join("video-clipper-merge") .join(uuid::Uuid::new_v4().to_string()); std::fs::create_dir_all(&temp_dir) .map_err(|e| format!("Failed to create temp dir: {e}"))?; let mut sorted_clips = config.clips.clone(); sorted_clips.sort_by(|a, b| { a.start_time .partial_cmp(&b.start_time) .unwrap_or(std::cmp::Ordering::Equal) }); let temp_dir_str = temp_dir.to_string_lossy().to_string(); let merge_result = clip_exporter::export_merged( &sorted_clips, &config.source_file_path, &output, &config.cut_mode, &temp_dir_str, ); let _ = std::fs::remove_dir_all(&temp_dir); merge_result?; let paths = vec![output]; let _ = on_event.send(ExportEvent::Finished { paths: paths.clone(), }); Ok(paths) } } }) .await .map_err(|e| format!("Task failed: {e}"))? }