fix: clear thumbnail cache and temp dirs on new session

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-21 11:18:14 -04:00
parent ab053edd14
commit 8013ef7c55
6 changed files with 39 additions and 0 deletions

View File

@@ -35,3 +35,10 @@ pub async fn extract_thumbnails(
.await .await
.map_err(|e| format!("Task failed: {e}"))? .map_err(|e| format!("Task failed: {e}"))?
} }
#[tauri::command]
pub async fn cleanup_thumbnails(paths: Vec<String>) -> Result<(), String> {
tokio::task::spawn_blocking(move || thumbnail_extractor::cleanup_thumbnail_dirs(&paths))
.await
.map_err(|e| format!("Task failed: {e}"))?
}

View File

@@ -19,6 +19,7 @@ pub fn run() {
media_analysis::extract_keyframes, media_analysis::extract_keyframes,
media_analysis::extract_waveform, media_analysis::extract_waveform,
media_analysis::extract_thumbnails, media_analysis::extract_thumbnails,
media_analysis::cleanup_thumbnails,
]) ])
.run(tauri::generate_context!()) .run(tauri::generate_context!())
.expect("error while running tauri application"); .expect("error while running tauri application");

View File

@@ -76,6 +76,17 @@ pub fn extract_thumbnails(
Ok(sheets) Ok(sheets)
} }
pub fn cleanup_thumbnail_dirs(paths: &[String]) -> Result<(), String> {
for path in paths {
let dir = std::path::Path::new(path);
if dir.is_dir() {
std::fs::remove_dir_all(dir)
.map_err(|e| format!("Failed to remove thumbnail dir {path}: {e}"))?;
}
}
Ok(())
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@@ -30,3 +30,7 @@ export async function extractThumbnails(
duration, duration,
}); });
} }
export async function cleanupThumbnails(paths: string[]): Promise<void> {
return invoke<void>('cleanup_thumbnails', { paths });
}

View File

@@ -2,10 +2,12 @@ import type { VideoMetadata } from '$lib/bindings/video';
import { startDownload } from '$lib/bindings/video'; import { startDownload } from '$lib/bindings/video';
import type { ThumbnailSpritesheet } from '$lib/bindings/mediaAnalysis'; import type { ThumbnailSpritesheet } from '$lib/bindings/mediaAnalysis';
import { import {
cleanupThumbnails,
extractKeyframes, extractKeyframes,
extractThumbnails, extractThumbnails,
extractWaveform, extractWaveform,
} from '$lib/bindings/mediaAnalysis'; } from '$lib/bindings/mediaAnalysis';
import { clearThumbnailCache } from '$lib/timeline/thumbnailRenderer';
export type SessionStatus = 'idle' | 'resolving' | 'ready' | 'error'; export type SessionStatus = 'idle' | 'resolving' | 'ready' | 'error';
export type DownloadStatus = 'idle' | 'downloading' | 'complete' | 'failed'; export type DownloadStatus = 'idle' | 'downloading' | 'complete' | 'failed';
@@ -112,6 +114,10 @@ async function triggerPostDownloadProcessing(filePath: string) {
export async function beginDownload() { export async function beginDownload() {
if (!session.url) return; if (!session.url) return;
const oldThumbnailDirs = [
...new Set(session.thumbnailSpritesheets.map((sheet) => sheet.filePath)),
];
clearThumbnailCache();
session.downloadStatus = 'downloading'; session.downloadStatus = 'downloading';
session.downloadProgress = 0; session.downloadProgress = 0;
session.localFilePath = null; session.localFilePath = null;
@@ -119,6 +125,12 @@ export async function beginDownload() {
session.waveformPeaks = []; session.waveformPeaks = [];
session.thumbnailSpritesheets = []; session.thumbnailSpritesheets = [];
if (oldThumbnailDirs.length > 0) {
void cleanupThumbnails(oldThumbnailDirs).catch((err) => {
console.error('Thumbnail temp dir cleanup failed:', err);
});
}
try { try {
await startDownload( await startDownload(
session.url, session.url,

View File

@@ -4,6 +4,10 @@ import { timeToX, type TimelineState } from './renderer';
const imageCache = new Map<string, HTMLImageElement>(); const imageCache = new Map<string, HTMLImageElement>();
export function clearThumbnailCache(): void {
imageCache.clear();
}
const TARGET_SPACING_PX = 100; const TARGET_SPACING_PX = 100;
function getImagePath(dir: string, frameIndex: number): string { function getImagePath(dir: string, frameIndex: number): string {