feat: add cache IPC commands for analysis caching
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
153
src-tauri/src/commands/cache.rs
Normal file
153
src-tauri/src/commands/cache.rs
Normal file
@@ -0,0 +1,153 @@
|
||||
use crate::models::{ThumbnailSpritesheet, WaveformTiers};
|
||||
use crate::services::cache_manager::{self, CacheManifest, CacheStats};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CachedAnalysis {
|
||||
pub waveform_tiers: Option<WaveformTiers>,
|
||||
pub keyframe_positions: Vec<f64>,
|
||||
pub thumbnail_spritesheets: Vec<ThumbnailSpritesheet>,
|
||||
pub caption_file_path: Option<String>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn load_cached_analysis(url: String) -> Option<CachedAnalysis> {
|
||||
let url_clone = url.clone();
|
||||
let manifest = tokio::task::spawn_blocking(move || cache_manager::load_manifest(&url_clone))
|
||||
.await
|
||||
.ok()
|
||||
.flatten()?;
|
||||
|
||||
let cache_dir = cache_manager::cache_dir_for_url(&url);
|
||||
|
||||
// Resolve relative paths in thumbnail spritesheets to absolute paths
|
||||
let spritesheets: Vec<ThumbnailSpritesheet> = manifest
|
||||
.thumbnail_spritesheets
|
||||
.into_iter()
|
||||
.map(|mut sheet| {
|
||||
let abs_path = cache_dir.join(&sheet.file_path);
|
||||
sheet.file_path = abs_path.to_string_lossy().to_string();
|
||||
sheet
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Verify thumbnail files actually exist on disk
|
||||
let thumbs_valid = if spritesheets.is_empty() {
|
||||
false
|
||||
} else {
|
||||
let first_dir = std::path::Path::new(&spritesheets[0].file_path);
|
||||
first_dir.is_dir()
|
||||
};
|
||||
|
||||
// Resolve caption path to absolute
|
||||
let caption_path = manifest
|
||||
.caption_file_path
|
||||
.map(|rel| cache_dir.join(&rel).to_string_lossy().to_string())
|
||||
.filter(|p| std::path::Path::new(p).is_file());
|
||||
|
||||
Some(CachedAnalysis {
|
||||
waveform_tiers: manifest.waveform_tiers,
|
||||
keyframe_positions: manifest.keyframe_positions,
|
||||
thumbnail_spritesheets: if thumbs_valid {
|
||||
spritesheets
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
caption_file_path: caption_path,
|
||||
})
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn save_analysis_to_cache(
|
||||
url: String,
|
||||
title: String,
|
||||
duration: f64,
|
||||
fps: f64,
|
||||
waveform_tiers: Option<WaveformTiers>,
|
||||
keyframe_positions: Vec<f64>,
|
||||
thumbnail_spritesheets: Vec<ThumbnailSpritesheet>,
|
||||
caption_file_path: Option<String>,
|
||||
) -> Result<(), String> {
|
||||
let cache_dir = cache_manager::cache_dir_for_url(&url);
|
||||
|
||||
// Convert absolute spritesheet paths to relative
|
||||
let relative_sheets: Vec<ThumbnailSpritesheet> = thumbnail_spritesheets
|
||||
.into_iter()
|
||||
.map(|mut sheet| {
|
||||
if let Ok(rel) = std::path::Path::new(&sheet.file_path).strip_prefix(&cache_dir) {
|
||||
sheet.file_path = rel.to_string_lossy().to_string();
|
||||
}
|
||||
sheet
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Convert absolute caption path to relative
|
||||
let relative_caption = caption_file_path.and_then(|abs| {
|
||||
std::path::Path::new(&abs)
|
||||
.strip_prefix(&cache_dir)
|
||||
.ok()
|
||||
.map(|rel| rel.to_string_lossy().to_string())
|
||||
});
|
||||
|
||||
let now = format!(
|
||||
"{}",
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
.as_secs()
|
||||
);
|
||||
|
||||
let manifest = CacheManifest {
|
||||
version: 1,
|
||||
source_url: url.clone(),
|
||||
title,
|
||||
duration,
|
||||
fps,
|
||||
created_at: now.clone(),
|
||||
last_accessed_at: now,
|
||||
waveform_tiers,
|
||||
keyframe_positions,
|
||||
thumbnail_spritesheets: relative_sheets,
|
||||
caption_file_path: relative_caption,
|
||||
};
|
||||
|
||||
tokio::task::spawn_blocking(move || cache_manager::save_manifest(&url, &manifest))
|
||||
.await
|
||||
.map_err(|e| format!("Task failed: {e}"))?
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn clear_video_cache(url: String) -> Result<(), String> {
|
||||
tokio::task::spawn_blocking(move || cache_manager::clear_cache_entry(&url))
|
||||
.await
|
||||
.map_err(|e| format!("Task failed: {e}"))?
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn clear_all_cache() -> Result<(), String> {
|
||||
tokio::task::spawn_blocking(cache_manager::clear_all_cache)
|
||||
.await
|
||||
.map_err(|e| format!("Task failed: {e}"))?
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_cache_stats() -> Result<CacheStats, String> {
|
||||
tokio::task::spawn_blocking(cache_manager::get_cache_stats)
|
||||
.await
|
||||
.map_err(|e| format!("Task failed: {e}"))?
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_thumbnail_cache_dir(url: String) -> String {
|
||||
let dir = cache_manager::thumbnail_cache_dir(&url);
|
||||
std::fs::create_dir_all(&dir).ok();
|
||||
dir.to_string_lossy().to_string()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_caption_cache_dir(url: String) -> String {
|
||||
let dir = cache_manager::caption_cache_dir(&url);
|
||||
std::fs::create_dir_all(&dir).ok();
|
||||
dir.to_string_lossy().to_string()
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod cache;
|
||||
pub mod dependencies;
|
||||
pub mod export;
|
||||
pub mod media_analysis;
|
||||
|
||||
@@ -5,7 +5,7 @@ mod services;
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use commands::{dependencies, export, media_analysis, video};
|
||||
use commands::{cache, dependencies, export, media_analysis, video};
|
||||
use tauri::Manager;
|
||||
|
||||
struct MediaServerPort(u16);
|
||||
@@ -123,6 +123,13 @@ pub fn run() {
|
||||
media_analysis::check_embedded_subtitles,
|
||||
media_analysis::list_system_fonts,
|
||||
export::export_clips,
|
||||
cache::load_cached_analysis,
|
||||
cache::save_analysis_to_cache,
|
||||
cache::clear_video_cache,
|
||||
cache::clear_all_cache,
|
||||
cache::get_cache_stats,
|
||||
cache::get_thumbnail_cache_dir,
|
||||
cache::get_caption_cache_dir,
|
||||
get_media_server_port,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
|
||||
Reference in New Issue
Block a user