Compare commits

..

11 Commits

4 changed files with 26 additions and 38 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "vidbee",
"version": "1.0.0",
"version": "0.3.5",
"description": "A modern Electron application for downloading videos and audios",
"main": "./out/main/index.js",
"author": "VidBee",

View File

@@ -448,4 +448,4 @@
"internal": {
"indexes": {}
}
}
}

View File

@@ -27,42 +27,16 @@ import {
} from '../../store/downloads'
import { settingsAtom } from '../../store/settings'
const normalizeSavedFileName = (fileName?: string): string | undefined => {
if (!fileName) {
return undefined
}
const trimmed = fileName.trim()
if (!trimmed) {
return undefined
}
return trimmed.replace(/\.f\d+(?=\.[^.]+$)/i, '')
}
const generateFilePathCandidates = (
downloadPath: string,
title: string,
format: string,
savedFileName?: string
): string[] => {
const candidateFileNames = savedFileName
? [savedFileName]
: [`${title} via VidBee.${format}`, `${title}.${format}`]
const normalizedDownloadPath = downloadPath.replace(/\\/g, '/')
const safeTitle = title.trim() || 'Unknown'
const savedNameCandidates: string[] = []
const trimmedSavedFileName = savedFileName?.trim()
if (trimmedSavedFileName) {
const normalized = normalizeSavedFileName(trimmedSavedFileName)
if (normalized) {
savedNameCandidates.push(normalized)
}
if (!normalized || normalized !== trimmedSavedFileName) {
savedNameCandidates.push(trimmedSavedFileName)
}
}
const candidateFileNames =
savedNameCandidates.length > 0
? savedNameCandidates
: [`${safeTitle} via VidBee.${format}`, `${safeTitle}.${format}`]
return Array.from(
new Set(candidateFileNames.map((fileName) => `${normalizedDownloadPath}/${fileName}`))
)
@@ -82,10 +56,10 @@ const tryFileOperation = async (
}
const getSavedFileExtension = (fileName?: string): string | undefined => {
const normalized = normalizeSavedFileName(fileName)
if (!normalized) {
if (!fileName) {
return undefined
}
const normalized = fileName.trim()
if (!normalized.includes('.')) {
return undefined
}
@@ -208,7 +182,6 @@ export function DownloadItem({ download }: DownloadItemProps) {
? actionsContainerBaseClass
: `${actionsContainerBaseClass} sm:opacity-0 sm:group-hover:opacity-100`
const resolvedExtension = resolveDownloadExtension(download)
const normalizedSavedFileName = normalizeSavedFileName(download.savedFileName)
// Track if the file exists
const [fileExists, setFileExists] = useState(false)
@@ -479,10 +452,10 @@ export function DownloadItem({ download }: DownloadItemProps) {
})
}
if (normalizedSavedFileName || download.savedFileName) {
if (download.savedFileName) {
metadataDetails.push({
label: t('download.metadata.savedFile'),
value: normalizedSavedFileName ?? download.savedFileName
value: download.savedFileName
})
}

View File

@@ -1,3 +1,4 @@
import { Badge } from '@renderer/components/ui/badge'
import { Button } from '@renderer/components/ui/button'
import {
Dialog,
@@ -13,7 +14,7 @@ import { Switch } from '@renderer/components/ui/switch'
import { ipcServices } from '@renderer/lib/ipc'
import { settingsAtom } from '@renderer/store/settings'
import { resolveFeedAtom } from '@renderer/store/subscriptions'
import type { SubscriptionRule } from '@shared/types'
import type { SubscriptionResolvedFeed, SubscriptionRule } from '@shared/types'
import { useAtom, useSetAtom } from 'jotai'
import { ChevronRight } from 'lucide-react'
import { useEffect, useId, useRef, useState } from 'react'
@@ -66,6 +67,7 @@ export function SubscriptionFormDialog({
const [namingTemplate, setNamingTemplate] = useState('')
// Feed detection state
const [detectedFeed, setDetectedFeed] = useState<SubscriptionResolvedFeed | null>(null)
const [detectingFeed, setDetectingFeed] = useState(false)
const detectTimeout = useRef<NodeJS.Timeout | null>(null)
@@ -94,6 +96,7 @@ export function SubscriptionFormDialog({
setDownloadDirectory(settings.downloadPath)
setNamingTemplate(settings.subscriptionFilenameTemplate)
}
setDetectedFeed(null)
}, [
open,
mode,
@@ -134,11 +137,13 @@ export function SubscriptionFormDialog({
// Feed detection logic
useEffect(() => {
if (!url.trim()) {
setDetectedFeed(null)
return
}
// In edit mode, don't detect if URL hasn't changed
if (mode === 'edit' && subscription && url.trim() === subscription.feedUrl) {
setDetectedFeed(null)
return
}
@@ -149,9 +154,11 @@ export function SubscriptionFormDialog({
detectTimeout.current = setTimeout(async () => {
setDetectingFeed(true)
try {
await resolveFeed(url.trim())
const result = await resolveFeed(url.trim())
setDetectedFeed(result)
} catch (error) {
console.error('Failed to resolve feed:', error)
setDetectedFeed(null)
} finally {
setDetectingFeed(false)
}
@@ -245,6 +252,14 @@ export function SubscriptionFormDialog({
placeholder={t('subscriptions.placeholders.url')}
onChange={(event) => setUrl(event.target.value)}
/>
{detectedFeed && (
<Badge variant="outline" className="w-fit text-xs">
{t('subscriptions.detectedFeed', {
platform: detectedFeed.platform,
feed: detectedFeed.feedUrl
})}
</Badge>
)}
{detectingFeed && (
<p className="text-xs text-muted-foreground">{t('subscriptions.detecting')}</p>
)}