Commit Graph

14 Commits

Author SHA1 Message Date
xRangerDE
092932d8d5 release: 4.5.27 disable-ads + queue context menu + cleanup
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 20:11:41 +02:00
xRangerDE
fdb096fa96 feat: streamlink quality preference + per-item notifications + path validation
Three Phase-11 wins.

1. Streamlink stream quality is now configurable. config.streamlink_quality
   defaults to "best" (preserves prior behaviour) but can be set to source,
   1080p60, 720p60, 720p, 480p, or audio_only via a new dropdown in
   Settings -> Download. The chosen quality is passed as STREAMS to
   streamlink with ",best" appended as a fallback so an old VOD lacking
   the chosen rendition still completes. Used by both the queue
   downloadVODPart and the standalone download-clip IPC. The whitelist is
   enforced via normalizeStreamlinkQuality so an arbitrary string in the
   config file falls back to "best".

2. Per-item completion notifications. Default off because long queues
   would spam the OS notifications panel. When enabled (Settings ->
   Queue zwischen App-Starts checkbox area), every successful download
   pops a "{title}" notification whose click brings the window forward
   AND opens shell.showItemInFolder on the produced file (or the
   download folder if the file is gone). The end-of-queue summary
   notification still fires regardless.

3. Download-path writability check on selectFolder. The renderer now
   asks the new check-folder-writable IPC after the user picks a
   folder; if isDownloadPathWritable returns false, a warning toast
   surfaces immediately instead of the next download failing with a
   cryptic "datei zu klein" / "ENOENT" error. Save proceeds anyway —
   the user might be picking a USB-stick path that is offline at the
   moment.

Plus DE + EN locale strings for every label/option/hint, all wired
through applyLanguageToStaticUI for live language switch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 20:00:36 +02:00
xRangerDE
6379723248 feat: taskbar progress + VOD card delegation + context menu + LRU bound
Four wins from a deep-audit pass.

1. Windows taskbar progress bar. While downloads run, mainWindow.
   setProgressBar(0..1) shows aggregate progress on the taskbar icon
   (visible while minimised). New activeDownloadProgress map tracks
   per-item fractions because main's downloadQueue.progress field
   is not updated mid-download (only renderer streams progress).
   Cleared via clearDownloadProgress in processOneQueueItem.finally
   so the bar resets when the queue idles.

2. VOD card data-* refactor. The previous inline-onclick template
   strings did escapedTitle = title.replace(/'/, "\\'").replace(/"/,
   "&quot;") and then interpolated that into onclick="addToQueue('...')".
   Edge cases (titles with backslash, &apos;, etc.) could break the
   JS parser. All identity now lives on data-vod-id / -url / -title /
   -date / -streamer / -duration on .vod-card. A delegated click
   listener on #vodGrid reads the dataset at click time and
   dispatches to openClipDialog / addToQueue / openExternal. Plus:
   clicking the thumbnail / title / meta now opens the VOD on Twitch
   in the OS default browser.

3. Right-click context menu on VOD cards. Items: "Open on Twitch",
   "Copy VOD URL" (uses navigator.clipboard, toast confirmation),
   "Trim VOD", "+ Queue", and toggle "Mark as downloaded" /
   "Unmark downloaded". The mark toggle hits a new
   ipcMain.handle("mark-vod-downloaded", id, mark) so a user can
   add or remove entries in config.downloaded_vod_ids manually
   without re-downloading. Menu auto-closes on outside-click /
   Escape / scroll. Repositioned to stay inside the viewport.

4. userIdLoginCache now bounded (insertion-order eviction at 4096).
   Was Map<string, string> with no cap; setUserIdLogin helper
   centralises insertion + eviction. Long-running sessions with
   thousands of unique streamer lookups no longer accumulate the
   reverse-lookup table forever.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 15:56:33 +02:00
xRangerDE
e2c0e3a2bf feat: hide-downloaded filter + reset list + config export/import
Three companion features around the 4.5.22 already-downloaded badge.

1. "Hide downloaded" toggle in the VOD filter row. Persisted to
   localStorage so power users who keep it on across sessions don't
   re-flip it on every launch. Filter applies before the title-search
   filter so the match counter stays consistent.

