Compare commits

..

No commits in common. "37b793b9e8963a33ac2a4d3cf092d6ddfb85c73b" and "173ae61a3fe1bdc97e9a9becefb637df9f2660f6" have entirely different histories.

9 changed files with 10 additions and 27 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "twitch-vod-manager",
"version": "4.5.12",
"version": "4.5.11",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "twitch-vod-manager",
"version": "4.5.12",
"version": "4.5.11",
"license": "MIT",
"dependencies": {
"axios": "^1.6.0",

View File

@ -1,6 +1,6 @@
{
"name": "twitch-vod-manager",
"version": "4.5.12",
"version": "4.5.11",
"description": "Twitch VOD Manager - Download Twitch VODs easily",
"main": "dist/main.js",
"author": "xRangerDE",

View File

@ -106,11 +106,6 @@
style="width: 18px; height: 18px; accent-color: #9146FF;">
<span id="formatTimestamp" style="color: #aaa;">01.02.2026_CLIP_00-00-00_1.mp4 (mit Zeitstempel)</span>
</label>
<label style="display: flex; align-items: center; gap: 10px; cursor: pointer; margin-bottom: 8px;">
<input type="radio" name="filenameFormat" value="parts" onchange="updateFilenameExamples()"
style="width: 18px; height: 18px; accent-color: #9146FF;">
<span id="formatParts" style="color: #aaa;">01.02.2026_Part01.mp4 (Parts-Format)</span>
</label>
<label style="display: flex; align-items: center; gap: 10px; cursor: pointer; margin-bottom: 10px;">
<input type="radio" name="filenameFormat" value="template" onchange="updateFilenameExamples()"
style="width: 18px; height: 18px; accent-color: #9146FF;">

View File

@ -364,7 +364,7 @@ function sanitizeCustomClip(raw: unknown): CustomClip | undefined {
if (!Number.isFinite(startSec) || !Number.isFinite(durationSec) || durationSec <= 0 || !Number.isFinite(startPart)) return undefined;
const filenameFormat = raw.filenameFormat;
if (filenameFormat !== 'simple' && filenameFormat !== 'timestamp' && filenameFormat !== 'template' && filenameFormat !== 'parts') return undefined;
if (filenameFormat !== 'simple' && filenameFormat !== 'timestamp' && filenameFormat !== 'template') return undefined;
return {
startSec: Math.max(0, startSec),
@ -2666,15 +2666,9 @@ async function downloadVOD(
const s = Math.floor(startOffset % 60);
const timeStr = `${h.toString().padStart(2, '0')}-${m.toString().padStart(2, '0')}-${s.toString().padStart(2, '0')}`;
return path.join(folder, `${dateStr}_CLIP_${timeStr}_${partNum}.mp4`);
} else {
return path.join(folder, `${dateStr}_${partNum}.mp4`);
}
if (clip.filenameFormat === 'parts') {
// Mirrors the global filename_template_parts default:
// `{date}_Part{part_padded}.mp4` -> e.g. 08.05.2026_Part07.mp4
return path.join(folder, `${dateStr}_Part${partNum.toString().padStart(2, '0')}.mp4`);
}
return path.join(folder, `${dateStr}_${partNum}.mp4`);
};
// If clip is longer than part duration, split into parts

View File

@ -34,7 +34,7 @@ interface CustomClip {
startSec: number;
durationSec: number;
startPart: number;
filenameFormat: 'simple' | 'timestamp' | 'template' | 'parts';
filenameFormat: 'simple' | 'timestamp' | 'template';
filenameTemplate?: string;
}

View File

@ -189,7 +189,6 @@ const UI_TEXT_DE = {
unknownError: 'Unbekannter Fehler',
formatSimple: '(Standard)',
formatTimestamp: '(mit Zeitstempel)',
formatParts: '(Parts-Format)',
formatTemplate: '(benutzerdefiniert)',
templateEmpty: 'Das Template darf im benutzerdefinierten Modus nicht leer sein.',
templatePlaceholder: '{date}_{part}.mp4',

View File

@ -189,7 +189,6 @@ const UI_TEXT_EN = {
unknownError: 'Unknown error',
formatSimple: '(default)',
formatTimestamp: '(with timestamp)',
formatParts: '(parts naming)',
formatTemplate: '(custom template)',
templateEmpty: 'Template cannot be empty in custom template mode.',
templatePlaceholder: '{date}_{part}.mp4',

View File

@ -535,12 +535,9 @@ function formatSecondsWithPattern(totalSeconds: number, pattern: string): string
.replace(/\\(.)/g, '$1');
}
function getSelectedFilenameFormat(): 'simple' | 'timestamp' | 'template' | 'parts' {
function getSelectedFilenameFormat(): 'simple' | 'timestamp' | 'template' {
const selected = query<HTMLInputElement>('input[name="filenameFormat"]:checked').value;
if (selected === 'template') return 'template';
if (selected === 'timestamp') return 'timestamp';
if (selected === 'parts') return 'parts';
return 'simple';
return selected === 'template' ? 'template' : selected === 'timestamp' ? 'timestamp' : 'simple';
}
function updateFilenameTemplateVisibility(): void {
@ -898,7 +895,6 @@ function updateFilenameExamples(): void {
byId('formatSimple').textContent = `${dateStr}_${partNum}.mp4 ${UI_TEXT.clips.formatSimple}`;
byId('formatTimestamp').textContent = `${dateStr}_CLIP_${timeStr}_${partNum}.mp4 ${UI_TEXT.clips.formatTimestamp}`;
byId('formatParts').textContent = `${dateStr}_Part${partNum.padStart(2, '0')}.mp4 ${UI_TEXT.clips.formatParts}`;
byId('formatTemplate').textContent = `${buildTemplatePreview(template, {
title: clipDialogData.title,
date,

View File

@ -2,7 +2,7 @@ export interface CustomClip {
startSec: number;
durationSec: number;
startPart: number;
filenameFormat: 'simple' | 'timestamp' | 'template' | 'parts';
filenameFormat: 'simple' | 'timestamp' | 'template';
filenameTemplate?: string;
}