diff --git a/local-scrapers-repo b/local-scrapers-repo index f56983d1..e48fd1a2 160000 --- a/local-scrapers-repo +++ b/local-scrapers-repo @@ -1 +1 @@ -Subproject commit f56983d17df532f0342cf9bb9d11ae74f64637ff +Subproject commit e48fd1a255b90cac10cd60fdddab8410783434a1 diff --git a/src/components/player/AndroidVideoPlayer.tsx b/src/components/player/AndroidVideoPlayer.tsx index ebde55fd..1da20407 100644 --- a/src/components/player/AndroidVideoPlayer.tsx +++ b/src/components/player/AndroidVideoPlayer.tsx @@ -228,6 +228,20 @@ const AndroidVideoPlayer: React.FC = () => { // Check if we have a logo to show const hasLogo = metadata && metadata.logo && !metadataLoading; + // Prefetch backdrop and title logo for faster loading screen appearance + useEffect(() => { + if (backdrop && typeof backdrop === 'string') { + Image.prefetch(backdrop).catch(() => {}); + } + }, [backdrop]); + + useEffect(() => { + const logoUrl = (metadata && (metadata as any).logo) as string | undefined; + if (logoUrl && typeof logoUrl === 'string') { + Image.prefetch(logoUrl).catch(() => {}); + } + }, [metadata]); + // Resolve current episode description for series const currentEpisodeDescription = (() => { try { @@ -1827,6 +1841,7 @@ const AndroidVideoPlayer: React.FC = () => { {hasLogo ? ( + <> { }} /> + + {`Via ${(currentStreamProvider || streamProvider || '').toString().toUpperCase()}${(currentQuality || quality) ? ` • ${(currentQuality || quality)}p` : ''}`} + + ) : ( <> + + {`Via ${(currentStreamProvider || streamProvider || '').toString().toUpperCase()}${(currentQuality || quality) ? ` • ${(currentQuality || quality)}p` : ''}`} + )} diff --git a/src/components/player/VideoPlayer.tsx b/src/components/player/VideoPlayer.tsx index 90ef8c20..6eee480e 100644 --- a/src/components/player/VideoPlayer.tsx +++ b/src/components/player/VideoPlayer.tsx @@ -250,6 +250,20 @@ const VideoPlayer: React.FC = () => { // Check if we have a logo to show const hasLogo = metadata && metadata.logo && !metadataLoading; + + // Prefetch backdrop and title logo for faster loading screen appearance + useEffect(() => { + if (backdrop && typeof backdrop === 'string') { + Image.prefetch(backdrop).catch(() => {}); + } + }, [backdrop]); + + useEffect(() => { + const logoUrl = (metadata && (metadata as any).logo) as string | undefined; + if (logoUrl && typeof logoUrl === 'string') { + Image.prefetch(logoUrl).catch(() => {}); + } + }, [metadata]); // Resolve current episode description for series const currentEpisodeDescription = (() => { try { @@ -1738,6 +1752,7 @@ const VideoPlayer: React.FC = () => { {hasLogo ? ( + <> { }} /> + {/* Minimal provider/quality indicator under logo (not animated) */} + + {`Via ${(currentStreamProvider || streamProvider || '').toString().toUpperCase()}${(currentQuality || quality) ? ` • ${(currentQuality || quality)}p` : ''}`} + + ) : ( <> + {/* Minimal provider/quality indicator under spinner */} + + {`Via ${(currentStreamProvider || streamProvider || '').toString().toUpperCase()}${(currentQuality || quality) ? ` • ${(currentQuality || quality)}p` : ''}`} + )} diff --git a/src/screens/StreamsScreen.tsx b/src/screens/StreamsScreen.tsx index 751e1e6b..9e1e10d4 100644 --- a/src/screens/StreamsScreen.tsx +++ b/src/screens/StreamsScreen.tsx @@ -15,6 +15,7 @@ import { Dimensions, Linking, Clipboard, + Image as RNImage, } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; @@ -1344,6 +1345,20 @@ export const StreamsScreen = () => { return metadata?.poster || null; }, [currentEpisode, metadata, episodeThumbnail]); + // Prefetch hero/backdrop and title logo when StreamsScreen opens + useEffect(() => { + const urls: string[] = []; + if (episodeImage && typeof episodeImage === 'string') urls.push(episodeImage); + if (bannerImage && typeof bannerImage === 'string') urls.push(bannerImage); + if (metadata && (metadata as any).logo && typeof (metadata as any).logo === 'string') { + urls.push((metadata as any).logo as string); + } + // Deduplicate and prefetch + Array.from(new Set(urls)).forEach(u => { + RNImage.prefetch(u).catch(() => {}); + }); + }, [episodeImage, bannerImage, metadata]); + const isLoading = type === 'series' ? loadingEpisodeStreams : loadingStreams; const streams = type === 'series' ? episodeStreams : groupedStreams;