refactor: remove duplicate VOD start and chapter panel helpers

handleWatchVodFromChapter was identical to handleWatchVod except for an
optional startSeconds argument that the bridge already supports. Merged
into a single function with startSeconds?: number.

openChapterPanel was a wrapper around showChapterPanel whose two branches
both executed the same code. Removed the wrapper; call sites now call
showChapterPanel directly.

Also removes stale mpv references from CLAUDE.md that were superseded by
the hls.js migration commit.
This commit is contained in:
Andre
2026-05-12 20:34:05 +02:00
parent 1fe2093ebe
commit 4fa308b9e6
2 changed files with 7 additions and 57 deletions
+2 -5
View File
@@ -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. 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 ## 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/<kanal>) test-playback-pipeline.mjs — Standalone-Test: streamlink → HLS-URL → Manifest → Segment (node scripts/test-playback-pipeline.mjs twitch.tv/<kanal>)
flatpak/ 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) build-flatpak.sh — 6-Schritt Build-Pipeline (WSL2)
twitch4steamdeck.sh — Launcher mit zypak-wrapper twitch4steamdeck.sh — Launcher mit zypak-wrapper
tv.twitch4steamdeck.App.desktop 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 | | 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. | | 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. | | 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. | | Flaggen-Emojis auf Windows | Nur Rechtecke | Unicode Regional Indicators brauchen Noto Color Emoji (Linux). Im Dev-Mode ignorieren. |
+5 -52
View File
@@ -157,7 +157,7 @@ export default function ChannelScreen({ channel, onBack }: Props): JSX.Element {
setFocusRegion('hero') setFocusRegion('hero')
} else { } else {
if (chapter) { if (chapter) {
void handleWatchVodFromChapter(vod, chapter.positionSeconds) void handleWatchVod(vod, chapter.positionSeconds)
} else { } else {
void handleWatchVod(vod) void handleWatchVod(vod)
setChapterPanelVod(null) setChapterPanelVod(null)
@@ -229,7 +229,7 @@ export default function ChannelScreen({ channel, onBack }: Props): JSX.Element {
case 'y': { case 'y': {
e.preventDefault() e.preventDefault()
const vod = currentVod ?? vods[shelfIndex] const vod = currentVod ?? vods[shelfIndex]
if (vod) openChapterPanel(vod, true) if (vod) showChapterPanel(vod)
break break
} }
case 'x': case 'x':
@@ -273,7 +273,7 @@ export default function ChannelScreen({ channel, onBack }: Props): JSX.Element {
if (e.key === 'y') { if (e.key === 'y') {
e.preventDefault() e.preventDefault()
const vod = vods[shelfIndex] const vod = vods[shelfIndex]
if (vod) openChapterPanel(vod, false) if (vod) showChapterPanel(vod)
} else if (e.key === 'ArrowLeft') { } else if (e.key === 'ArrowLeft') {
e.preventDefault() e.preventDefault()
setShelfIndex((i) => Math.max(0, i - 1)) setShelfIndex((i) => Math.max(0, i - 1))
@@ -413,54 +413,7 @@ export default function ChannelScreen({ channel, onBack }: Props): JSX.Element {
.catch(() => setAvailableQualities([])) .catch(() => setAvailableQualities([]))
} }
const handleWatchVod = async (vod: VodInfo): Promise<void> => { const handleWatchVod = async (vod: VodInfo, startSeconds?: number): Promise<void> => {
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<void> => {
setPlayState('starting') setPlayState('starting')
setErrorMsg('') setErrorMsg('')
setFocusRegion('hero') setFocusRegion('hero')
@@ -815,7 +768,7 @@ export default function ChannelScreen({ channel, onBack }: Props): JSX.Element {
}} }}
onChangeQuality={(q) => void handleQualityChange(q)} onChangeQuality={(q) => void handleQualityChange(q)}
onOpenChapters={!isLivePlayback && currentVod onOpenChapters={!isLivePlayback && currentVod
? () => openChapterPanel(currentVod, true) ? () => showChapterPanel(currentVod)
: undefined} : undefined}
onTogglePause={() => { onTogglePause={() => {
if (playState === 'playing') { if (playState === 'playing') {