refactor(types): remove obsolete format/quality/codec fields and related logic to simplify download and avoid redundant storage
This commit is contained in:
@@ -407,8 +407,7 @@ class DownloadEngine extends EventEmitter {
|
||||
createdAt,
|
||||
tags: options.tags,
|
||||
origin,
|
||||
subscriptionId: options.subscriptionId,
|
||||
subscriptionTitle: options.subscriptionTitle
|
||||
subscriptionId: options.subscriptionId
|
||||
}
|
||||
|
||||
this.queue.add(id, options, item)
|
||||
@@ -420,8 +419,7 @@ class DownloadEngine extends EventEmitter {
|
||||
downloadPath: targetDownloadPath,
|
||||
tags: options.tags,
|
||||
origin,
|
||||
subscriptionId: options.subscriptionId,
|
||||
subscriptionTitle: options.subscriptionTitle
|
||||
subscriptionId: options.subscriptionId
|
||||
})
|
||||
}
|
||||
|
||||
@@ -441,8 +439,6 @@ class DownloadEngine extends EventEmitter {
|
||||
let availableFormats: VideoFormat[] = []
|
||||
let selectedFormat: VideoFormat | undefined
|
||||
let actualFormat: string | null = null
|
||||
let actualQuality: string | null = null
|
||||
let actualCodec: string | null = null
|
||||
let videoInfo: VideoInfo | undefined
|
||||
|
||||
// First, get detailed video info to capture basic metadata and formats
|
||||
@@ -455,20 +451,6 @@ class DownloadEngine extends EventEmitter {
|
||||
|
||||
if (selectedFormat) {
|
||||
actualFormat = selectedFormat.ext || actualFormat
|
||||
|
||||
if (selectedFormat.height) {
|
||||
actualQuality = `${selectedFormat.height}p${
|
||||
selectedFormat.fps && selectedFormat.fps === 60 ? '60' : ''
|
||||
}`
|
||||
} else if (selectedFormat.format_note) {
|
||||
actualQuality = selectedFormat.format_note
|
||||
}
|
||||
|
||||
if (options.type === 'audio' || options.type === 'extract') {
|
||||
actualCodec = selectedFormat.acodec || actualCodec
|
||||
} else {
|
||||
actualCodec = selectedFormat.vcodec || selectedFormat.acodec || actualCodec
|
||||
}
|
||||
}
|
||||
|
||||
this.updateDownloadInfo(id, {
|
||||
@@ -513,18 +495,6 @@ class DownloadEngine extends EventEmitter {
|
||||
selectedFormat = candidate
|
||||
actualFormat = candidate.ext || actualFormat
|
||||
|
||||
if (candidate.height) {
|
||||
actualQuality = `${candidate.height}p${candidate.fps === 60 ? '60' : ''}`
|
||||
} else if (candidate.format_note) {
|
||||
actualQuality = candidate.format_note
|
||||
}
|
||||
|
||||
if (options.type === 'audio' || options.type === 'extract') {
|
||||
actualCodec = candidate.acodec || actualCodec
|
||||
} else {
|
||||
actualCodec = candidate.vcodec || candidate.acodec || actualCodec
|
||||
}
|
||||
|
||||
this.updateDownloadInfo(id, {
|
||||
selectedFormat: candidate
|
||||
})
|
||||
@@ -640,16 +610,6 @@ class DownloadEngine extends EventEmitter {
|
||||
if (extMatch && !actualFormat) {
|
||||
actualFormat = extMatch[1]
|
||||
}
|
||||
|
||||
const heightMatch = formatInfo.match(/(\d+)p/)
|
||||
if (heightMatch && !actualQuality) {
|
||||
actualQuality = `${heightMatch[1]}p`
|
||||
}
|
||||
|
||||
const codecMatch = formatInfo.match(/(?:vcodec|acodec)[:\s]*([^\s,]+)/)
|
||||
if (codecMatch && !actualCodec) {
|
||||
actualCodec = codecMatch[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,9 +719,6 @@ class DownloadEngine extends EventEmitter {
|
||||
status: 'completed',
|
||||
completedAt: Date.now(),
|
||||
fileSize,
|
||||
format: willMerge ? 'mp4' : actualFormat || undefined,
|
||||
quality: actualQuality || undefined,
|
||||
codec: actualCodec || undefined,
|
||||
savedFileName
|
||||
})
|
||||
scopedLoggers.download.info('Download completed successfully for ID:', id)
|
||||
@@ -848,15 +805,6 @@ class DownloadEngine extends EventEmitter {
|
||||
if (updates.fileSize !== undefined) {
|
||||
historyUpdates.fileSize = updates.fileSize
|
||||
}
|
||||
if (updates.format !== undefined) {
|
||||
historyUpdates.format = updates.format
|
||||
}
|
||||
if (updates.quality !== undefined) {
|
||||
historyUpdates.quality = updates.quality
|
||||
}
|
||||
if (updates.codec !== undefined) {
|
||||
historyUpdates.codec = updates.codec
|
||||
}
|
||||
if (updates.description !== undefined) {
|
||||
historyUpdates.description = updates.description
|
||||
}
|
||||
@@ -884,6 +832,9 @@ class DownloadEngine extends EventEmitter {
|
||||
if (updates.playlistSize !== undefined) {
|
||||
historyUpdates.playlistSize = updates.playlistSize
|
||||
}
|
||||
if (updates.selectedFormat !== undefined) {
|
||||
historyUpdates.selectedFormat = updates.selectedFormat
|
||||
}
|
||||
if (updates.status !== undefined) {
|
||||
historyUpdates.status = updates.status
|
||||
}
|
||||
@@ -893,9 +844,6 @@ class DownloadEngine extends EventEmitter {
|
||||
if (updates.error !== undefined) {
|
||||
historyUpdates.error = updates.error
|
||||
}
|
||||
if (updates.selectedFormat !== undefined) {
|
||||
historyUpdates.selectedFormat = updates.selectedFormat
|
||||
}
|
||||
if (updates.savedFileName !== undefined) {
|
||||
historyUpdates.savedFileName = updates.savedFileName
|
||||
}
|
||||
@@ -924,9 +872,6 @@ class DownloadEngine extends EventEmitter {
|
||||
error,
|
||||
duration: completedDownload?.item.duration,
|
||||
fileSize: completedDownload?.item.fileSize,
|
||||
format: completedDownload?.item.format,
|
||||
quality: completedDownload?.item.quality,
|
||||
codec: completedDownload?.item.codec,
|
||||
description: completedDownload?.item.description,
|
||||
channel: completedDownload?.item.channel,
|
||||
uploader: completedDownload?.item.uploader,
|
||||
@@ -934,7 +879,6 @@ class DownloadEngine extends EventEmitter {
|
||||
tags: completedDownload?.item.tags,
|
||||
origin: completedDownload?.item.origin,
|
||||
subscriptionId: completedDownload?.item.subscriptionId,
|
||||
subscriptionTitle: completedDownload?.item.subscriptionTitle,
|
||||
playlistId: completedDownload?.item.playlistId,
|
||||
playlistTitle: completedDownload?.item.playlistTitle,
|
||||
playlistIndex: completedDownload?.item.playlistIndex,
|
||||
@@ -964,9 +908,6 @@ class DownloadEngine extends EventEmitter {
|
||||
downloadedAt: updates.downloadedAt ?? Date.now(),
|
||||
completedAt: updates.completedAt,
|
||||
error: updates.error,
|
||||
format: updates.format,
|
||||
quality: updates.quality,
|
||||
codec: updates.codec,
|
||||
description: updates.description,
|
||||
channel: updates.channel,
|
||||
uploader: updates.uploader,
|
||||
@@ -974,7 +915,6 @@ class DownloadEngine extends EventEmitter {
|
||||
tags: updates.tags ?? options.tags,
|
||||
origin: updates.origin ?? options.origin,
|
||||
subscriptionId: updates.subscriptionId ?? options.subscriptionId,
|
||||
subscriptionTitle: updates.subscriptionTitle ?? options.subscriptionTitle,
|
||||
// Download-specific format info
|
||||
selectedFormat: updates.selectedFormat,
|
||||
playlistId: updates.playlistId,
|
||||
@@ -995,8 +935,7 @@ class DownloadEngine extends EventEmitter {
|
||||
downloadPath: resolvedDownloadPath ?? base.downloadPath,
|
||||
tags: updates.tags ?? base.tags,
|
||||
origin: updates.origin ?? base.origin,
|
||||
subscriptionId: updates.subscriptionId ?? base.subscriptionId,
|
||||
subscriptionTitle: updates.subscriptionTitle ?? base.subscriptionTitle
|
||||
subscriptionId: updates.subscriptionId ?? base.subscriptionId
|
||||
}
|
||||
|
||||
historyManager.addHistoryItem(merged)
|
||||
|
||||
@@ -371,8 +371,7 @@ export class SubscriptionScheduler extends EventEmitter {
|
||||
customFilenameTemplate: namingTemplate,
|
||||
tags,
|
||||
origin: 'subscription',
|
||||
subscriptionId,
|
||||
subscriptionTitle: subscription.title
|
||||
subscriptionId
|
||||
})
|
||||
|
||||
this.downloads.set(downloadId, {
|
||||
|
||||
@@ -55,6 +55,73 @@ const tryFileOperation = async (
|
||||
return false
|
||||
}
|
||||
|
||||
const getSavedFileExtension = (fileName?: string): string | undefined => {
|
||||
if (!fileName) {
|
||||
return undefined
|
||||
}
|
||||
const normalized = fileName.trim()
|
||||
if (!normalized.includes('.')) {
|
||||
return undefined
|
||||
}
|
||||
const ext = normalized.split('.').pop()
|
||||
return ext?.toLowerCase()
|
||||
}
|
||||
|
||||
const resolveDownloadExtension = (download: DownloadRecord): string => {
|
||||
const savedExt = getSavedFileExtension(download.savedFileName)
|
||||
if (savedExt) {
|
||||
return savedExt
|
||||
}
|
||||
const selectedExt = download.selectedFormat?.ext?.toLowerCase()
|
||||
if (selectedExt) {
|
||||
return selectedExt
|
||||
}
|
||||
return download.type === 'audio' ? 'mp3' : 'mp4'
|
||||
}
|
||||
|
||||
const getFormatLabel = (download: DownloadRecord): string | undefined => {
|
||||
if (download.selectedFormat?.ext) {
|
||||
return download.selectedFormat.ext.toUpperCase()
|
||||
}
|
||||
const savedExt = getSavedFileExtension(download.savedFileName)
|
||||
return savedExt ? savedExt.toUpperCase() : undefined
|
||||
}
|
||||
|
||||
const getQualityLabel = (download: DownloadRecord): string | undefined => {
|
||||
const format = download.selectedFormat
|
||||
if (!format) {
|
||||
return undefined
|
||||
}
|
||||
if (format.height) {
|
||||
return `${format.height}p${format.fps === 60 ? '60' : ''}`
|
||||
}
|
||||
if (format.format_note) {
|
||||
return format.format_note
|
||||
}
|
||||
if (typeof format.quality === 'number') {
|
||||
return format.quality.toString()
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
const sanitizeCodec = (codec?: string | null): string | undefined => {
|
||||
if (!codec || codec === 'none') {
|
||||
return undefined
|
||||
}
|
||||
return codec
|
||||
}
|
||||
|
||||
const getCodecLabel = (download: DownloadRecord): string | undefined => {
|
||||
const format = download.selectedFormat
|
||||
if (!format) {
|
||||
return undefined
|
||||
}
|
||||
if (download.type === 'audio' || download.type === 'extract') {
|
||||
return sanitizeCodec(format.acodec)
|
||||
}
|
||||
return sanitizeCodec(format.vcodec) ?? sanitizeCodec(format.acodec)
|
||||
}
|
||||
|
||||
interface DownloadItemProps {
|
||||
download: DownloadRecord
|
||||
}
|
||||
@@ -106,8 +173,7 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
const removeHistory = useSetAtom(removeHistoryRecordAtom)
|
||||
const isHistory = download.entryType === 'history'
|
||||
const isSubscriptionDownload = download.origin === 'subscription'
|
||||
const subscriptionLabel =
|
||||
download.subscriptionTitle ?? download.subscriptionId ?? t('subscriptions.labels.unknown')
|
||||
const subscriptionLabel = download.subscriptionId ?? t('subscriptions.labels.unknown')
|
||||
const timestamp = download.completedAt ?? download.downloadedAt ?? download.createdAt
|
||||
const showActionsWithoutHover = isHistory || download.status === 'completed'
|
||||
const actionsContainerBaseClass =
|
||||
@@ -115,6 +181,7 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
const actionsContainerClass = showActionsWithoutHover
|
||||
? actionsContainerBaseClass
|
||||
: `${actionsContainerBaseClass} sm:opacity-0 sm:group-hover:opacity-100`
|
||||
const resolvedExtension = resolveDownloadExtension(download)
|
||||
|
||||
// Track if the file exists
|
||||
const [fileExists, setFileExists] = useState(false)
|
||||
@@ -129,7 +196,7 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
}
|
||||
|
||||
try {
|
||||
const formatForPath = download.format || (download.type === 'audio' ? 'mp3' : 'mp4')
|
||||
const formatForPath = resolvedExtension
|
||||
const filePaths = generateFilePathCandidates(
|
||||
download.downloadPath,
|
||||
download.title,
|
||||
@@ -151,13 +218,7 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
}
|
||||
|
||||
checkFileExists()
|
||||
}, [
|
||||
download.title,
|
||||
download.downloadPath,
|
||||
download.format,
|
||||
download.savedFileName,
|
||||
download.type
|
||||
])
|
||||
}, [download.title, download.downloadPath, download.savedFileName, resolvedExtension])
|
||||
|
||||
const handleCancel = async () => {
|
||||
if (isHistory) return
|
||||
@@ -172,7 +233,7 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
const handleOpenFolder = async () => {
|
||||
try {
|
||||
const downloadPath = download.downloadPath || settings.downloadPath
|
||||
const format = download.format || (download.type === 'audio' ? 'mp3' : 'mp4')
|
||||
const format = resolvedExtension
|
||||
const filePaths = generateFilePathCandidates(
|
||||
downloadPath,
|
||||
download.title,
|
||||
@@ -193,12 +254,7 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
}
|
||||
// Check if copy to clipboard is available
|
||||
const canCopyToClipboard = () => {
|
||||
return !!(
|
||||
download.title &&
|
||||
download.downloadPath &&
|
||||
fileExists &&
|
||||
(download.savedFileName || download.format)
|
||||
)
|
||||
return Boolean(download.title && download.downloadPath && fileExists)
|
||||
}
|
||||
|
||||
// need title, downloadPath, format
|
||||
@@ -210,10 +266,10 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
|
||||
// Type guard: these values are guaranteed to exist after canCopyToClipboard() check
|
||||
const downloadPath = download.downloadPath
|
||||
const format = download.format
|
||||
const format = resolvedExtension
|
||||
const title = download.title
|
||||
|
||||
if (!downloadPath || !format || !title) {
|
||||
if (!downloadPath || !title) {
|
||||
toast.error(t('notifications.copyFailed'))
|
||||
return
|
||||
}
|
||||
@@ -246,7 +302,7 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
if (!isHistory) return
|
||||
try {
|
||||
const downloadPath = download.downloadPath || settings.downloadPath
|
||||
const format = download.format || (download.type === 'audio' ? 'mp3' : 'mp4')
|
||||
const format = resolvedExtension
|
||||
const filePaths = generateFilePathCandidates(
|
||||
downloadPath,
|
||||
download.title,
|
||||
@@ -363,11 +419,7 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
download.selectedFormat?.filesize || download.selectedFormat?.filesize_approx
|
||||
const inlineFileSize = selectedFormatSize ? formatFileSize(selectedFormatSize) : undefined
|
||||
|
||||
const formatLabelValue = download.selectedFormat?.ext
|
||||
? download.selectedFormat.ext.toUpperCase()
|
||||
: download.format
|
||||
? download.format.toUpperCase()
|
||||
: undefined
|
||||
const formatLabelValue = getFormatLabel(download)
|
||||
|
||||
if (formatLabelValue) {
|
||||
metadataDetails.push({
|
||||
@@ -376,14 +428,12 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
})
|
||||
}
|
||||
|
||||
const qualityValue = download.selectedFormat?.height
|
||||
? `${download.selectedFormat.height}p${download.selectedFormat.fps === 60 ? '60' : ''}`
|
||||
: download.quality
|
||||
const qualityLabel = getQualityLabel(download)
|
||||
|
||||
if (qualityValue) {
|
||||
if (qualityLabel) {
|
||||
metadataDetails.push({
|
||||
label: t('download.metadata.quality'),
|
||||
value: qualityValue
|
||||
value: qualityLabel
|
||||
})
|
||||
}
|
||||
|
||||
@@ -394,10 +444,11 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
})
|
||||
}
|
||||
|
||||
if (download.codec) {
|
||||
const codecValue = getCodecLabel(download)
|
||||
if (codecValue) {
|
||||
metadataDetails.push({
|
||||
label: t('download.metadata.codec'),
|
||||
value: download.codec
|
||||
value: codecValue
|
||||
})
|
||||
}
|
||||
|
||||
@@ -508,7 +559,7 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
})
|
||||
}
|
||||
|
||||
if (download.selectedFormat.height && !qualityValue) {
|
||||
if (download.selectedFormat.height && !qualityLabel) {
|
||||
metadataDetails.push({
|
||||
label: t('download.metadata.height'),
|
||||
value: `${download.selectedFormat.height}px`
|
||||
@@ -639,11 +690,9 @@ export function DownloadItem({ download }: DownloadItemProps) {
|
||||
)}
|
||||
|
||||
{/* Quality badge */}
|
||||
{(download.selectedFormat?.height || download.quality) && (
|
||||
{qualityLabel && (
|
||||
<Badge variant="outline" className="text-[10px] px-1.5 py-0.5 shrink-0">
|
||||
{download.selectedFormat?.height
|
||||
? `${download.selectedFormat.height}p${download.selectedFormat.fps === 60 ? '60' : ''}`
|
||||
: download.quality}
|
||||
{qualityLabel}
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
|
||||
@@ -28,9 +28,6 @@ const toHistoryRecord = (item: DownloadHistoryItem): DownloadRecord => ({
|
||||
speed: undefined,
|
||||
duration: item.duration,
|
||||
fileSize: item.fileSize,
|
||||
format: item.format,
|
||||
quality: item.quality,
|
||||
codec: item.codec,
|
||||
createdAt: item.downloadedAt,
|
||||
startedAt: item.downloadedAt,
|
||||
completedAt: item.completedAt ?? item.downloadedAt,
|
||||
|
||||
@@ -62,9 +62,6 @@ export interface DownloadItem {
|
||||
// Enhanced video information
|
||||
duration?: number
|
||||
fileSize?: number
|
||||
format?: string
|
||||
quality?: string
|
||||
codec?: string
|
||||
savedFileName?: string
|
||||
// Timestamps
|
||||
createdAt: number
|
||||
@@ -78,7 +75,6 @@ export interface DownloadItem {
|
||||
tags?: string[]
|
||||
origin?: 'manual' | 'subscription'
|
||||
subscriptionId?: string
|
||||
subscriptionTitle?: string
|
||||
// Download-specific format info
|
||||
selectedFormat?: VideoFormat
|
||||
// Playlist context (optional)
|
||||
@@ -112,10 +108,6 @@ export interface DownloadHistoryItem {
|
||||
downloadedAt: number
|
||||
completedAt?: number
|
||||
error?: string
|
||||
// Enhanced video information
|
||||
format?: string
|
||||
quality?: string
|
||||
codec?: string
|
||||
// Additional metadata
|
||||
description?: string
|
||||
channel?: string
|
||||
@@ -124,7 +116,6 @@ export interface DownloadHistoryItem {
|
||||
tags?: string[]
|
||||
origin?: 'manual' | 'subscription'
|
||||
subscriptionId?: string
|
||||
subscriptionTitle?: string
|
||||
// Download-specific format info
|
||||
selectedFormat?: VideoFormat
|
||||
// Playlist context (optional)
|
||||
@@ -149,7 +140,6 @@ export interface DownloadOptions {
|
||||
tags?: string[]
|
||||
origin?: 'manual' | 'subscription'
|
||||
subscriptionId?: string
|
||||
subscriptionTitle?: string
|
||||
}
|
||||
|
||||
export interface PlaylistEntry {
|
||||
|
||||
Reference in New Issue
Block a user