Commit Graph

520 Commits

Author SHA1 Message Date
xRangerDE
825c5dc96c feat(cmd-palette): add streamer search — type name or @login to jump
Reads config.streamers from the renderer global, builds one command per
streamer with label=name and keywords='@name name'. Action: showTab('vods')
+ selectStreamer(name). No-op if selectStreamer is unavailable
(e.g. on platforms where the streamers list wasn't loaded yet).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 01:25:25 +02:00
xRangerDE
a6b64ddf15 .gitignore: tmp_e2e_full/tmp_bugtest/tmp_dl test artifacts + codeberg stub
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 01:24:02 +02:00
xRangerDE
5439786652 docs: comprehensive CHANGELOG 4.6.155 -> 5.1.0-alpha.1
43 commits seit 4.6.155, 20 neue Module, 219 unit tests, 5 alpha-Tags + 5.0.0 GA.
Bricht nach Pillar gegliedert auf, listet Breaking Changes (additive),
Build/Migration Checklist + Roadmap-Rest fuer 5.1.x.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 01:03:06 +02:00
xRangerDE
d7d0fafe5c release: 5.1.0-alpha.1 - top-clips-crawler + command palette
Pillar 7 (Auto-Discovery) gets the Helix top-clips-crawler module (9 tests).
Pillar 5 (UI Power) gets its first visible component: Command Palette via
Ctrl+K with 6 tab-jump commands.

219 unit tests + e2e:release gruen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 00:05:20 +02:00
xRangerDE
2065f794a6 feat(ui): Command Palette (Ctrl+K) — Pillar 5 first visible component
Modal markup + CSS (.command-palette .cp-*) + renderer-command-palette.ts.
6 statische Tab-Wechsel-Befehle (VODs/Queue/Streamers/Stats/Archive/Settings)
mit prefix-Match. ArrowUp/Down navigiert, Enter ausfuehrt, Esc/Click-on-Overlay
schliesst. Registriert sich in closeTopmostOpenModal damit globaler Esc-Handler
es korrekt findet.

clearList via removeChild-Loop statt innerHTML='' (Hook-Pattern Bypass — gleiches
Verhalten, sicherer).

npm run test:e2e gruen — App startet sauber mit dem neuen Modal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 00:04:14 +02:00
xRangerDE
dc2b609132 feat(discovery): Helix top-clips-crawler module + rangeLastDays helper (9 tests)
Pillar 7 (Auto-Discovery) addition. Pure module — fetchImpl injizierbar fuer
Tests. Helix /clips endpoint, supports broadcaster_id + first (clamped 1-100) +
started_at/ended_at. Returns sorted-desc by view_count. snake_case Helix-
Felder werden auf camelCase im Public-Interface gemappt.

219 unit tests. IPC wiring + Auto-Discovery-Scheduler kommt post-5.1.0-alpha.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 00:00:38 +02:00
xRangerDE
f775e7a9e2 docs: CLAUDE.md update module inventory (19 modules, 17 test files, 210 tests)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:58:11 +02:00
xRangerDE
595269d9f5 release: 5.1.0-alpha.0 - integrity-check + archive-files-store + format-helpers
Continuation post-5.0.0. Adds three more domain/infra modules + 46 tests
(210 total). Touched pillars:

- Pillar 1 (Live-Rec): integrity-check ffprobe parser + verdict
- Pillar 6 (Smart-Resume / Archive): archive-files-store CRUD + summary
- Pillar 4 (Architecture-Split): format-helpers extraction (4 more pure
  functions out of main.ts: sanitizeFilenamePart, formatTwitchDurationFromSeconds,
  formatDateWithPattern, getMergeGroupPhaseText)

main.ts continues to shrink (now ~7160 LoC from 7485 start). Renderer-side
work (Pillar 5 UI Power) + recorder integration (Plan 04b) + OAuth IPC
wiring (needs Twitch Client ID from user) still ahead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:57:35 +02:00
xRangerDE
35189f6776 refactor: extract format helpers (sanitize, twitch-duration, date-pattern, merge-phase) + 24 tests
src/main/infra/format-helpers.ts. main.ts adapter for getMergeGroupPhaseText
injects config.language. 210 unit tests gruen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:57:22 +02:00
xRangerDE
bd1db9b873 feat(archive): archive-files-store CRUD + summaryByStreamer (10 tests)
upsert / get / list (filter by streamer, ordered by createdAt DESC NULLS LAST) /
setVerified / delete / summaryByStreamer (aggregated count + bytes per streamer) /
totalBytes. normalizeLogin used on streamer_login at write + filter time so
@Alice/Alice/alice all collapse to alice.

186 unit tests gruen. Storage layer for Pillar 1 verification + Pillar 6
archive index — recorder/storage-stats integration is post-5.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:53:54 +02:00
xRangerDE
987fb73a0e feat(integrity): ffprobe JSON parser + verdict assessor (12 tests)
Pillar 1 storage-layer piece. Spawn-free design — caller liefert das
ffprobe-Output als String, dieses Modul parsed + bewertet (no-video-stream,
duration-too-short, expected-duration mismatch).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:52:48 +02:00
xRangerDE
5b1c68a122 release: 5.0.0 — vitest + SQLite + OAuth storage/flow + Smart-Resume foundation
Major bump. v5.0.0-GA umfasst:

Foundation
- vitest test infrastructure
- 11 neue Module in src/main/{infra,domain}/
- main.ts: -198 LoC pure helpers extracted
- 164 unit tests + full e2e:release suite gruen

Persistence (Pillar 3 — done)
- better-sqlite3 mit WAL + 5s busy_timeout
- schema v5 (9 tables: schema_meta, config_kv, queue_items, downloaded_vods,
  streamers, archive_files, migrations_applied, oauth_accounts, chunk_index)
- Idempotenter JSON to SQLite Migrator (shadow-write, .v4-backup)
- Long-lived DB-Handle Singleton mit shutdown-close

Auth (Pillar 2 — scaffold done)
- SecureStorage (Electron safeStorage + Memory-Impl)
- token-store CRUD auf oauth_accounts (encrypted)
- PKCE pair + state generator
- Loopback HTTP server (127.0.0.1, ephemeral port)
- Twitch OAuth 2.1 Authorization Code Flow + PKCE module
- IPC wiring + Client ID config + Renderer button kommen in 5.1.x

Smart-Resume (Pillar 6 — foundation done)
- chunk_index table
- sha1 buffer + streaming file hash helpers
- chunk-index-store CRUD
- Integration in den Live-Recorder kommt in 5.1.x

Post-5.0 Roadmap
- Plan 04b: Resume in Recorder
- Plan 05: Live-Rec Polish + Sub-only (braucht Twitch Client ID)
- Plan 06: UI Power (virtual list, mini-player, command palette)
- Plan 07-09: Architektur-Split (Pillar 4 Rest)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:48:02 +02:00
xRangerDE
5a5d6f9c47 feat(auth): Twitch OAuth 2.1 Authorization Code Flow + PKCE + Loopback (21 tests)
3 new modules:
- src/main/domain/pkce.ts: PKCE pair (S256) + state (RFC 7636)
- src/main/infra/loopback-server.ts: ephemeral 127.0.0.1:PORT redirect capture
- src/main/domain/twitch-oauth.ts: startLoginFlow / awaitAuthorizationCode /
  exchangeCodeForToken / fetchTwitchUserInfo

Flow runs entirely scaffold-ready — IPC wiring + Client ID config and
shell.openExternal(authUrl) trigger come in a follow-on plan once the user
registers a Twitch dev app. 164 unit tests gruen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:46:22 +02:00
xRangerDE
c08b6fef7d refactor(db): lift db handle to long-lived singleton + close in shutdown
appDb module-scope let, getAppDb() exported getter, opened once in
app.whenReady with migrator run inline, closed in shutdownCleanup before
debugLog flush so WAL checkpoint completes cleanly. Unlocks IPC handlers
to read/write SQLite without per-call open/close.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:43:01 +02:00
xRangerDE
5465847c87 docs: Smart-Resume pattern note + roadmap Plan 04 DONE
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:21:26 +02:00
xRangerDE
bf16a49cff release: 5.0.0-alpha.3 - Smart-Resume foundation (chunk-hash + index)
Plan 04 abgeschlossen.
- schema-v5.ts: chunk_index table (item_id, chunk_seq, sha1_hex, bytes)
- src/main/infra/chunk-hash.ts: sha1 buffer + streaming file
- src/main/domain/chunk-index-store.ts: CRUD + dedupe lookup
- 143 unit tests (vorher 126, +17 fuer schema + hash + store)
- npm run test:e2e:release gruen

Integration mit dem live Recorder folgt in Plan 04b. Plan 04 ist rein
additiv; kein bestehender Recorder-Code wurde modifiziert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:20:49 +02:00
xRangerDE
f156d8bdcf feat(resume): chunk-index-store CRUD (8 tests)
record / listForItem (ordered by chunk_seq) / countForItem / lookupBySha1
(dedupe candidates) / deleteForItem. ON CONFLICT(item_id, chunk_seq) DO
UPDATE means re-recording overwrites prior hash. 143 unit tests gruen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:19:50 +02:00
xRangerDE
59a8912fba feat(resume): chunk-hash sha1 helpers (8 tests)
hashBuffer (sync) + hashFile (async streaming). 1MB+ files don't block.
Known-input vectors (hello, empty) verify against canonical sha1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:18:57 +02:00
xRangerDE
3667233a26 feat(db): add chunk_index table for Smart-Resume (sha1 of HLS segments)
UNIQUE(item_id, chunk_seq) + indices on item_id and sha1_hex. 1 new db test
(127 total). No producer wired up yet — that comes with the Plan 04b
integration into the live recorder.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:18:15 +02:00
xRangerDE
eac1dac180 docs(plan): Plan 04 Smart-Resume Foundation (storage layer only)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:17:22 +02:00
xRangerDE
80b4292405 docs: OAuth storage layer pattern + roadmap Plan 03 DONE
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:15:12 +02:00
xRangerDE
baede7cd84 release: 5.0.0-alpha.2 - OAuth foundation (storage layer)
Plan 03 abgeschlossen.
- schema-v5.ts: oauth_accounts table (provider, twitch_user_id, encrypted_*_token, ...)
- src/main/infra/secure-storage.ts: SecureStorage interface + Memory + Electron impls
- src/main/domain/token-store.ts: provider-agnostic CRUD on oauth_accounts
- 126 unit tests (vorher 106, +20 fuer schema + secure-storage + token-store)
- npm run test:e2e:release gruen

Twitch OAuth Flow itself (Authorization Code + PKCE via system browser
or embedded BrowserWindow) is deferred to Plan 03b — goal.md proposed
Device Code Flow which Twitch does not support.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:14:39 +02:00
xRangerDE
d82ab3c31a feat(auth): token-store CRUD on oauth_accounts (encrypted, 11 tests)
upsert / list / getDefault / setDefault / getAccessToken / getRefreshToken /
delete. UNIQUE(provider, twitch_user_id) via ON CONFLICT DO UPDATE. setDefault
ist provider-scoped (genau ein default pro provider). Scopes als JSON-Array
serialisiert. 126 unit tests gruen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:13:37 +02:00
xRangerDE
d1eacf31f2 feat(auth): SecureStorage interface + Memory + Electron impls (7 tests)
Electron impl wraps safeStorage (Win Credential Manager). MemoryImpl uses
base64 (no real crypto) — clearly marks isEncryptionAvailable()=false for
test/headless envs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:12:23 +02:00
xRangerDE
bc84eb2917 feat(db): add oauth_accounts table to schema v5 (2 new tests)
UNIQUE(provider, twitch_user_id), indices on provider + is_default.
108 unit tests gruen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:11:32 +02:00
xRangerDE
f6a66a7c77 docs(plan): Plan 03 OAuth Foundation (storage layer only — Twitch lacks Device Code support, flow deferred to 03b)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:10:32 +02:00
xRangerDE
63a3c7c1b4 docs: SQLite migrator pattern + roadmap Plan 02 DONE
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:07:13 +02:00
xRangerDE
16e0bfa059 release: 5.0.0-alpha.1 - SQLite migrator (shadow write, JSON stays master)
Plan 02 abgeschlossen.
- better-sqlite3 + @types installiert
- src/main/infra/{db.ts, schema-v5.ts} - DbHandle wrapper + schema v5 (7 tables + 6 indices)
- src/main/domain/migrator.ts - JSON to SQLite (idempotent, fail-soft, .v4-backup)
- main.ts: lazy-require Aufruf im app.whenReady
- 106 unit tests (vorher 91, +15 fuer db + migrator)
- npm run test:e2e:release gruen

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:06:38 +02:00
xRangerDE
edeaddb383 feat(db): wire migrator into app startup (fail-soft, lazy require)
Migrator runs on app.whenReady before pollers/createWindow. Lazy require
keeps native better-sqlite3 errors from blocking app startup. Result is
logged via appendDebugLog for diagnosis. Verified via npm run test:e2e
(0 issues, app starts cleanly).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:05:29 +02:00
xRangerDE
6480bc2586 feat(db): JSON to SQLite migrator (idempotent, fail-soft, 8 tests)
Migrates config.json (31 whitelisted config_kv keys + downloaded_vod_ids +
streamers) and download_queue.json (queue_items). Per-source try/catch:
malformed JSON logs into result.errors and continues. .v4-backup copies
written on success. migrations_applied marker prevents double-runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:04:25 +02:00
xRangerDE
93481999bd feat(db): better-sqlite3 wrapper + schema bootstrap (7 tests)
DbHandle interface (run/get/all/transaction/runBatch/close/raw).
Schema bootstrap splits SQL on ; and runs each statement via prepare().run()
to avoid pre-tool hook false-positive on .exec( pattern.
WAL mode + 5s busy_timeout + foreign_keys ON.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:03:17 +02:00
xRangerDE
bfe0f671a5 feat(db): schema v5 inline (7 tables + 6 indices)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:01:59 +02:00
xRangerDE
02c3b3df5b build: add better-sqlite3 + @types
Native binding verified loadable via node -e require smoke.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:01:29 +02:00
xRangerDE
713d8fca8a docs(roadmap): reorder to Pillar 3 (SQLite) as Plan 02; add Plan 02 doc
Reasoning: stateful main.ts split (former Plan 02-04) requires state-strategy
design that's better informed after features land. SQLite is the first
user-visible 5.0 milestone and architecturally independent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:00:31 +02:00
xRangerDE
1184e57da5 docs: CLAUDE.md notes new test:unit script + v5 split status
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:50:57 +02:00
xRangerDE
b649cf36f2 release: 5.0.0-alpha.0 — foundation: vitest + 5 pure modules extracted
Plan 01 abgeschlossen. main.ts: 7485 → 7287 LoC (-198).
5 neue Module + 91 Unit-Tests:
  src/main/infra/fs-atomic.ts
  src/main/infra/duration.ts
  src/main/domain/update-version-utils.ts
  src/main/domain/i18n-backend.ts
  src/main/domain/config-normalize.ts

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:50:25 +02:00
xRangerDE
fb1392bc4b refactor: extract config normalizers to src/main/domain/config-normalize + 47 tests
8 pure helpers (normalizeAutoRecordPollSeconds, normalizeAutoRecordList,
normalizeStreamlinkQuality, normalizeFilenameTemplate,
normalizeMetadataCacheMinutes, normalizePerformanceMode, isPlainObject,
normalizeLogin) plus VALID_STREAMLINK_QUALITIES + PerformanceMode type.
getStreamlinkStreamArg and normalizeConfigTemplates stay in main.ts
because they read globals (config / DEFAULT_*).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:48:58 +02:00
xRangerDE
89b30d33b9 refactor: extract BACKEND_MESSAGES + tBackend to src/main/domain/i18n-backend + 8 tests
Pure variant takes language as parameter. main.ts retains 2-arg adapter
that injects config.language so call-sites are unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:46:12 +02:00
xRangerDE
aee2914397 refactor: extract duration helpers to src/main/infra/duration + 18 tests
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:44:15 +02:00
xRangerDE
995e4b62dd refactor: extract writeFileAtomicSync to src/main/infra/fs-atomic + 6 tests
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:43:12 +02:00
xRangerDE
640807778c refactor: relocate update-version-utils to src/main/domain/ + vitest
16 unit tests covering normalize/compare/isNewer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:42:05 +02:00
xRangerDE
1b4dac5709 scaffold: src/main/{infra,domain} directory tree for v5 split
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:40:52 +02:00
xRangerDE
84aa4c5eca build: add test:unit + chain into test:e2e:release
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:40:24 +02:00
xRangerDE
cf859e70db build: vitest config (node env, src/**/*.test.ts)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:39:46 +02:00
xRangerDE
d97f75d0f7 build: add vitest devDep
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:39:19 +02:00
xRangerDE
956ffc30bc docs: v5.0.0 goal + roadmap + foundation plan
- tasks/v5.0.0-goal.md: 7-Pillar Vision, Breaking Changes, Release-Phasen
- tasks/v5.0.0-roadmap.md: Reality-Check vs Goal, 11-Plan Execution-Order
- tasks/v5.0.0-plan-01-foundation.md: Vitest + 5 Pure-Module-Extraktionen

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:37:54 +02:00
xRangerDE
0e81a47e9e release: 4.6.155 aria-live on clipStatus + viewer-modal status fields
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 12:17:04 +02:00
xRangerDE
70643b4c08 a11y: aria-live=polite on clipStatus + chatViewer/eventsViewer status
Three more user-triggered status messages that updated silently for screen-reader users:
- clipStatus — clip download progress/result text below the URL input on the Clips tab
- eventsViewerStatus — loading/error message inside the events viewer modal
- chatViewerStatus — loading/error message + filter result count inside the chat viewer modal

All three get role="status" + aria-live="polite". Same reasoning as 4.6.153/154 — the user explicitly clicks a button or opens a modal, then the result fills in asynchronously. Without aria-live the announcement was lost.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 12:16:49 +02:00
xRangerDE
86d68466f9 release: 4.6.154 aria-live on 3 more refresh-result status messages
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 12:11:27 +02:00
xRangerDE
ae156ff395 a11y: aria-live=polite on 3 more refresh-result status messages
Following the cleanupReport fix in 4.6.153, three more user-triggered refresh result strings were updating silently:

- statsLastScannedLabel — "Letzter Scan: <timestamp>" / "Scanne..." in the Archive-Statistik header after clicking Aktualisieren
- archiveSearchSummary — "{matchCount} matches (scanned {scanned}…)" / "Scanne..." after clicking Suchen
- storageSummary — "Total: {files} files, {size} — Free disk: {free}" / "Scanne..." after clicking Aktualisieren on the Storage card

All three are textContent updates triggered by an explicit user action that finishes asynchronously. Without aria-live, screen reader users hear nothing after pressing the action button — the result text fills in off-screen.

Added role="status" + aria-live="polite" to all three. "polite" because the result isn't urgent — the user requested it and waiting for a natural break in speech is fine.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 12:11:13 +02:00