mirror of
https://github.com/neosubhamoy/neodlp.git
synced 2025-12-19 01:32:57 +05:30
feat: added filename template option in settings
This commit is contained in:
@@ -87,6 +87,7 @@ export default function App({ children }: { children: React.ReactNode }) {
|
||||
const FORCE_INTERNET_PROTOCOL = useSettingsPageStatesStore(state => state.settings.force_internet_protocol);
|
||||
const USE_CUSTOM_COMMANDS = useSettingsPageStatesStore(state => state.settings.use_custom_commands);
|
||||
const CUSTOM_COMMANDS = useSettingsPageStatesStore(state => state.settings.custom_commands);
|
||||
const FILENAME_TEMPLATE = useSettingsPageStatesStore(state => state.settings.filename_template);
|
||||
|
||||
const isErrored = useDownloaderPageStatesStore((state) => state.isErrored);
|
||||
const isErrorExpected = useDownloaderPageStatesStore((state) => state.isErrorExpected);
|
||||
@@ -124,7 +125,7 @@ export default function App({ children }: { children: React.ReactNode }) {
|
||||
const fetchVideoMetadata = async (url: string, formatId?: string, playlistIndex?: string, selectedSubtitles?: string | null, resumeState?: DownloadState, downloadConfig?: DownloadConfiguration): Promise<RawVideoInfo | null> => {
|
||||
try {
|
||||
const args = [url, '--dump-single-json', '--no-warnings'];
|
||||
if (formatId) args.push('-f', formatId);
|
||||
if (formatId) args.push('--format', formatId);
|
||||
if (selectedSubtitles) args.push('--embed-subs', '--sub-lang', selectedSubtitles);
|
||||
if (playlistIndex) args.push('--playlist-items', playlistIndex);
|
||||
if (PREFER_VIDEO_OVER_PLAYLIST && !playlistIndex) args.push('--no-playlist');
|
||||
@@ -285,12 +286,12 @@ export default function App({ children }: { children: React.ReactNode }) {
|
||||
'--paths',
|
||||
`home:${downloadDirPath}`,
|
||||
'--output',
|
||||
`%(title)s_%(resolution|unknown)s[${downloadId}].%(ext)s`,
|
||||
`${FILENAME_TEMPLATE}[${downloadId}].%(ext)s`,
|
||||
'--windows-filenames',
|
||||
'--restrict-filenames',
|
||||
'--exec',
|
||||
'after_move:echo Finalpath: {}',
|
||||
'-f',
|
||||
'--format',
|
||||
selectedFormat,
|
||||
'--no-mtime',
|
||||
'--no-warnings',
|
||||
|
||||
@@ -72,6 +72,10 @@ const addCustomCommandSchema = z.object({
|
||||
args: z.string().min(1, { message: "Arguments are required" }),
|
||||
});
|
||||
|
||||
const filenameTemplateShcema = z.object({
|
||||
template: z.string().min(1, { message: "Filename Template is required" }),
|
||||
});
|
||||
|
||||
export default function SettingsPage() {
|
||||
const { setTheme } = useTheme();
|
||||
|
||||
@@ -118,6 +122,7 @@ export default function SettingsPage() {
|
||||
const forceInternetProtocol = useSettingsPageStatesStore(state => state.settings.force_internet_protocol);
|
||||
const useCustomCommands = useSettingsPageStatesStore(state => state.settings.use_custom_commands);
|
||||
const customCommands = useSettingsPageStatesStore(state => state.settings.custom_commands);
|
||||
const filenameTemplate = useSettingsPageStatesStore(state => state.settings.filename_template);
|
||||
|
||||
const websocketPort = useSettingsPageStatesStore(state => state.settings.websocket_port);
|
||||
const isChangingWebSocketPort = useSettingsPageStatesStore(state => state.isChangingWebSocketPort);
|
||||
@@ -297,6 +302,30 @@ export default function SettingsPage() {
|
||||
}
|
||||
}
|
||||
|
||||
const filenameTemplateForm = useForm<z.infer<typeof filenameTemplateShcema>>({
|
||||
resolver: zodResolver(filenameTemplateShcema),
|
||||
defaultValues: {
|
||||
template: filenameTemplate,
|
||||
},
|
||||
mode: "onChange",
|
||||
});
|
||||
const watchedFilenameTemplate = filenameTemplateForm.watch("template");
|
||||
const { errors: filenameTemplateFormErrors } = filenameTemplateForm.formState;
|
||||
|
||||
function handleFilenameTemplateSubmit(values: z.infer<typeof filenameTemplateShcema>) {
|
||||
try {
|
||||
saveSettingsKey('filename_template', values.template);
|
||||
toast.success("Filename Template updated", {
|
||||
description: `Filename Template changed to ${values.template}`,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error changing filename template:", error);
|
||||
toast.error("Failed to change filename template", {
|
||||
description: "An error occurred while trying to change the filename template. Please try again.",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
interface Config {
|
||||
port: number;
|
||||
}
|
||||
@@ -372,7 +401,14 @@ export default function SettingsPage() {
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={
|
||||
() => resetSettings()
|
||||
() => {
|
||||
resetSettings()
|
||||
proxyUrlForm.reset();
|
||||
rateLimitForm.reset();
|
||||
addCustomCommandForm.reset();
|
||||
filenameTemplateForm.reset();
|
||||
websocketPortForm.reset();
|
||||
}
|
||||
}>Reset</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
@@ -629,6 +665,36 @@ export default function SettingsPage() {
|
||||
</AlertDialog>
|
||||
</div>
|
||||
</div>
|
||||
<div className="filename-template">
|
||||
<h3 className="font-semibold">Filename Template</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Set the template for naming downloaded files (download id and file extension will be auto-appended at the end, changing template may cause paused downloads to re-start from begining)</p>
|
||||
<Form {...filenameTemplateForm}>
|
||||
<form onSubmit={filenameTemplateForm.handleSubmit(handleFilenameTemplateSubmit)} className="flex gap-4 w-full" autoComplete="off">
|
||||
<FormField
|
||||
control={filenameTemplateForm.control}
|
||||
name="template"
|
||||
render={({ field }) => (
|
||||
<FormItem className="w-full">
|
||||
<FormControl>
|
||||
<Input
|
||||
className="focus-visible:ring-0"
|
||||
placeholder="Enter filename template"
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={!watchedFilenameTemplate || watchedFilenameTemplate === filenameTemplate || Object.keys(filenameTemplateFormErrors).length > 0}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent key="formats" value="formats" className="flex flex-col gap-4 min-h-[350px]">
|
||||
<div className="video-format">
|
||||
|
||||
@@ -179,6 +179,7 @@ export const useSettingsPageStatesStore = create<SettingsPageStatesStore>((set)
|
||||
force_internet_protocol: 'ipv4',
|
||||
use_custom_commands: false,
|
||||
custom_commands: [],
|
||||
filename_template: '%(title)s_%(resolution|unknown)s',
|
||||
// extension settings
|
||||
websocket_port: 53511
|
||||
},
|
||||
@@ -239,6 +240,7 @@ export const useSettingsPageStatesStore = create<SettingsPageStatesStore>((set)
|
||||
force_internet_protocol: 'ipv4',
|
||||
use_custom_commands: false,
|
||||
custom_commands: [],
|
||||
filename_template: '%(title)s_%(resolution|unknown)s',
|
||||
// extension settings
|
||||
websocket_port: 53511
|
||||
},
|
||||
|
||||
@@ -43,6 +43,7 @@ export interface Settings {
|
||||
force_internet_protocol: string;
|
||||
use_custom_commands: boolean;
|
||||
custom_commands: CustomCommand[];
|
||||
filename_template: string;
|
||||
// extension settings
|
||||
websocket_port: number;
|
||||
}
|
||||
@@ -52,4 +53,4 @@ export interface DownloadConfiguration {
|
||||
embed_metadata: boolean | null;
|
||||
embed_thumbnail: boolean | null;
|
||||
custom_command: string | null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user