diff --git a/src-tauri/src/storage.rs b/src-tauri/src/storage.rs index c8a1c1b..e507ea3 100644 --- a/src-tauri/src/storage.rs +++ b/src-tauri/src/storage.rs @@ -179,7 +179,90 @@ fn open_database(app: &AppHandle) -> Result { } pub fn initialize_storage(app: &AppHandle) -> Result<()> { - let _ = open_database(app)?; + let connection = open_database(app)?; + migrate_legacy_files(app, &connection)?; + Ok(()) +} + +fn get_legacy_settings_path(app: &AppHandle) -> Result { + Ok(get_app_data_dir(app)?.join("settings.json")) +} + +fn get_legacy_history_path(app: &AppHandle) -> Result { + Ok(get_app_data_dir(app)?.join("history.json")) +} + +fn migrate_legacy_files(app: &AppHandle, connection: &Connection) -> Result<()> { + let task_count: i64 = connection.query_row("SELECT COUNT(*) FROM tasks", [], |row| row.get(0))?; + + let settings_path = get_legacy_settings_path(app)?; + if settings_path.exists() { + let content = fs::read_to_string(&settings_path)?; + let legacy_settings: Settings = serde_json::from_str(&content)?; + save_settings(app, &legacy_settings)?; + } + + if task_count == 0 { + let history_path = get_legacy_history_path(app)?; + if history_path.exists() { + let content = fs::read_to_string(&history_path)?; + let legacy_history: Vec = serde_json::from_str(&content)?; + for item in legacy_history { + let metadata = VideoMetadata { + id: item.id.clone(), + title: item.title.clone(), + thumbnail: item.thumbnail.clone(), + duration: None, + uploader: None, + url: Some(item.url.clone()), + extractor: None, + site_name: None, + }; + let options = DownloadOptions { + is_audio_only: false, + quality: "best".to_string(), + output_path: item.output_path.clone(), + output_format: item.format.clone(), + cookies_path: None, + }; + let metadata_json = serde_json::to_string(&metadata)?; + let options_json = serde_json::to_string(&options)?; + let status = match item.status.as_str() { + "success" => "completed", + other => other, + }; + let timestamp = to_rfc3339(item.timestamp); + + connection.execute( + "INSERT OR IGNORE INTO tasks ( + id, source_url, normalized_url, extractor, site_name, title, thumbnail, output_path, + file_path, status, progress, speed, eta, format, is_audio_only, quality, output_format, + cookies_path, error_message, created_at, started_at, finished_at, metadata_json, options_json + ) VALUES ( + ?1, ?2, ?3, NULL, NULL, ?4, ?5, ?6, + ?7, ?8, 100, '-', NULL, ?9, 0, 'best', ?10, + '', NULL, ?11, ?11, ?11, ?12, ?13 + )", + params![ + item.id, + item.url, + item.url, + item.title, + item.thumbnail, + item.output_path, + item.file_path, + status, + item.format, + item.format, + timestamp, + metadata_json, + options_json + ], + )?; + } + } + } + Ok(()) } diff --git a/src/stores/queue.ts b/src/stores/queue.ts index cb9ccc2..b936f1a 100644 --- a/src/stores/queue.ts +++ b/src/stores/queue.ts @@ -19,6 +19,8 @@ export const useQueueStore = defineStore('queue', () => { let taskUnlisten: (() => void) | null = null const activeTasks = computed(() => tasks.value.filter(task => !['completed', 'failed', 'cancelled'].includes(task.status))) + const recentTasks = computed(() => tasks.value.slice(0, 12)) + const terminalTasks = computed(() => tasks.value.filter(task => ['completed', 'failed', 'cancelled'].includes(task.status)).slice(0, 8)) function upsertTask(task: TaskRecord) { const index = tasks.value.findIndex(item => item.id === task.id) @@ -70,5 +72,5 @@ export const useQueueStore = defineStore('queue', () => { isListening.value = false } - return { tasks, activeTasks, initListener, loadTasks, cancelTask, retryTask, disposeListener } + return { tasks, activeTasks, recentTasks, terminalTasks, initListener, loadTasks, cancelTask, retryTask, disposeListener } }) diff --git a/src/views/History.vue b/src/views/History.vue index 4b7fec0..aeca7ba 100644 --- a/src/views/History.vue +++ b/src/views/History.vue @@ -1,7 +1,8 @@ @@ -137,6 +143,13 @@ onMounted(loadHistory) > +