diff --git a/CLAUDE.md b/CLAUDE.md index f137087..9049124 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -84,8 +84,6 @@ bash flatpak/build-flatpak.sh ``` Das Skript: prüft deps → npm-Build → Python-Deps generieren → Streamlink-Tarballs hashen → `flatpak-builder` → SCP zum Steam Deck. -> **Hinweis:** Das Flatpak-Manifest (`flatpak/tv.twitch4steamdeck.App.yml`) enthält noch mpv als Dependency — muss bereinigt werden, sobald der hls.js-Ansatz auf dem Steam Deck getestet und bestätigt ist. - --- ## Codebase-Struktur @@ -154,11 +152,10 @@ scripts/ test-playback-pipeline.mjs — Standalone-Test: streamlink → HLS-URL → Manifest → Segment (node scripts/test-playback-pipeline.mjs twitch.tv/) flatpak/ - tv.twitch4steamdeck.App.yml — Flatpak-Manifest (Streamlink, alle Native-Deps; mpv-Einträge noch zu bereinigen) + tv.twitch4steamdeck.App.yml — Flatpak-Manifest (Streamlink, alle Native-Deps) build-flatpak.sh — 6-Schritt Build-Pipeline (WSL2) twitch4steamdeck.sh — Launcher mit zypak-wrapper tv.twitch4steamdeck.App.desktop - patches/mpv-ffmpeg7-avio-const.patch — (obsolet nach mpv-Entfernung) ``` --- @@ -259,7 +256,7 @@ Wenn der User während der Wiedergabe das Kapitel-Panel öffnet (Y-Taste), läuf | Problem | Status | Details | |---|---|---| -| hls.js Performance auf Steam Deck | Ungetestet | Chromiums VA-API Hardware-Decode sollte ausreichen. Falls Dropped Frames bei 1080p60 → Qualitäts-Button im Overlay nutzen (720p60 wählen) oder mpv-Fallback evaluieren. | +| hls.js Performance auf Steam Deck | Ungetestet | Chromiums VA-API Hardware-Decode sollte ausreichen. Falls Dropped Frames bei 1080p60 → Qualitäts-Button im Overlay nutzen (720p60 wählen). | | Twitch Live-Stream URL-Expiry | Unkritisch | `streamlink --stream-url` Token in URL kann ablaufen. hls.js handelt Playlist-Refresh automatisch; bei Verbindungsabbruch muss neu gestartet werden. | | Ad-Bypass | Nicht implementiert | `--twitch-disable-ads` von Streamlink deprecated. Post-MVP. | | Flaggen-Emojis auf Windows | Nur Rechtecke | Unicode Regional Indicators brauchen Noto Color Emoji (Linux). Im Dev-Mode ignorieren. | diff --git a/src/renderer/src/screens/ChannelScreen.tsx b/src/renderer/src/screens/ChannelScreen.tsx index 98d7498..9f8f0fc 100644 --- a/src/renderer/src/screens/ChannelScreen.tsx +++ b/src/renderer/src/screens/ChannelScreen.tsx @@ -157,7 +157,7 @@ export default function ChannelScreen({ channel, onBack }: Props): JSX.Element { setFocusRegion('hero') } else { if (chapter) { - void handleWatchVodFromChapter(vod, chapter.positionSeconds) + void handleWatchVod(vod, chapter.positionSeconds) } else { void handleWatchVod(vod) setChapterPanelVod(null) @@ -229,7 +229,7 @@ export default function ChannelScreen({ channel, onBack }: Props): JSX.Element { case 'y': { e.preventDefault() const vod = currentVod ?? vods[shelfIndex] - if (vod) openChapterPanel(vod, true) + if (vod) showChapterPanel(vod) break } case 'x': @@ -273,7 +273,7 @@ export default function ChannelScreen({ channel, onBack }: Props): JSX.Element { if (e.key === 'y') { e.preventDefault() const vod = vods[shelfIndex] - if (vod) openChapterPanel(vod, false) + if (vod) showChapterPanel(vod) } else if (e.key === 'ArrowLeft') { e.preventDefault() setShelfIndex((i) => Math.max(0, i - 1)) @@ -413,54 +413,7 @@ export default function ChannelScreen({ channel, onBack }: Props): JSX.Element { .catch(() => setAvailableQualities([])) } - const handleWatchVod = async (vod: VodInfo): Promise => { - setPlayState('starting') - setErrorMsg('') - setFocusRegion('hero') - setChapterPanelVod(null) - setCurrentVod(vod) - setPendingChapterVod(null) - setVodChaptersLoaded(false) - setAvailableQualities(undefined) - setCurrentQuality('best') - setQualityPanelOpen(false) - void loadChapters(vod.id) - .then((loaded) => { setChapters(loaded); setVodChaptersLoaded(true) }) - .catch(() => { setVodChaptersLoaded(true) }) - try { - await window.t4sd.playback.startVod( - vod.id, - channel.broadcasterLogin, - vod.title, - vod.durationSeconds - ) - } catch (e) { - setPlayState('error') - setErrorMsg(String(e)) - return - } - window.t4sd.playback.getQualities(`twitch.tv/videos/${vod.id}`) - .then((qs) => setAvailableQualities(qs.length > 0 ? qs : [])) - .catch(() => setAvailableQualities([])) - } - - const openChapterPanel = (vod: VodInfo, duringPlayback: boolean): void => { - if (duringPlayback) { - setChapterPanelVod(vod) - setChapters([]) - setChapterIndex(0) - setChaptersLoading(true) - setFocusRegion('chapters') - void loadChapters(vod.id) - .then((loaded) => setChapters(loaded)) - .catch(() => {}) - .finally(() => setChaptersLoading(false)) - return - } - showChapterPanel(vod) - } - - const handleWatchVodFromChapter = async (vod: VodInfo, startSeconds: number): Promise => { + const handleWatchVod = async (vod: VodInfo, startSeconds?: number): Promise => { setPlayState('starting') setErrorMsg('') setFocusRegion('hero') @@ -815,7 +768,7 @@ export default function ChannelScreen({ channel, onBack }: Props): JSX.Element { }} onChangeQuality={(q) => void handleQualityChange(q)} onOpenChapters={!isLivePlayback && currentVod - ? () => openChapterPanel(currentVod, true) + ? () => showChapterPanel(currentVod) : undefined} onTogglePause={() => { if (playState === 'playing') {