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:
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user