chore: optimize ui and save structure (#19)

* feat: persist and use saved file name for downloads

* feat(settings): ensure and migrate download directory to VidBee/Downloads

* feat: format download dates with locale date and time for clarity

* feat(files): try multiple candidate file paths for file ops and DRY logic

* fix(download): handle multi-path file deletion and warn on failure
This commit is contained in:
Nexmoe
2025-11-08 21:28:51 +08:00
committed by GitHub
parent 27287238aa
commit bd7f4a433c
7 changed files with 521 additions and 117 deletions

View File

@@ -80,7 +80,7 @@ export const buildDownloadArgs = (
}
// Output path with proper encoding handling
const outputTemplate = path.join(downloadPath, '%(title)s.%(ext)s')
const outputTemplate = path.join(downloadPath, '%(title)s via VidBee.%(ext)s')
args.push('-o', outputTemplate)
// Add options for better filename handling

View File

@@ -742,13 +742,16 @@ class DownloadEngine extends EventEmitter {
fileSize = latestKnownSizeBytes
}
const savedFileName = path.basename(actualFilePath)
this.updateDownloadInfo(id, {
status: 'completed',
completedAt: Date.now(),
fileSize,
format: willMerge ? 'mp4' : actualFormat || undefined,
quality: actualQuality || undefined,
codec: actualCodec || undefined
codec: actualCodec || undefined,
savedFileName
})
scopedLoggers.download.info('Download completed successfully for ID:', id)
this.emit('download-completed', id)
@@ -882,6 +885,9 @@ class DownloadEngine extends EventEmitter {
if (updates.selectedFormat !== undefined) {
historyUpdates.selectedFormat = updates.selectedFormat
}
if (updates.savedFileName !== undefined) {
historyUpdates.savedFileName = updates.savedFileName
}
if (Object.keys(historyUpdates).length > 0) {
this.upsertHistoryEntry(id, snapshot.options, historyUpdates)
@@ -936,6 +942,7 @@ class DownloadEngine extends EventEmitter {
type: options.type,
status: updates.status || 'pending',
downloadPath: updates.downloadPath,
savedFileName: updates.savedFileName,
fileSize: updates.fileSize,
duration: updates.duration,
downloadedAt: updates.downloadedAt ?? Date.now(),

View File

@@ -1,3 +1,4 @@
import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import type { AppSettings } from '../shared/types'
@@ -8,6 +9,24 @@ const ElectronStore = require('electron-store')
// Access the default export
const Store = ElectronStore.default || ElectronStore
const OLD_DEFAULT_DOWNLOAD_PATH = path.join(os.homedir(), 'Downloads')
const ensureDirectoryExists = (dir: string) => {
try {
fs.mkdirSync(dir, { recursive: true })
} catch (error) {
console.error('Failed to ensure download directory:', error)
}
}
const resolveDefaultDownloadPath = () => {
const downloadDir = path.join(os.homedir(), 'Downloads', 'VidBee')
ensureDirectoryExists(downloadDir)
return downloadDir
}
const DEFAULT_DOWNLOAD_PATH = resolveDefaultDownloadPath()
class SettingsManager {
// biome-ignore lint/suspicious/noExplicitAny: electron-store requires dynamic import
private store: any
@@ -16,9 +35,10 @@ class SettingsManager {
this.store = new Store({
defaults: {
...defaultSettings,
downloadPath: path.join(os.homedir(), 'Downloads')
downloadPath: DEFAULT_DOWNLOAD_PATH
}
})
this.ensureDownloadDirectory()
}
get<K extends keyof AppSettings>(key: K): AppSettings[K] {
@@ -26,6 +46,9 @@ class SettingsManager {
}
set<K extends keyof AppSettings>(key: K, value: AppSettings[K]): void {
if (key === 'downloadPath' && typeof value === 'string') {
ensureDirectoryExists(value)
}
this.store.set(key, value)
}
@@ -35,6 +58,9 @@ class SettingsManager {
setAll(settings: Partial<AppSettings>): void {
for (const [key, value] of Object.entries(settings)) {
if (key === 'downloadPath' && typeof value === 'string') {
ensureDirectoryExists(value)
}
this.store.set(key as keyof AppSettings, value as AppSettings[keyof AppSettings])
}
}
@@ -43,8 +69,22 @@ class SettingsManager {
this.store.clear()
this.store.set({
...defaultSettings,
downloadPath: path.join(os.homedir(), 'Downloads')
downloadPath: DEFAULT_DOWNLOAD_PATH
})
ensureDirectoryExists(DEFAULT_DOWNLOAD_PATH)
}
private ensureDownloadDirectory(): void {
try {
const currentPath: string | undefined = this.store.get('downloadPath')
if (!currentPath || currentPath === OLD_DEFAULT_DOWNLOAD_PATH) {
this.store.set('downloadPath', DEFAULT_DOWNLOAD_PATH)
return
}
ensureDirectoryExists(currentPath)
} catch (error) {
console.error('Failed to verify download directory:', error)
}
}
}