2. "Reset downloaded list" button in a new Backup & Maintenance
   settings card. Confirm-dialog before clearing, IPC returns the
   removed count for a "cleared N entries" toast. Renderer refreshes
   its config copy + re-renders the VOD grid so badges disappear
   immediately. No files are touched.

3. Config export / import via dialog.show*Dialog. Export strips
   client_secret (should never travel as plain text via cloud sync),
   tags the file with __exportVersion + __exportedAt. Import runs
   the JSON through normalizeConfigTemplates so out-of-range fields
   fall back to defaults; if the imported file lacks client_secret,
   the existing value is preserved. After import the renderer reloads
   config + relocalizes if language changed + re-renders streamers /
   settings form / VOD grid.

DE + EN locale strings for every label, button, toast, and confirm
dialog. New backupCardTitle / backupCardIntro section header in
Settings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 15:46:21 +02:00
xRangerDE
3f04b42b02 feat: auto-resume queue toggle + already-downloaded VOD indicator
Two real UX wins.

1. Auto-resume queue on startup. New checkbox in Settings -> Download
   ("Queue beim Start automatisch fortsetzen"). When enabled and the
   persisted queue has pending items, processQueue() fires ~5 seconds
   after did-finish-load — long enough for the user to see the queue
   and pause if they did not actually want this. Default off so the
   existing behaviour (explicit Start click) is preserved on upgrade.
   The Settings auto-save fingerprint includes the new flag and
   syncSettingsFormFromConfig restores it. Tooltip explains the
   timing on hover.

2. Already-downloaded indicator on VOD cards. Config gains
   downloaded_vod_ids: string[] (bounded to 4096 latest entries).
   Every successful queue-item download appends its parsed VOD ID
   (or every component ID for merge groups). On the VOD grid each
   card whose vod.id is in the set gets a small green checkmark
   badge in the top-right plus a slightly dimmed thumbnail, with a
   localized "Already downloaded" / "Bereits heruntergeladen"
   tooltip. The lookup builds a Set once per render so it stays
   O(1) per card. The renderer refreshes its local config copy on
   every "newly completed" queue update so the badge appears live
   without waiting for a settings save.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 15:16:21 +02:00
xRangerDE
3e1d4e188c feat: cutter/merge i18n + per-item retry + status-bar queue summary
Three Phase-6 wins.

1. Cutter & Merge tab labels were the same i18n gap as the trim-VOD
   dialog before 4.5.20: Dauer / Aufloesung / FPS / Auswahl / Start: /
   Ende: / Schneiden / Zusammenfuegen were hardcoded German in
   index.html. Each got an id + setText wiring + DE/EN locale strings
   (cutter.infoDuration / .infoResolution / .infoFps / .infoSelection
   / .startLabel / .endLabel; cutter.cut + merge.merge already existed
   for dynamic state, now also used as initial text on btnCut /
   btnMerge).

2. Per-item retry button on failed queue entries. The existing
   "retry failed" queue-action retried ALL failed items at once;
   when only one specific item should be retried (e.g. transient
   network blip on one URL), the user had to remove every other
   failed item first. New ipcMain.handle("retry-queue-item", id)
   resets that single item to status: pending and triggers
   processQueue if idle. A small ↻ icon now sits next to the
   remove (x) button on items in the error state.

3. Status bar queue summary. The footer previously showed only the
   connection status + version. With longer queues the user had to
   scroll the queue panel to see how many downloads were active
   versus pending. New span between the status indicator and the
   version reads "{downloading} dl, {pending} queued" (locale-aware,
   hidden when queue is empty). Updated on onQueueUpdated and
   onDownloadProgress so it stays live.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 14:02:42 +02:00
xRangerDE
16d2456770 feat: trim-VOD dialog i18n + Twitch API help link + log file shortcut
Three small UX wins.

1. Trim-VOD dialog: every inner label was hardcoded German in
   index.html (Start:, Ende:, Startzeit (HH:MM:SS):, Dauer:, Start
   Part-Nummer..., Leer lassen = Teil 1, Dateinamen-Format:, Zur
   Queue hinzufuegen). EN-mode users had a German dialog. Each
   element now has an id + setText wiring + DE/EN locale strings.

