fix(player): hide ad-heavy WebView behind opaque cover until stream scraped
User bug: opening a WebView-fallback scene (yespornvip etc.) shows the host's ad-heavy page while INJECTED_JS auto-plays + scrapes the stream url in the background. User sees ads instead of a loading state. Render an opaque cover (theme.bg + spinner "Loading video…") over the WebView while !extractedUrl. The WebView is still laid out and painted underneath, so media keeps playing (autoplay via mediaPlaybackRequiresUserAction=false) and the performance-scan picks up the CDN url — but the user only ever sees a loading screen, then the native player. Applies to every WebView-fallback host. Safety: if no stream is scraped within 15s (host needs a real tap to start), reveal the WebView so the user can interact manually — no worse than before. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bb4a17ae79
commit
00ea8c3fd4
1 changed files with 31 additions and 0 deletions
|
|
@ -988,6 +988,17 @@ function EmbedWebViewPlayer({ params }: { params: RouteParams }) {
|
|||
const [resolveError, setResolveError] = React.useState<string | null>(null);
|
||||
const [skipResolve, setSkipResolve] = React.useState(false);
|
||||
const [resolveAttempted, setResolveAttempted] = React.useState(false);
|
||||
// Anti-ads: trzymamy nieprzezroczysty cover NA WebView dopóki INJECTED_JS nie
|
||||
// wyciągnie URL — user nie widzi ad-heavy strony hostera (bug yespornvip "otwiera
|
||||
// reklamy" 2026-05-31). WebView gra pod spodem (jest malowany, media leci, scrape
|
||||
// łapie CDN). Jeśli po REVEAL_AFTER_MS autoplay nie zaskoczył (host wymaga gestu) —
|
||||
// odsłaniamy WebView żeby user mógł ręcznie tapnąć play (graceful fallback).
|
||||
const [revealEmbed, setRevealEmbed] = React.useState(false);
|
||||
React.useEffect(() => {
|
||||
if (extractedUrl) return;
|
||||
const t = setTimeout(() => setRevealEmbed(true), 15000);
|
||||
return () => clearTimeout(t);
|
||||
}, [extractedUrl]);
|
||||
|
||||
// Stage 0.8: mobile-side hoster resolvery. Mobile IP usera unika Cloudflare
|
||||
// Turnstile / CAPTCHA gate który blokuje Hetzner VPS — embed page renderuje
|
||||
|
|
@ -1206,6 +1217,12 @@ function EmbedWebViewPlayer({ params }: { params: RouteParams }) {
|
|||
</View>
|
||||
)}
|
||||
/>
|
||||
{!extractedUrl && !revealEmbed && (
|
||||
<View style={styles.coverOverlay}>
|
||||
<ActivityIndicator color={theme.fg} size="large" />
|
||||
<Text style={styles.overlayText}>Loading video…</Text>
|
||||
</View>
|
||||
)}
|
||||
{extractedUrl && (
|
||||
<Pressable
|
||||
style={styles.extractBanner}
|
||||
|
|
@ -1241,6 +1258,20 @@ const styles = StyleSheet.create({
|
|||
backgroundColor: 'rgba(0,0,0,0.6)',
|
||||
paddingHorizontal: 32,
|
||||
},
|
||||
// Nieprzezroczysty cover na WebView — ukrywa ad-heavy stronę hostera podczas gdy
|
||||
// INJECTED_JS auto-play + scrape działają pod spodem. Solidne tło (nie alpha) =
|
||||
// zero podglądu reklam.
|
||||
coverOverlay: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: theme.bg,
|
||||
paddingHorizontal: 32,
|
||||
},
|
||||
overlayText: { color: theme.fg, marginTop: 12, fontSize: 13, textAlign: 'center' },
|
||||
errorTitle: { color: theme.bad, fontSize: 18, fontWeight: '700', marginBottom: 8 },
|
||||
errorBody: { color: theme.fg, fontSize: 14, marginBottom: 16, textAlign: 'center' },
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue