use std::path::{Path, PathBuf};
use tracing::info;
use crate::error::PageError;
use super::video::Video;
impl Video {
pub async fn save_as(&self, path: impl AsRef<Path>) -> Result<(), PageError> {
let current_path = self.path().await?;
let target_path = path.as_ref();
if let Some(parent) = target_path.parent() {
tokio::fs::create_dir_all(parent).await.map_err(|e| {
PageError::EvaluationFailed(format!("Failed to create directory: {e}"))
})?;
}
tokio::fs::copy(¤t_path, target_path)
.await
.map_err(|e| PageError::EvaluationFailed(format!("Failed to copy video: {e}")))?;
let state = self.state.read().await;
if let Some(ref video_path) = state.video_path {
if let Ok(content) = tokio::fs::read_to_string(video_path).await {
if let Ok(metadata) = serde_json::from_str::<serde_json::Value>(&content) {
if let Some(frames_dir) = metadata.get("frames_dir").and_then(|v| v.as_str()) {
let source_frames = PathBuf::from(frames_dir);
if source_frames.exists() {
let target_frames = target_path.with_extension("frames");
copy_dir_recursive(&source_frames, &target_frames).await?;
}
}
}
}
}
info!("Video saved to {:?}", target_path);
Ok(())
}
pub async fn delete(&self) -> Result<(), PageError> {
let state = self.state.read().await;
if let Some(ref video_path) = state.video_path {
if let Ok(content) = tokio::fs::read_to_string(video_path).await {
if let Ok(metadata) = serde_json::from_str::<serde_json::Value>(&content) {
if let Some(frames_dir) = metadata.get("frames_dir").and_then(|v| v.as_str()) {
let frames_path = PathBuf::from(frames_dir);
if frames_path.exists() {
let _ = tokio::fs::remove_dir_all(&frames_path).await;
}
}
}
}
tokio::fs::remove_file(video_path)
.await
.map_err(|e| PageError::EvaluationFailed(format!("Failed to delete video: {e}")))?;
info!("Video deleted");
}
Ok(())
}
}
pub(super) async fn copy_dir_recursive(src: &Path, dst: &Path) -> Result<(), PageError> {
tokio::fs::create_dir_all(dst)
.await
.map_err(|e| PageError::EvaluationFailed(format!("Failed to create directory: {e}")))?;
let mut entries = tokio::fs::read_dir(src)
.await
.map_err(|e| PageError::EvaluationFailed(format!("Failed to read directory: {e}")))?;
while let Some(entry) = entries
.next_entry()
.await
.map_err(|e| PageError::EvaluationFailed(format!("Failed to read directory entry: {e}")))?
{
let src_path = entry.path();
let dst_path = dst.join(entry.file_name());
if src_path.is_dir() {
Box::pin(copy_dir_recursive(&src_path, &dst_path)).await?;
} else {
tokio::fs::copy(&src_path, &dst_path)
.await
.map_err(|e| PageError::EvaluationFailed(format!("Failed to copy file: {e}")))?;
}
}
Ok(())
}