fix(mobile): no false "Mark broken" while a video is still recovering

eporner/sxyprn/fpoxxx resolve phone-side; the native player errors on initial load, then
re-resolve swaps in a fresh URL ~1-3s later and plays fine — but the terminal error
overlay with "Mark broken" rendered during that gap (report dafa8cdb). Added a
recoveryPending flag (mirrors the telemetry's fallback-aware logic: re-resolve / in-place
seek recovery / proxy / webview still in flight) that shows a "Reconnecting…" spinner
instead, and only surfaces the terminal error + Mark broken when nothing is left to try.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
goon-foss 2026-07-01 10:37:19 +02:00
parent c029b7c687
commit 7cf338f812

View file

@ -698,6 +698,18 @@ function NativeVideoPlayer({ params }: { params: RouteParams }) {
? panSeekTarget ? panSeekTarget
: position; : position;
// Czy jest jeszcze JAKAKOLWIEK ścieżka ratunku w toku? Gdy tak — NIE pokazuj
// terminalnego błędu z „Mark broken", bo za chwilę zagra (report dafa8cdb: eporner/
// sxyprn/fpoxxx native pada na starcie, re-resolve podmienia URL ~1-3s później i gra;
// przez tę chwilę migało „Playback failed / Mark broken"). Lustro logiki telemetrii:
// re-resolve IP-bound, in-place seek-recovery, proxy albo WebView jeszcze nie próbowane.
const recoveryPending =
status === 'error' &&
((!!resolvePageUrl && !reResolveDone && !loadedOnceRef.current) ||
(loadedOnceRef.current && seekRecoveryRef.current < 2 && !isGoneError(playerError?.message)) ||
(!!fallbackProxyUrl && !didFallbackProxyRef.current && url !== fallbackProxyUrl) ||
(!!fallbackEmbedUrl && !didFallbackWebViewRef.current));
return ( return (
<View style={styles.root} onLayout={onLayout}> <View style={styles.root} onLayout={onLayout}>
{/* Hidden status bar — full-bleed video w landscape bez 24px paska systemu. */} {/* Hidden status bar — full-bleed video w landscape bez 24px paska systemu. */}
@ -817,7 +829,7 @@ function NativeVideoPlayer({ params }: { params: RouteParams }) {
<Text style={styles.overlayText}>{title ?? 'Loading…'}</Text> <Text style={styles.overlayText}>{title ?? 'Loading…'}</Text>
</View> </View>
)} )}
{status === 'error' && !fallbackEmbedUrl && ( {status === 'error' && !recoveryPending && (
<View style={styles.overlay}> <View style={styles.overlay}>
<Text style={styles.errorTitle}> <Text style={styles.errorTitle}>
{isGoneError(playerError?.message) ? 'Source no longer available' : 'Playback failed'} {isGoneError(playerError?.message) ? 'Source no longer available' : 'Playback failed'}
@ -839,10 +851,14 @@ function NativeVideoPlayer({ params }: { params: RouteParams }) {
</View> </View>
</View> </View>
)} )}
{status === 'error' && fallbackEmbedUrl && ( {recoveryPending && (
<View style={styles.overlay} pointerEvents="none"> <View style={styles.overlay} pointerEvents="none">
<ActivityIndicator color={theme.fg} size="large" /> <ActivityIndicator color={theme.fg} size="large" />
<Text style={styles.overlayText}>Native player failed switching to embed</Text> <Text style={styles.overlayText}>
{fallbackEmbedUrl && !didFallbackWebViewRef.current
? 'Native player failed — switching to embed…'
: 'Reconnecting…'}
</Text>
</View> </View>
)} )}
</View> </View>