2. Settings -> Twitch API card now opens with a help line + link
   to dev.twitch.tv/console/apps. Uses window.api.openExternal so
   the link opens in the user's default browser instead of the
   Electron renderer (which has nodeIntegration off / no native
   navigation). Fixes the "no idea how to set this up" first-run
   friction.

3. Settings -> Live Debug Log gets an "Open log file" button next
   to Refresh. Uses a new ipcMain handle (open-debug-log-file ->
   shell.showItemInFolder on DEBUG_LOG_FILE) so users no longer
   have to navigate manually to ProgramData. As a small defensive
   bundle:
   - get-debug-log: lines parameter capped at [1, 5000] so a
     misbehaving renderer (or future feature) cannot ask main to
     slice millions of lines.
   - export-runtime-metrics: now uses writeFileAtomicSync (the
     fsync+rename helper from cycle 1) instead of plain
     writeFileSync so a power loss mid-export cannot leave a
     half-written metrics file at the user-chosen path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 13:33:10 +02:00
xRangerDE
933af6a6da feat: queue "Open file" / "Show in folder" + clickable finish notification
After a download completes there was no way to jump to the result
without manually navigating the download folder.

Server-side:
- DownloadResult and QueueItem gain optional outputFiles: string[]
  (single entry for VOD/clip, multi for parts/merge-group splits).
  Threaded through every downloadVOD / processDownloadMergeGroup
  branch into processOneQueueItem which attaches it to the queue
  item on success. Persisted via sanitizeQueueItem so the actions
  survive a queue file reload.
- New IPC handlers open-file (shell.openPath) and show-in-folder
  (shell.showItemInFolder), both with existence + type checks.
- The "downloads finished" Notification gets a click handler that
  brings the window to the foreground and opens the download folder.

Renderer-side:
- Expanded queue-item details now render an action row when
  status === completed and outputFiles is non-empty.
- "Open file" only shown when there is exactly one file (so multi-
  part downloads do not surprise the user by opening just part 1).
  "Show in folder" always shown.
- DE / EN locale strings + a graceful toast if the file was moved
  or deleted between completion and click.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 12:19:29 +02:00
xRangerDE
013e8be1f0 feat(clip): add Parts-format preset to Trim-Clip dialog
The Trim-Clip filename-format radio group only offered three presets
(simple, timestamp, custom template). Users who organise their archive
with the global filename_template_parts pattern (e.g.
08.05.2026_Part07.mp4) had to switch to "custom template" and retype
{date}_Part{part_padded}.mp4 every time.

New "parts" preset:
- index.html: 4th radio option, span#formatParts for the live preview
- types.ts + renderer-globals.d.ts: filenameFormat union extended
- main.ts: makeClipFilename branch produces ${dateStr}_Part${padded}.mp4;
  sanitizeCustomClip whitelists "parts" so persisted queue items with
  the new format survive a restart
- renderer.ts: getSelectedFilenameFormat returns "parts"; live preview
  via partNum.padStart(2, "0")
- DE/EN locales: clips.formatParts label

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 11:46:20 +02:00
xRangerDE
54d04d4f73 feat: support parallel downloads (up to 2 simultaneous)
Add parallel_downloads config option (1 or 2) with Settings UI dropdown.
Refactor processQueue to run concurrent download slots using Promise.race,
extracting per-item logic into processOneQueueItem. Add per-item process
tracking via activeDownloads Map and cancelledItemIds Set so cancel/pause
correctly terminates all active downloads.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 09:54:20 +01:00
xRangerDE
4750af2f97 feat(merge-split): add MergeGroup type definitions to all interface locations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:46:20 +01:00
xRangerDE
47df9664a4 release: 4.2.4 improve updater and queue persistence 2026-03-06 02:48:07 +01:00
xRangerDE
b7cd8fbec2 release: 4.2.3 improve updates and startup UX 2026-03-06 02:34:16 +01:00
xRangerDE
2631924ef5 chore: migrate repository to Codeberg, bump version to 4.2.0, update update logic 2026-03-01 20:23:21 +01:00