From 7a6a58054a178ad4deed632c50fe77b9136c9af4 Mon Sep 17 00:00:00 2001 From: Andre <200930841+Andre-Bzk@users.noreply.github.com> Date: Wed, 13 May 2026 19:38:35 +0200 Subject: [PATCH] refactor: replace playback-initiated ref with conditional IPC subscription A mutable ref guarded AppShell's IPC listeners against events fired by ChannelScreen's playback session. The ref had to be set and cleared in five separate places, making the control flow hard to follow. The two contexts are already mutually exclusive at the UI level, so the guard is unnecessary. Subscribing only when no ChannelScreen is open expresses the same invariant through React's effect lifecycle instead. --- src/renderer/src/screens/AppShell.tsx | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/renderer/src/screens/AppShell.tsx b/src/renderer/src/screens/AppShell.tsx index c667b4c..ef59543 100644 --- a/src/renderer/src/screens/AppShell.tsx +++ b/src/renderer/src/screens/AppShell.tsx @@ -35,8 +35,6 @@ export default function AppShell({ onLogout }: Props): JSX.Element { const [livePlayState, setLivePlayState] = useState('idle') const [livePosition, setLivePosition] = useState(0) const liveVideoRef = useRef(null) - // Verhindert dass ChannelScreen-Events den globalen Overlay aktivieren - const isGlobalPlaybackInitiated = useRef(false) // Quality state für globalen Overlay const [liveAvailableQualities, setLiveAvailableQualities] = useState(undefined) const [liveCurrentQuality, setLiveCurrentQuality] = useState('best') @@ -46,19 +44,14 @@ export default function AppShell({ onLogout }: Props): JSX.Element { const isGlobalPlaying = livePlayState !== 'idle' - // IPC-Listener für globalen Playback (nur wenn kein ChannelScreen aktiv) + // IPC-Listener für globalen Playback — nur aktiv wenn kein ChannelScreen offen ist useEffect(() => { - const unsubHls = window.t4sd.playback.onHlsUrl((payload: HlsUrlPayload) => { - if (isGlobalPlaybackInitiated.current) { - setLiveHlsPayload(payload) - } - }) + if (selectedChannel) return + const unsubHls = window.t4sd.playback.onHlsUrl(setLiveHlsPayload) const unsubEvent = window.t4sd.playback.onEvent((ev) => { - if (!isGlobalPlaybackInitiated.current) return if (ev.kind === 'started') { setLivePlayState('playing') } else if (ev.kind === 'stopped') { - isGlobalPlaybackInitiated.current = false setLiveHlsPayload(null) setLivePlayState('idle') setLiveChannel(null) @@ -68,7 +61,6 @@ export default function AppShell({ onLogout }: Props): JSX.Element { setLiveQualityPanelOpen(false) setLiveErrorMsg('') } else if (ev.kind === 'error') { - isGlobalPlaybackInitiated.current = false setLiveHlsPayload(null) setLivePlayState('error') setLiveErrorMsg(ev.message ?? 'Stream konnte nicht gestartet werden.') @@ -77,7 +69,7 @@ export default function AppShell({ onLogout }: Props): JSX.Element { } }) return () => { unsubHls(); unsubEvent() } - }, []) + }, [!!selectedChannel]) const requestSidebar = useCallback(() => { const idx = SIDEBAR_ITEMS.findIndex((t) => t.key === tab) @@ -109,7 +101,6 @@ export default function AppShell({ onLogout }: Props): JSX.Element { // Direkt-Start: kein ChannelScreen — globaler Overlay startet sofort const handleStartLive = useCallback((ch: FollowedChannelInfo) => { - isGlobalPlaybackInitiated.current = true setLiveChannel(ch) setLivePlayState('starting') setLiveAvailableQualities(undefined) @@ -124,7 +115,6 @@ export default function AppShell({ onLogout }: Props): JSX.Element { }, []) const handleStopLive = useCallback(() => { - isGlobalPlaybackInitiated.current = false liveVideoRef.current?.stop() setLiveHlsPayload(null) setLivePlayState('idle') @@ -394,7 +384,6 @@ export default function AppShell({ onLogout }: Props): JSX.Element { onPaused={() => setLivePlayState('paused')} onEnded={handleStopLive} onError={() => { - isGlobalPlaybackInitiated.current = false setLiveHlsPayload(null) setLivePlayState('error') setLiveErrorMsg('Wiedergabefehler — Stream konnte nicht geladen werden.')