From d55143e6fb93ce346c709d64f5d024b139ca71e5 Mon Sep 17 00:00:00 2001 From: tapframe Date: Thu, 16 Oct 2025 12:21:05 +0530 Subject: [PATCH 01/17] changes --- src/components/player/AndroidVideoPlayer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/player/AndroidVideoPlayer.tsx b/src/components/player/AndroidVideoPlayer.tsx index 0a89cdc7..2354da8e 100644 --- a/src/components/player/AndroidVideoPlayer.tsx +++ b/src/components/player/AndroidVideoPlayer.tsx @@ -86,7 +86,7 @@ const AndroidVideoPlayer: React.FC = () => { }, [route.params]); // TEMP: force React Native Video for testing (disable VLC) const TEMP_FORCE_RNV = false; - const TEMP_FORCE_VLC = true; + const TEMP_FORCE_VLC = false; const useVLC = Platform.OS === 'android' && !TEMP_FORCE_RNV && (TEMP_FORCE_VLC || forceVlc); // Log player selection @@ -1614,7 +1614,7 @@ const AndroidVideoPlayer: React.FC = () => { resizeModes = ['contain', 'cover']; } else { // On Android with VLC backend, only 'none' (original) and 'cover' (client-side crop) - resizeModes = useVLC ? ['none', 'cover'] : ['contain', 'cover', 'none']; + resizeModes = useVLC ? ['none', 'cover'] : ['cover', 'none']; } const currentIndex = resizeModes.indexOf(resizeMode); From e435a68aea783acf9ef9fdc0c48b7077b9b00d20 Mon Sep 17 00:00:00 2001 From: tapframe Date: Fri, 17 Oct 2025 15:00:36 +0530 Subject: [PATCH 02/17] UI changes --- enginefs | 1 + src/navigation/AppNavigator.tsx | 9 ++-- src/screens/StreamsScreen.tsx | 12 +---- src/services/trailerService.ts | 89 +++++++++++++++++++++++++++------ 4 files changed, 83 insertions(+), 28 deletions(-) create mode 160000 enginefs diff --git a/enginefs b/enginefs new file mode 160000 index 00000000..3a70b36f --- /dev/null +++ b/enginefs @@ -0,0 +1 @@ +Subproject commit 3a70b36f873307cd83fb3178bb891f73cf73aa87 diff --git a/src/navigation/AppNavigator.tsx b/src/navigation/AppNavigator.tsx index 32219897..c8057995 100644 --- a/src/navigation/AppNavigator.tsx +++ b/src/navigation/AppNavigator.tsx @@ -672,7 +672,7 @@ const MainTabs = () => { bottom: 0, left: 0, right: 0, - height: 85, + height: 85 + insets.bottom, backgroundColor: 'transparent', overflow: 'hidden', }}> @@ -722,7 +722,7 @@ const MainTabs = () => { { // Dynamically require to avoid impacting Android bundle const { createNativeBottomTabNavigator } = require('@bottom-tabs/react-navigation'); const IOSTab = createNativeBottomTabNavigator(); + const downloadsEnabled = appSettings?.enableDownloads !== false; return ( @@ -828,6 +829,8 @@ const MainTabs = () => { backgroundColor="transparent" /> { tabBarIcon: () => ({ sfSymbol: 'magnifyingglass' }), }} /> - {appSettings?.enableDownloads !== false && ( + {downloadsEnabled && ( - onPress()} - activeOpacity={0.7} - > - - + {settings?.enableDownloads !== false && ( - The trailer URL or null if not found */ static async getTrailerUrl(title: string, year: number, tmdbId?: string, type?: 'movie' | 'tv'): Promise { + logger.info('TrailerService', `getTrailerUrl requested: title="${title}", year=${year}, tmdbId=${tmdbId || 'n/a'}, type=${type || 'n/a'}, useLocal=${this.USE_LOCAL_SERVER}`); if (this.USE_LOCAL_SERVER) { // Try local server first, fallback to XPrime if it fails const localResult = await this.getTrailerFromLocalServer(title, year, tmdbId, type); if (localResult) { + logger.info('TrailerService', 'Returning trailer URL from local server'); return localResult; } @@ -46,6 +54,7 @@ export class TrailerService { */ private static async getTrailerFromLocalServer(title: string, year: number, tmdbId?: string, type?: 'movie' | 'tv'): Promise { try { + const startTime = Date.now(); const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.TIMEOUT); @@ -65,6 +74,8 @@ export class TrailerService { } const url = `${this.AUTO_SEARCH_URL}?${params.toString()}`; + logger.info('TrailerService', `Local server request URL: ${url}`); + logger.info('TrailerService', `Local server timeout set to ${this.TIMEOUT}ms`); const response = await fetch(url, { method: 'GET', @@ -77,25 +88,55 @@ export class TrailerService { clearTimeout(timeoutId); + const elapsed = Date.now() - startTime; + const contentType = response.headers.get('content-type') || 'unknown'; + logger.info('TrailerService', `Local server response: status=${response.status} ok=${response.ok} content-type=${contentType} elapsedMs=${elapsed}`); + + // Read body as text first so we can log it even on non-200s + let rawText = ''; + try { + rawText = await response.text(); + if (rawText) { + const preview = rawText.length > 200 ? `${rawText.slice(0, 200)}...` : rawText; + logger.info('TrailerService', `Local server body preview: ${preview}`); + } else { + logger.info('TrailerService', 'Local server body is empty'); + } + } catch (e) { + const msg = e instanceof Error ? `${e.name}: ${e.message}` : String(e); + logger.warn('TrailerService', `Failed reading local server body text: ${msg}`); + } + if (!response.ok) { logger.warn('TrailerService', `Auto-search failed: ${response.status} ${response.statusText}`); return null; } - const data = await response.json(); + // Attempt to parse JSON from the raw text + let data: any = null; + try { + data = rawText ? JSON.parse(rawText) : null; + const keys = typeof data === 'object' && data !== null ? Object.keys(data).join(',') : typeof data; + logger.info('TrailerService', `Local server JSON parsed. Keys/Type: ${keys}`); + } catch (e) { + const msg = e instanceof Error ? `${e.name}: ${e.message}` : String(e); + logger.warn('TrailerService', `Failed to parse local server JSON: ${msg}`); + return null; + } if (!data.url || !this.isValidTrailerUrl(data.url)) { logger.warn('TrailerService', `Invalid trailer URL from auto-search: ${data.url}`); return null; } - logger.info('TrailerService', `Successfully found trailer: ${data.url.substring(0, 50)}...`); + logger.info('TrailerService', `Successfully found trailer: ${String(data.url).substring(0, 80)}...`); return data.url; } catch (error) { if (error instanceof Error && error.name === 'AbortError') { - logger.warn('TrailerService', 'Auto-search request timed out'); + logger.warn('TrailerService', `Auto-search request timed out after ${this.TIMEOUT}ms`); } else { - logger.error('TrailerService', 'Error in auto-search:', error); + const msg = error instanceof Error ? `${error.name}: ${error.message}` : String(error); + logger.error('TrailerService', `Error in auto-search: ${msg}`); } return null; // Return null to trigger XPrime fallback } @@ -115,6 +156,8 @@ export class TrailerService { const url = `${this.XPRIME_URL}?title=${encodeURIComponent(title)}&year=${year}`; logger.info('TrailerService', `Fetching trailer from XPrime for: ${title} (${year})`); + logger.info('TrailerService', `XPrime request URL: ${url}`); + logger.info('TrailerService', `XPrime timeout set to ${this.TIMEOUT}ms`); const response = await fetch(url, { method: 'GET', @@ -127,12 +170,14 @@ export class TrailerService { clearTimeout(timeoutId); + logger.info('TrailerService', `XPrime response: status=${response.status} ok=${response.ok}`); if (!response.ok) { logger.warn('TrailerService', `XPrime failed: ${response.status} ${response.statusText}`); return null; } const trailerUrl = await response.text(); + logger.info('TrailerService', `XPrime raw URL length: ${trailerUrl ? trailerUrl.length : 0}`); if (!trailerUrl || !this.isValidTrailerUrl(trailerUrl.trim())) { logger.warn('TrailerService', `Invalid trailer URL from XPrime: ${trailerUrl}`); @@ -145,9 +190,10 @@ export class TrailerService { return cleanUrl; } catch (error) { if (error instanceof Error && error.name === 'AbortError') { - logger.warn('TrailerService', 'XPrime request timed out'); + logger.warn('TrailerService', `XPrime request timed out after ${this.TIMEOUT}ms`); } else { - logger.error('TrailerService', 'Error fetching from XPrime:', error); + const msg = error instanceof Error ? `${error.name}: ${error.message}` : String(error); + logger.error('TrailerService', `Error fetching from XPrime: ${msg}`); } return null; } @@ -218,16 +264,21 @@ export class TrailerService { if (url.includes('M3U')) { // Try to get M3U without encryption first, then with encryption const baseUrl = url.split('?')[0]; - return `${baseUrl}?formats=M3U+none,M3U+appleHlsEncryption`; + const best = `${baseUrl}?formats=M3U+none,M3U+appleHlsEncryption`; + logger.info('TrailerService', `Optimized format URL from M3U: ${best.substring(0, 80)}...`); + return best; } // Fallback to MP4 if available if (url.includes('MPEG4')) { const baseUrl = url.split('?')[0]; - return `${baseUrl}?formats=MPEG4`; + const best = `${baseUrl}?formats=MPEG4`; + logger.info('TrailerService', `Optimized format URL from MPEG4: ${best.substring(0, 80)}...`); + return best; } } // Return the original URL if no format optimization is needed + logger.info('TrailerService', 'No format optimization applied'); return url; } @@ -238,7 +289,9 @@ export class TrailerService { * @returns Promise - True if trailer is available */ static async isTrailerAvailable(title: string, year: number): Promise { + logger.info('TrailerService', `Checking trailer availability for: ${title} (${year})`); const trailerUrl = await this.getTrailerUrl(title, year); + logger.info('TrailerService', `Trailer availability for ${title} (${year}): ${trailerUrl ? 'available' : 'not available'}`); return trailerUrl !== null; } @@ -249,9 +302,11 @@ export class TrailerService { * @returns Promise - Trailer data or null if not found */ static async getTrailerData(title: string, year: number): Promise { + logger.info('TrailerService', `getTrailerData for: ${title} (${year})`); const url = await this.getTrailerUrl(title, year); if (!url) { + logger.info('TrailerService', 'No trailer URL found for getTrailerData'); return null; } @@ -292,6 +347,7 @@ export class TrailerService { localServer: { status: 'online' | 'offline'; responseTime?: number }; xprimeServer: { status: 'online' | 'offline'; responseTime?: number }; }> { + logger.info('TrailerService', 'Testing servers (local and XPrime)'); const results: { localServer: { status: 'online' | 'offline'; responseTime?: number }; xprimeServer: { status: 'online' | 'offline'; responseTime?: number }; @@ -312,9 +368,11 @@ export class TrailerService { status: 'online', responseTime: Date.now() - startTime }; + logger.info('TrailerService', `Local server online. Response time: ${results.localServer.responseTime}ms`); } } catch (error) { - logger.warn('TrailerService', 'Local server test failed:', error); + const msg = error instanceof Error ? `${error.name}: ${error.message}` : String(error); + logger.warn('TrailerService', `Local server test failed: ${msg}`); } // Test XPrime server @@ -329,11 +387,14 @@ export class TrailerService { status: 'online', responseTime: Date.now() - startTime }; + logger.info('TrailerService', `XPrime server online. Response time: ${results.xprimeServer.responseTime}ms`); } } catch (error) { - logger.warn('TrailerService', 'XPrime server test failed:', error); + const msg = error instanceof Error ? `${error.name}: ${error.message}` : String(error); + logger.warn('TrailerService', `XPrime server test failed: ${msg}`); } + logger.info('TrailerService', `Server test results -> local: ${results.localServer.status}, xprime: ${results.xprimeServer.status}`); return results; } } From e9d54bf0d6937798dfe2fcef600d1d80f0501d96 Mon Sep 17 00:00:00 2001 From: tapframe Date: Fri, 17 Oct 2025 20:18:34 +0530 Subject: [PATCH 03/17] trailer section init --- TrailerService | 1 + src/components/metadata/TrailerModal.tsx | 352 ++++++++++++++ src/components/metadata/TrailersSection.tsx | 485 ++++++++++++++++++++ src/screens/MetadataScreen.tsx | 11 + src/services/trailerService.ts | 59 +++ 5 files changed, 908 insertions(+) create mode 160000 TrailerService create mode 100644 src/components/metadata/TrailerModal.tsx create mode 100644 src/components/metadata/TrailersSection.tsx diff --git a/TrailerService b/TrailerService new file mode 160000 index 00000000..2cb2c6d1 --- /dev/null +++ b/TrailerService @@ -0,0 +1 @@ +Subproject commit 2cb2c6d1a3ca60416160bdb28be800fe249207fc diff --git a/src/components/metadata/TrailerModal.tsx b/src/components/metadata/TrailerModal.tsx new file mode 100644 index 00000000..c23f6a40 --- /dev/null +++ b/src/components/metadata/TrailerModal.tsx @@ -0,0 +1,352 @@ +import React, { useState, useEffect, useCallback, memo } from 'react'; +import { + View, + Text, + StyleSheet, + Modal, + TouchableOpacity, + ActivityIndicator, + Dimensions, + Platform, + Alert, +} from 'react-native'; +import { MaterialIcons } from '@expo/vector-icons'; +import { useTheme } from '../../contexts/ThemeContext'; +import { logger } from '../../utils/logger'; +import TrailerService from '../../services/trailerService'; +import TrailerPlayer from '../video/TrailerPlayer'; + +const { width, height } = Dimensions.get('window'); +const isTablet = width >= 768; + +interface TrailerVideo { + id: string; + key: string; + name: string; + site: string; + size: number; + type: string; + official: boolean; + published_at: string; +} + +interface TrailerModalProps { + visible: boolean; + onClose: () => void; + trailer: TrailerVideo | null; + contentTitle: string; +} + +const TrailerModal: React.FC = memo(({ + visible, + onClose, + trailer, + contentTitle +}) => { + const { currentTheme } = useTheme(); + const [trailerUrl, setTrailerUrl] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [isPlaying, setIsPlaying] = useState(false); + + // Load trailer when modal opens or trailer changes + useEffect(() => { + if (visible && trailer) { + loadTrailer(); + } else { + // Reset state when modal closes + setTrailerUrl(null); + setLoading(false); + setError(null); + setIsPlaying(false); + } + }, [visible, trailer]); + + const loadTrailer = useCallback(async () => { + if (!trailer) return; + + setLoading(true); + setError(null); + setTrailerUrl(null); + + try { + const youtubeUrl = `https://www.youtube.com/watch?v=${trailer.key}`; + + logger.info('TrailerModal', `Loading trailer: ${trailer.name} (${youtubeUrl})`); + + // Use the direct YouTube URL method - much more efficient! + const directUrl = await TrailerService.getTrailerFromYouTubeUrl( + youtubeUrl, + `${contentTitle} - ${trailer.name}`, + new Date(trailer.published_at).getFullYear().toString() + ); + + if (directUrl) { + setTrailerUrl(directUrl); + setIsPlaying(true); + logger.info('TrailerModal', `Successfully loaded direct trailer URL for: ${trailer.name}`); + } else { + throw new Error('No streaming URL available'); + } + } catch (err) { + const errorMessage = err instanceof Error ? err.message : 'Failed to load trailer'; + setError(errorMessage); + logger.error('TrailerModal', 'Error loading trailer:', err); + + Alert.alert( + 'Trailer Unavailable', + 'This trailer could not be loaded at this time. Please try again later.', + [{ text: 'OK', style: 'default' }] + ); + } finally { + setLoading(false); + } + }, [trailer, contentTitle]); + + const handleClose = useCallback(() => { + setIsPlaying(false); + onClose(); + }, [onClose]); + + const handleTrailerError = useCallback(() => { + setError('Failed to play trailer'); + setIsPlaying(false); + }, []); + + const handleTrailerEnd = useCallback(() => { + setIsPlaying(false); + }, []); + + if (!visible || !trailer) return null; + + const modalHeight = isTablet ? height * 0.8 : height * 0.7; + const modalWidth = isTablet ? width * 0.8 : width * 0.95; + + return ( + + + + {/* Header */} + + + + + {trailer.name} + + + + + + + + {/* Trailer Info */} + + + {trailer.type} • {new Date(trailer.published_at).getFullYear()} + {trailer.official && ' • Official'} + + + + {/* Player Container */} + + {loading && ( + + + + Loading trailer... + + + )} + + {error && !loading && ( + + + + {error} + + + Try Again + + + )} + + {trailerUrl && !loading && !error && ( + + logger.info('TrailerModal', 'Trailer loaded successfully')} + onError={handleTrailerError} + onEnd={handleTrailerEnd} + onPlaybackStatusUpdate={(status) => { + if (status.isLoaded && !isPlaying) { + setIsPlaying(true); + } + }} + /> + + )} + + + {/* Footer */} + + + {contentTitle} + + + + + + ); +}); + +const styles = StyleSheet.create({ + overlay: { + flex: 1, + backgroundColor: 'rgba(0,0,0,0.9)', + justifyContent: 'center', + alignItems: 'center', + }, + modal: { + borderRadius: 16, + overflow: 'hidden', + elevation: 10, + shadowColor: '#000', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.3, + shadowRadius: 8, + }, + header: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + paddingHorizontal: 20, + paddingVertical: 16, + borderBottomWidth: 1, + borderBottomColor: 'rgba(255,255,255,0.1)', + }, + titleContainer: { + flexDirection: 'row', + alignItems: 'center', + flex: 1, + gap: 8, + }, + title: { + fontSize: 16, + fontWeight: '600', + flex: 1, + }, + closeButton: { + padding: 4, + marginLeft: 8, + }, + infoContainer: { + paddingHorizontal: 20, + paddingVertical: 8, + }, + meta: { + fontSize: 12, + opacity: 0.8, + }, + playerContainer: { + aspectRatio: 16 / 9, + backgroundColor: '#000', + position: 'relative', + }, + loadingContainer: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#000', + gap: 16, + }, + loadingText: { + fontSize: 14, + opacity: 0.8, + }, + errorContainer: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#000', + padding: 20, + gap: 16, + }, + errorText: { + fontSize: 14, + textAlign: 'center', + opacity: 0.8, + }, + retryButton: { + paddingHorizontal: 20, + paddingVertical: 10, + borderRadius: 20, + }, + retryButtonText: { + color: '#fff', + fontSize: 14, + fontWeight: '600', + }, + playerWrapper: { + flex: 1, + }, + player: { + flex: 1, + }, + footer: { + paddingHorizontal: 20, + paddingVertical: 12, + borderTopWidth: 1, + borderTopColor: 'rgba(255,255,255,0.1)', + }, + footerText: { + fontSize: 12, + opacity: 0.6, + textAlign: 'center', + }, +}); + +export default TrailerModal; diff --git a/src/components/metadata/TrailersSection.tsx b/src/components/metadata/TrailersSection.tsx new file mode 100644 index 00000000..935db614 --- /dev/null +++ b/src/components/metadata/TrailersSection.tsx @@ -0,0 +1,485 @@ +import React, { useState, useEffect, memo } from 'react'; +import { + View, + Text, + StyleSheet, + TouchableOpacity, + ActivityIndicator, + Dimensions, + Alert, + Platform, +} from 'react-native'; +import { MaterialIcons } from '@expo/vector-icons'; +import FastImage from '@d11/react-native-fast-image'; +import { useTheme } from '../../contexts/ThemeContext'; +import { logger } from '../../utils/logger'; +import TrailerService from '../../services/trailerService'; +import TrailerModal from './TrailerModal'; + +const { width } = Dimensions.get('window'); +const isTablet = width >= 768; + +interface TrailerVideo { + id: string; + key: string; + name: string; + site: string; + size: number; + type: string; + official: boolean; + published_at: string; +} + +interface TrailersSectionProps { + tmdbId: number | null; + type: 'movie' | 'tv'; + contentId: string; + contentTitle: string; +} + +interface CategorizedTrailers { + [key: string]: TrailerVideo[]; +} + +const TrailersSection: React.FC = memo(({ + tmdbId, + type, + contentId, + contentTitle +}) => { + const { currentTheme } = useTheme(); + const [trailers, setTrailers] = useState({}); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [selectedTrailer, setSelectedTrailer] = useState(null); + const [modalVisible, setModalVisible] = useState(false); + + // Fetch trailers from TMDB + useEffect(() => { + if (!tmdbId) return; + + const fetchTrailers = async () => { + setLoading(true); + setError(null); + + try { + logger.info('TrailersSection', `Fetching trailers for TMDB ID: ${tmdbId}, type: ${type}`); + + // First check if the movie/TV show exists + const basicEndpoint = type === 'movie' + ? `https://api.themoviedb.org/3/movie/${tmdbId}?api_key=d131017ccc6e5462a81c9304d21476de` + : `https://api.themoviedb.org/3/tv/${tmdbId}?api_key=d131017ccc6e5462a81c9304d21476de`; + + const basicResponse = await fetch(basicEndpoint); + if (!basicResponse.ok) { + logger.error('TrailersSection', `TMDB ID ${tmdbId} not found: ${basicResponse.status}`); + setError(`Content not found (TMDB ID: ${tmdbId})`); + return; + } + + const videosEndpoint = type === 'movie' + ? `https://api.themoviedb.org/3/movie/${tmdbId}/videos?api_key=d131017ccc6e5462a81c9304d21476de&language=en-US` + : `https://api.themoviedb.org/3/tv/${tmdbId}/videos?api_key=d131017ccc6e5462a81c9304d21476de&language=en-US`; + + logger.info('TrailersSection', `Fetching videos from: ${videosEndpoint}`); + + const response = await fetch(videosEndpoint); + if (!response.ok) { + // 404 is normal - means no videos exist for this content + if (response.status === 404) { + logger.info('TrailersSection', `No videos found for TMDB ID ${tmdbId} (404 response)`); + setTrailers({}); // Empty trailers - section won't render + return; + } + logger.error('TrailersSection', `Videos endpoint failed: ${response.status} ${response.statusText}`); + throw new Error(`Failed to fetch trailers: ${response.status}`); + } + + const data = await response.json(); + logger.info('TrailersSection', `Received ${data.results?.length || 0} videos for TMDB ID ${tmdbId}`); + + const categorized = categorizeTrailers(data.results || []); + const totalVideos = Object.values(categorized).reduce((sum, videos) => sum + videos.length, 0); + + if (totalVideos === 0) { + logger.info('TrailersSection', `No videos found for TMDB ID ${tmdbId} - this is normal`); + setTrailers({}); // No trailers available + } else { + logger.info('TrailersSection', `Categorized ${totalVideos} videos into ${Object.keys(categorized).length} categories`); + setTrailers(categorized); + } + } catch (err) { + const errorMessage = err instanceof Error ? err.message : 'Failed to load trailers'; + setError(errorMessage); + logger.error('TrailersSection', 'Error fetching trailers:', err); + } finally { + setLoading(false); + } + }; + + fetchTrailers(); + }, [tmdbId, type]); + + // Categorize trailers by type + const categorizeTrailers = (videos: any[]): CategorizedTrailers => { + const categories: CategorizedTrailers = {}; + + videos.forEach(video => { + if (video.site !== 'YouTube') return; // Only YouTube videos + + const category = video.type; + if (!categories[category]) { + categories[category] = []; + } + categories[category].push(video); + }); + + // Sort within each category by published date (newest first) + Object.keys(categories).forEach(category => { + categories[category].sort((a, b) => + new Date(b.published_at).getTime() - new Date(a.published_at).getTime() + ); + }); + + return categories; + }; + + // Handle trailer selection + const handleTrailerPress = (trailer: TrailerVideo) => { + setSelectedTrailer(trailer); + setModalVisible(true); + }; + + // Handle modal close + const handleModalClose = () => { + setModalVisible(false); + setSelectedTrailer(null); + }; + + // Get thumbnail URL for YouTube video + const getYouTubeThumbnail = (videoId: string, quality: 'default' | 'hq' | 'maxres' = 'hq') => { + const qualities = { + default: `https://img.youtube.com/vi/${videoId}/default.jpg`, + hq: `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`, + maxres: `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg` + }; + return qualities[quality]; + }; + + // Format trailer type for display + const formatTrailerType = (type: string): string => { + switch (type) { + case 'Trailer': + return 'Official Trailers'; + case 'Teaser': + return 'Teasers'; + case 'Clip': + return 'Clips & Scenes'; + case 'Featurette': + return 'Featurettes'; + case 'Behind the Scenes': + return 'Behind the Scenes'; + default: + return type; + } + }; + + // Get icon for trailer type + const getTrailerTypeIcon = (type: string): string => { + switch (type) { + case 'Trailer': + return 'movie'; + case 'Teaser': + return 'videocam'; + case 'Clip': + return 'content-cut'; + case 'Featurette': + return 'featured-video'; + case 'Behind the Scenes': + return 'camera'; + default: + return 'play-circle-outline'; + } + }; + + if (!tmdbId) { + return null; // Don't show if no TMDB ID + } + + if (loading) { + return ( + + + + + Trailers + + + + + + Loading trailers... + + + + ); + } + + if (error) { + return ( + + + + + Trailers + + + + + + {error} + + + + ); + } + + const trailerCategories = Object.keys(trailers); + const totalVideos = Object.values(trailers).reduce((sum, videos) => sum + videos.length, 0); + + // Don't show section if no trailers (this is normal for many movies/TV shows) + if (trailerCategories.length === 0 || totalVideos === 0) { + // In development, show a subtle indicator that the section checked but found no trailers + if (__DEV__) { + return ( + + + + + Trailers + + + + + No trailers available + + + + ); + } + return null; + } + + return ( + + + + + Trailers + + + + {trailerCategories.map(category => ( + + + + + {formatTrailerType(category)} + + + {trailers[category].length} + + + + + {trailers[category].map(trailer => { + + return ( + handleTrailerPress(trailer)} + activeOpacity={0.8} + > + + + + + + + + {trailer.size}p + + + + + + + {trailer.name} + + + {new Date(trailer.published_at).getFullYear()} + {trailer.official && ' • Official'} + + + + ); + })} + + + ))} + + {/* Trailer Modal */} + + + ); +}); + +const styles = StyleSheet.create({ + container: { + paddingHorizontal: 16, + marginTop: 24, + marginBottom: 16, + }, + header: { + flexDirection: 'row', + alignItems: 'center', + marginBottom: 16, + gap: 8, + }, + headerTitle: { + fontSize: 18, + fontWeight: '700', + textTransform: 'uppercase', + letterSpacing: 1, + opacity: 0.9, + }, + loadingContainer: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + paddingVertical: 32, + gap: 12, + }, + loadingText: { + fontSize: 14, + opacity: 0.7, + }, + errorContainer: { + alignItems: 'center', + paddingVertical: 32, + gap: 8, + }, + errorText: { + fontSize: 14, + textAlign: 'center', + opacity: 0.7, + }, + categoryContainer: { + marginBottom: 24, + }, + categoryHeader: { + flexDirection: 'row', + alignItems: 'center', + marginBottom: 12, + gap: 8, + }, + categoryTitle: { + fontSize: 16, + fontWeight: '600', + flex: 1, + }, + categoryCount: { + fontSize: 12, + opacity: 0.6, + backgroundColor: 'rgba(255,255,255,0.1)', + paddingHorizontal: 8, + paddingVertical: 2, + borderRadius: 10, + }, + trailersGrid: { + flexDirection: 'row', + flexWrap: 'wrap', + gap: 12, + }, + trailerCard: { + width: isTablet ? (width - 32 - 24) / 3 : (width - 32 - 12) / 2, + backgroundColor: 'rgba(255,255,255,0.05)', + borderRadius: 12, + borderWidth: 1, + borderColor: 'rgba(255,255,255,0.1)', + overflow: 'hidden', + }, + thumbnailContainer: { + position: 'relative', + aspectRatio: 16 / 9, + }, + thumbnail: { + width: '100%', + height: '100%', + }, + playOverlay: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + backgroundColor: 'rgba(0,0,0,0.3)', + justifyContent: 'center', + alignItems: 'center', + }, + durationBadge: { + position: 'absolute', + bottom: 8, + right: 8, + backgroundColor: 'rgba(0,0,0,0.8)', + paddingHorizontal: 6, + paddingVertical: 2, + borderRadius: 4, + }, + durationText: { + color: '#fff', + fontSize: 10, + fontWeight: '600', + }, + trailerInfo: { + padding: 12, + }, + trailerTitle: { + fontSize: 13, + fontWeight: '600', + lineHeight: 16, + marginBottom: 4, + }, + trailerMeta: { + fontSize: 11, + opacity: 0.7, + }, + noTrailersContainer: { + alignItems: 'center', + paddingVertical: 16, + }, + noTrailersText: { + fontSize: 14, + opacity: 0.6, + fontStyle: 'italic', + }, +}); + +export default TrailersSection; diff --git a/src/screens/MetadataScreen.tsx b/src/screens/MetadataScreen.tsx index d37128ac..a922d8cf 100644 --- a/src/screens/MetadataScreen.tsx +++ b/src/screens/MetadataScreen.tsx @@ -26,6 +26,7 @@ import { MovieContent } from '../components/metadata/MovieContent'; import { MoreLikeThisSection } from '../components/metadata/MoreLikeThisSection'; import { RatingsSection } from '../components/metadata/RatingsSection'; import { CommentsSection, CommentBottomSheet } from '../components/metadata/CommentsSection'; +import TrailersSection from '../components/metadata/TrailersSection'; import { RouteParams, Episode } from '../types/metadata'; import Animated, { useAnimatedStyle, @@ -992,6 +993,16 @@ const MetadataScreen: React.FC = () => { )} + {/* Trailers Section - Lazy loaded */} + {shouldLoadSecondaryData && tmdbId && settings.enrichMetadataWithTMDB && ( + 0 ? 'tv' : 'movie'} + contentId={id} + contentTitle={metadata?.name || (metadata as any)?.title || 'Unknown'} + /> + )} + {/* Comments Section - Lazy loaded */} {shouldLoadSecondaryData && imdbId && ( - The direct streaming URL or null if failed + */ + static async getTrailerFromYouTubeUrl(youtubeUrl: string, title?: string, year?: string): Promise { + try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), this.TIMEOUT); + + const params = new URLSearchParams(); + params.append('youtube_url', youtubeUrl); + if (title) params.append('title', title); + if (year) params.append('year', year.toString()); + + const url = `${this.ENV_LOCAL_BASE}${this.ENV_LOCAL_TRAILER_PATH}?${params.toString()}`; + logger.info('TrailerService', `Fetching trailer directly from YouTube URL: ${youtubeUrl}`); + logger.info('TrailerService', `Direct trailer request URL: ${url}`); + + const response = await fetch(url, { + method: 'GET', + headers: { + 'Accept': 'application/json', + 'User-Agent': 'Nuvio/1.0', + }, + signal: controller.signal, + }); + + clearTimeout(timeoutId); + + logger.info('TrailerService', `Direct trailer response: status=${response.status} ok=${response.ok}`); + + if (!response.ok) { + logger.warn('TrailerService', `Direct trailer failed: ${response.status} ${response.statusText}`); + return null; + } + + const data = await response.json(); + + if (!data.url || !this.isValidTrailerUrl(data.url)) { + logger.warn('TrailerService', `Invalid trailer URL from direct fetch: ${data.url}`); + return null; + } + + logger.info('TrailerService', `Successfully got direct trailer: ${String(data.url).substring(0, 80)}...`); + return data.url; + } catch (error) { + if (error instanceof Error && error.name === 'AbortError') { + logger.warn('TrailerService', `Direct trailer request timed out after ${this.TIMEOUT}ms`); + } else { + const msg = error instanceof Error ? `${error.name}: ${error.message}` : String(error); + logger.error('TrailerService', `Error in direct trailer fetch: ${msg}`); + } + return null; + } + } + /** * Switch between local server and XPrime API * @param useLocal - true for local server, false for XPrime From 2303c329405642e0ca1c6cbb91fa7c845085f400 Mon Sep 17 00:00:00 2001 From: tapframe Date: Fri, 17 Oct 2025 20:32:46 +0530 Subject: [PATCH 04/17] ui changes --- src/components/metadata/TrailerModal.tsx | 175 ++++--- src/components/metadata/TrailersSection.tsx | 501 +++++++++++++++----- 2 files changed, 493 insertions(+), 183 deletions(-) diff --git a/src/components/metadata/TrailerModal.tsx b/src/components/metadata/TrailerModal.tsx index c23f6a40..46a07562 100644 --- a/src/components/metadata/TrailerModal.tsx +++ b/src/components/metadata/TrailerModal.tsx @@ -19,6 +19,24 @@ import TrailerPlayer from '../video/TrailerPlayer'; const { width, height } = Dimensions.get('window'); const isTablet = width >= 768; +// Helper function to format trailer type +const formatTrailerType = (type: string): string => { + switch (type) { + case 'Trailer': + return 'Official Trailer'; + case 'Teaser': + return 'Teaser'; + case 'Clip': + return 'Clip'; + case 'Featurette': + return 'Featurette'; + case 'Behind the Scenes': + return 'Behind the Scenes'; + default: + return type; + } +}; + interface TrailerVideo { id: string; key: string; @@ -136,42 +154,43 @@ const TrailerModal: React.FC = memo(({ maxHeight: modalHeight, backgroundColor: currentTheme.colors.background }]}> - {/* Header */} + {/* Enhanced Header */} - - - - {trailer.name} - + + + + + + + {trailer.name} + + + + {formatTrailerType(trailer.type)} • {new Date(trailer.published_at).getFullYear()} + + + - {/* Trailer Info */} - - - {trailer.type} • {new Date(trailer.published_at).getFullYear()} - {trailer.official && ' • Official'} - - - {/* Player Container */} {loading && ( @@ -223,11 +242,23 @@ const TrailerModal: React.FC = memo(({ )} - {/* Footer */} + {/* Enhanced Footer */} - - {contentTitle} - + + + + {contentTitle} + + + + + {trailer.size}p HD + + @@ -238,50 +269,70 @@ const TrailerModal: React.FC = memo(({ const styles = StyleSheet.create({ overlay: { flex: 1, - backgroundColor: 'rgba(0,0,0,0.9)', + backgroundColor: 'rgba(0,0,0,0.92)', justifyContent: 'center', alignItems: 'center', }, modal: { - borderRadius: 16, + borderRadius: 20, overflow: 'hidden', - elevation: 10, + elevation: 12, shadowColor: '#000', - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.3, - shadowRadius: 8, + shadowOffset: { width: 0, height: 6 }, + shadowOpacity: 0.4, + shadowRadius: 12, + borderWidth: 1, + borderColor: 'rgba(255,255,255,0.1)', }, + + // Enhanced Header Styles header: { flexDirection: 'row', - alignItems: 'center', + alignItems: 'flex-start', justifyContent: 'space-between', paddingHorizontal: 20, - paddingVertical: 16, + paddingVertical: 18, borderBottomWidth: 1, - borderBottomColor: 'rgba(255,255,255,0.1)', + borderBottomColor: 'rgba(255,255,255,0.08)', }, - titleContainer: { + headerLeft: { flexDirection: 'row', - alignItems: 'center', flex: 1, - gap: 8, + gap: 12, + }, + headerIconContainer: { + width: 36, + height: 36, + borderRadius: 10, + alignItems: 'center', + justifyContent: 'center', + }, + headerTextContainer: { + flex: 1, + gap: 4, }, title: { fontSize: 16, - fontWeight: '600', - flex: 1, + fontWeight: '700', + lineHeight: 20, + color: '#fff', }, - closeButton: { - padding: 4, - marginLeft: 8, - }, - infoContainer: { - paddingHorizontal: 20, - paddingVertical: 8, + headerMeta: { + flexDirection: 'row', + alignItems: 'center', + gap: 8, }, meta: { fontSize: 12, - opacity: 0.8, + opacity: 0.7, + fontWeight: '500', + }, + closeButton: { + width: 32, + height: 32, + borderRadius: 16, + alignItems: 'center', + justifyContent: 'center', }, playerContainer: { aspectRatio: 16 / 9, @@ -336,16 +387,34 @@ const styles = StyleSheet.create({ player: { flex: 1, }, + // Enhanced Footer Styles footer: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', paddingHorizontal: 20, - paddingVertical: 12, + paddingVertical: 16, borderTopWidth: 1, - borderTopColor: 'rgba(255,255,255,0.1)', + borderTopColor: 'rgba(255,255,255,0.08)', + }, + footerContent: { + flexDirection: 'row', + alignItems: 'center', + flex: 1, + gap: 6, }, footerText: { - fontSize: 12, + fontSize: 13, + fontWeight: '500', + opacity: 0.8, + }, + footerMeta: { + alignItems: 'flex-end', + }, + footerMetaText: { + fontSize: 11, opacity: 0.6, - textAlign: 'center', + fontWeight: '500', }, }); diff --git a/src/components/metadata/TrailersSection.tsx b/src/components/metadata/TrailersSection.tsx index 935db614..316301e1 100644 --- a/src/components/metadata/TrailersSection.tsx +++ b/src/components/metadata/TrailersSection.tsx @@ -8,6 +8,8 @@ import { Dimensions, Alert, Platform, + ScrollView, + Modal, } from 'react-native'; import { MaterialIcons } from '@expo/vector-icons'; import FastImage from '@d11/react-native-fast-image'; @@ -53,6 +55,8 @@ const TrailersSection: React.FC = memo(({ const [error, setError] = useState(null); const [selectedTrailer, setSelectedTrailer] = useState(null); const [modalVisible, setModalVisible] = useState(false); + const [selectedCategory, setSelectedCategory] = useState('Trailer'); + const [dropdownVisible, setDropdownVisible] = useState(false); // Fetch trailers from TMDB useEffect(() => { @@ -104,9 +108,16 @@ const TrailersSection: React.FC = memo(({ if (totalVideos === 0) { logger.info('TrailersSection', `No videos found for TMDB ID ${tmdbId} - this is normal`); setTrailers({}); // No trailers available + setSelectedCategory(''); // No category selected } else { logger.info('TrailersSection', `Categorized ${totalVideos} videos into ${Object.keys(categorized).length} categories`); setTrailers(categorized); + + // Auto-select the first available category, preferring "Trailer" + const availableCategories = Object.keys(categorized); + const preferredCategory = availableCategories.includes('Trailer') ? 'Trailer' : + availableCategories.includes('Teaser') ? 'Teaser' : availableCategories[0]; + setSelectedCategory(preferredCategory); } } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to load trailers'; @@ -156,6 +167,17 @@ const TrailersSection: React.FC = memo(({ setSelectedTrailer(null); }; + // Handle category selection + const handleCategorySelect = (category: string) => { + setSelectedCategory(category); + setDropdownVisible(false); + }; + + // Toggle dropdown + const toggleDropdown = () => { + setDropdownVisible(!dropdownVisible); + }; + // Get thumbnail URL for YouTube video const getYouTubeThumbnail = (videoId: string, quality: 'default' | 'hq' | 'maxres' = 'hq') => { const qualities = { @@ -272,73 +294,161 @@ const TrailersSection: React.FC = memo(({ return ( + {/* Enhanced Header with Category Selector */} - - Trailers + Trailers & Videos - - {trailerCategories.map(category => ( - - + {/* Category Selector - Right Aligned */} + {trailerCategories.length > 0 && selectedCategory && ( + + + {formatTrailerType(selectedCategory)} + - - {formatTrailerType(category)} - - - {trailers[category].length} - + + )} + + + {/* Category Dropdown Modal */} + setDropdownVisible(false)} + > + setDropdownVisible(false)} + > + + {trailerCategories.map(category => ( + handleCategorySelect(category)} + activeOpacity={0.7} + > + + + + + + {formatTrailerType(category)} + + + {trailers[category].length} + + + {selectedCategory === category && ( + + )} + + ))} + + - - {trailers[category].map(trailer => { - - return ( - handleTrailerPress(trailer)} - activeOpacity={0.8} - > - + {/* Selected Category Trailers */} + {selectedCategory && trailers[selectedCategory] && ( + + {/* Trailers Horizontal Scroll */} + + {trailers[selectedCategory].map((trailer, index) => ( + handleTrailerPress(trailer)} + activeOpacity={0.9} + > + {/* Thumbnail with Gradient Overlay */} + - - - - - + {/* Subtle Gradient Overlay */} + + {/* Quality Badge */} + + {trailer.size}p - - - {trailer.name} - - - {new Date(trailer.published_at).getFullYear()} - {trailer.official && ' • Official'} - - - - ); - })} - + {/* Trailer Info */} + + + {trailer.name} + + + {new Date(trailer.published_at).getFullYear()} + + + + ))} + {/* Scroll Indicator - shows when there are more items to scroll */} + {trailers[selectedCategory].length > (isTablet ? 4 : 3) && ( + + + + )} + - ))} + )} {/* Trailer Modal */} Date: Fri, 17 Oct 2025 20:35:48 +0530 Subject: [PATCH 05/17] rn video init for trailers --- src/components/metadata/TrailerModal.tsx | 45 +++++++++++++++++------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/components/metadata/TrailerModal.tsx b/src/components/metadata/TrailerModal.tsx index 46a07562..28764c2e 100644 --- a/src/components/metadata/TrailerModal.tsx +++ b/src/components/metadata/TrailerModal.tsx @@ -14,7 +14,7 @@ import { MaterialIcons } from '@expo/vector-icons'; import { useTheme } from '../../contexts/ThemeContext'; import { logger } from '../../utils/logger'; import TrailerService from '../../services/trailerService'; -import TrailerPlayer from '../video/TrailerPlayer'; +import Video, { VideoRef, OnLoadData, OnProgressData } from 'react-native-video'; const { width, height } = Dimensions.get('window'); const isTablet = width >= 768; @@ -62,6 +62,7 @@ const TrailerModal: React.FC = memo(({ contentTitle }) => { const { currentTheme } = useTheme(); + const videoRef = React.useRef(null); const [trailerUrl, setTrailerUrl] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); @@ -223,19 +224,37 @@ const TrailerModal: React.FC = memo(({ {trailerUrl && !loading && !error && ( - logger.info('TrailerModal', 'Trailer loaded successfully')} - onError={handleTrailerError} - onEnd={handleTrailerEnd} - onPlaybackStatusUpdate={(status) => { - if (status.isLoaded && !isPlaying) { - setIsPlaying(true); - } + controls={true} + paused={!isPlaying} + resizeMode="contain" + volume={1.0} + rate={1.0} + playInBackground={false} + playWhenInactive={false} + ignoreSilentSwitch="ignore" + onLoad={(data: OnLoadData) => { + logger.info('TrailerModal', 'Trailer loaded successfully', data); + }} + onError={(error) => { + logger.error('TrailerModal', 'Video error:', error); + handleTrailerError(); + }} + onEnd={() => { + logger.info('TrailerModal', 'Trailer ended'); + handleTrailerEnd(); + }} + onProgress={(data: OnProgressData) => { + // Handle progress if needed + }} + onLoadStart={() => { + logger.info('TrailerModal', 'Video load started'); + }} + onReadyForDisplay={() => { + logger.info('TrailerModal', 'Video ready for display'); }} /> From 71e34988769a8a4a3e18e34ce3e45571c17aac4a Mon Sep 17 00:00:00 2001 From: tapframe Date: Fri, 17 Oct 2025 21:29:15 +0530 Subject: [PATCH 06/17] ui fix --- src/components/metadata/TrailerModal.tsx | 118 +++++++---- src/components/metadata/TrailersSection.tsx | 213 +++++++++++++------- src/components/video/TrailerPlayer.tsx | 18 ++ 3 files changed, 238 insertions(+), 111 deletions(-) diff --git a/src/components/metadata/TrailerModal.tsx b/src/components/metadata/TrailerModal.tsx index 28764c2e..1c116574 100644 --- a/src/components/metadata/TrailerModal.tsx +++ b/src/components/metadata/TrailerModal.tsx @@ -10,8 +10,8 @@ import { Platform, Alert, } from 'react-native'; -import { MaterialIcons } from '@expo/vector-icons'; import { useTheme } from '../../contexts/ThemeContext'; +import { useTrailer } from '../../contexts/TrailerContext'; import { logger } from '../../utils/logger'; import TrailerService from '../../services/trailerService'; import Video, { VideoRef, OnLoadData, OnProgressData } from 'react-native-video'; @@ -62,11 +62,13 @@ const TrailerModal: React.FC = memo(({ contentTitle }) => { const { currentTheme } = useTheme(); + const { pauseTrailer, resumeTrailer } = useTrailer(); const videoRef = React.useRef(null); const [trailerUrl, setTrailerUrl] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [isPlaying, setIsPlaying] = useState(false); + const [retryCount, setRetryCount] = useState(0); // Load trailer when modal opens or trailer changes useEffect(() => { @@ -78,15 +80,25 @@ const TrailerModal: React.FC = memo(({ setLoading(false); setError(null); setIsPlaying(false); + setRetryCount(0); } }, [visible, trailer]); const loadTrailer = useCallback(async () => { if (!trailer) return; + // Pause hero section trailer when modal opens + try { + pauseTrailer(); + logger.info('TrailerModal', 'Paused hero section trailer'); + } catch (error) { + logger.warn('TrailerModal', 'Error pausing hero trailer:', error); + } + setLoading(true); setError(null); setTrailerUrl(null); + setRetryCount(0); // Reset retry count when starting fresh load try { const youtubeUrl = `https://www.youtube.com/watch?v=${trailer.key}`; @@ -110,6 +122,7 @@ const TrailerModal: React.FC = memo(({ } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to load trailer'; setError(errorMessage); + setLoading(false); logger.error('TrailerModal', 'Error loading trailer:', err); Alert.alert( @@ -117,21 +130,62 @@ const TrailerModal: React.FC = memo(({ 'This trailer could not be loaded at this time. Please try again later.', [{ text: 'OK', style: 'default' }] ); - } finally { - setLoading(false); } - }, [trailer, contentTitle]); + }, [trailer, contentTitle, pauseTrailer]); const handleClose = useCallback(() => { setIsPlaying(false); + + // Resume hero section trailer when modal closes + try { + resumeTrailer(); + logger.info('TrailerModal', 'Resumed hero section trailer'); + } catch (error) { + logger.warn('TrailerModal', 'Error resuming hero trailer:', error); + } + onClose(); - }, [onClose]); + }, [onClose, resumeTrailer]); const handleTrailerError = useCallback(() => { setError('Failed to play trailer'); setIsPlaying(false); }, []); + // Handle video playback errors with retry logic + const handleVideoError = useCallback((error: any) => { + logger.error('TrailerModal', 'Video error:', error); + + // Check if this is a permission/network error that might benefit from retry + const errorCode = error?.error?.code; + const isRetryableError = errorCode === -1102 || errorCode === -1009 || errorCode === -1005; + + if (isRetryableError && retryCount < 2) { + // Silent retry - increment count and try again + logger.info('TrailerModal', `Retrying video load (attempt ${retryCount + 1}/2)`); + setRetryCount(prev => prev + 1); + + // Small delay before retry to avoid rapid-fire attempts + setTimeout(() => { + if (videoRef.current) { + // Force video to reload by changing the source briefly + setTrailerUrl(null); + setTimeout(() => { + if (trailerUrl) { + setTrailerUrl(trailerUrl); + } + }, 100); + } + }, 1000); + return; + } + + // After 2 retries or for non-retryable errors, show the error + logger.error('TrailerModal', 'Video error after retries or non-retryable:', error); + setError('Unable to play trailer. Please try again.'); + setLoading(false); + }, [retryCount, trailerUrl]); + const handleTrailerEnd = useCallback(() => { setIsPlaying(false); }, []); @@ -158,13 +212,6 @@ const TrailerModal: React.FC = memo(({ {/* Enhanced Header */} - - - = memo(({ style={[styles.closeButton, { backgroundColor: 'rgba(255,255,255,0.1)' }]} hitSlop={{ top: 10, left: 10, right: 10, bottom: 10 }} > - + + Close + @@ -205,11 +250,6 @@ const TrailerModal: React.FC = memo(({ {error && !loading && ( - {error} @@ -222,7 +262,8 @@ const TrailerModal: React.FC = memo(({ )} - {trailerUrl && !loading && !error && ( + {/* Render the Video as soon as we have a URL; keep spinner overlay until onLoad */} + {trailerUrl && !error && ( ); }); // Ultra-optimized styles const styles = StyleSheet.create({ + heroWrapper: { + width: '100%', + marginTop: -150, // Extend wrapper 150px above to accommodate thumbnail overflow + paddingTop: 150, // Add padding to maintain proper positioning + overflow: 'hidden', // This will clip the thumbnail overflow when scrolling + }, heroSection: { width: '100%', backgroundColor: '#000', - overflow: 'hidden', + overflow: 'visible', // Allow thumbnail to extend within the wrapper }, absoluteFill: { @@ -1705,6 +1716,20 @@ const styles = StyleSheet.create({ right: 0, bottom: 0, }, + thumbnailContainer: { + position: 'absolute', + top: 0, // Now positioned at the top of the wrapper (which extends 150px above) + left: 0, + right: 0, + bottom: 0, + }, + thumbnailImage: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + }, backButtonContainer: { position: 'absolute', top: Platform.OS === 'android' ? 40 : 50, From 3effdee5c0d34487f2ca9a229c4aaf324e450ee8 Mon Sep 17 00:00:00 2001 From: tapframe Date: Fri, 17 Oct 2025 22:09:42 +0530 Subject: [PATCH 10/17] optimzed perf --- src/components/metadata/HeroSection.tsx | 107 +++++++++++++----------- 1 file changed, 58 insertions(+), 49 deletions(-) diff --git a/src/components/metadata/HeroSection.tsx b/src/components/metadata/HeroSection.tsx index ee4aa673..470c29e3 100644 --- a/src/components/metadata/HeroSection.tsx +++ b/src/components/metadata/HeroSection.tsx @@ -832,7 +832,7 @@ const HeroSection: React.FC = memo(({ const titleCardTranslateY = useSharedValue(0); const genreOpacity = useSharedValue(1); - // Performance optimization: Cache theme colors + // Ultra-optimized theme colors with stable references const themeColors = useMemo(() => ({ black: currentTheme.colors.black, darkBackground: currentTheme.colors.darkBackground, @@ -840,6 +840,15 @@ const HeroSection: React.FC = memo(({ text: currentTheme.colors.text }), [currentTheme.colors.black, currentTheme.colors.darkBackground, currentTheme.colors.highEmphasis, currentTheme.colors.text]); + // Pre-calculated style objects for better performance + const staticStyles = useMemo(() => ({ + heroWrapper: styles.heroWrapper, + heroSection: styles.heroSection, + absoluteFill: styles.absoluteFill, + thumbnailContainer: styles.thumbnailContainer, + thumbnailImage: styles.thumbnailImage, + }), []); + // Handle trailer preload completion const handleTrailerPreloaded = useCallback(() => { setTrailerPreloaded(true); @@ -1153,34 +1162,30 @@ const HeroSection: React.FC = memo(({ opacity: watchProgressOpacity.value, }), []); - // Enhanced backdrop with smooth loading animation and dynamic parallax effect + // Ultra-optimized backdrop with cached calculations and minimal worklet overhead const backdropImageStyle = useAnimatedStyle(() => { 'worklet'; const scrollYValue = scrollY.value; - // Default zoom factor - const defaultZoom = 1.1; // 10% zoom by default + // Pre-calculated constants for better performance + const DEFAULT_ZOOM = 1.1; + const SCROLL_UP_MULTIPLIER = 0.002; + const SCROLL_DOWN_MULTIPLIER = 0.0001; + const MAX_SCALE = 1.4; + const PARALLAX_FACTOR = 0.3; - // Dynamic scale based on scroll direction and position - let scale = defaultZoom; - if (scrollYValue < 0) { - // Scrolling up - zoom in to fill blank area - scale = defaultZoom + Math.abs(scrollYValue) * 0.002; // More aggressive zoom when scrolling up - } else { - // Scrolling down - subtle scale effect - scale = defaultZoom + scrollYValue * 0.0001; - } + // Optimized scale calculation with minimal branching + const scrollUpScale = DEFAULT_ZOOM + Math.abs(scrollYValue) * SCROLL_UP_MULTIPLIER; + const scrollDownScale = DEFAULT_ZOOM + scrollYValue * SCROLL_DOWN_MULTIPLIER; + const scale = Math.min(scrollYValue < 0 ? scrollUpScale : scrollDownScale, MAX_SCALE); - // Cap the scale to prevent excessive zoom - scale = Math.min(scale, 1.4); // Allow up to 40% zoom (including default) - - // Parallax effect - move image slower than scroll - const parallaxOffset = scrollYValue * 0.3; // 30% of scroll speed + // Single parallax calculation + const parallaxOffset = scrollYValue * PARALLAX_FACTOR; return { opacity: imageOpacity.value * imageLoadOpacity.value, transform: [ - { scale: scale }, + { scale }, { translateY: parallaxOffset } ], }; @@ -1209,29 +1214,29 @@ const HeroSection: React.FC = memo(({ opacity: genreOpacity.value }), []); - // Trailer parallax effect - moves slower than scroll for depth with dynamic zoom + // Ultra-optimized trailer parallax with cached calculations const trailerParallaxStyle = useAnimatedStyle(() => { 'worklet'; const scrollYValue = scrollY.value; - // Dynamic scale for trailer based on scroll direction - let scale = 1; - if (scrollYValue < 0) { - // Scrolling up - zoom in to fill blank area - scale = 1 + Math.abs(scrollYValue) * 0.0015; // Slightly less aggressive than background - } else { - // Scrolling down - subtle scale effect - scale = 1 + scrollYValue * 0.0001; - } + // Pre-calculated constants for better performance + const DEFAULT_ZOOM = 1.0; + const SCROLL_UP_MULTIPLIER = 0.0015; + const SCROLL_DOWN_MULTIPLIER = 0.0001; + const MAX_SCALE = 1.25; + const PARALLAX_FACTOR = 0.2; - // Cap the scale to prevent excessive zoom - scale = Math.min(scale, 1.25); // Allow up to 25% zoom for trailer + // Optimized scale calculation with minimal branching + const scrollUpScale = DEFAULT_ZOOM + Math.abs(scrollYValue) * SCROLL_UP_MULTIPLIER; + const scrollDownScale = DEFAULT_ZOOM + scrollYValue * SCROLL_DOWN_MULTIPLIER; + const scale = Math.min(scrollYValue < 0 ? scrollUpScale : scrollDownScale, MAX_SCALE); - const parallaxOffset = scrollYValue * 0.2; // 20% of scroll speed for trailer + // Single parallax calculation + const parallaxOffset = scrollYValue * PARALLAX_FACTOR; return { transform: [ - { scale: scale }, + { scale }, { translateY: parallaxOffset } ], }; @@ -1384,27 +1389,31 @@ const HeroSection: React.FC = memo(({ } }, [isFocused, setTrailerPlaying]); - // Pause/resume trailer based on scroll with hysteresis and guard + // Ultra-optimized scroll-based pause/resume with cached calculations useDerivedValue(() => { 'worklet'; try { if (!scrollGuardEnabledSV.value || isFocusedSV.value === 0) return; - const pauseThreshold = heroHeight.value * 0.7; // pause when beyond 70% - const resumeThreshold = heroHeight.value * 0.4; // resume when back within 40% - + + // Pre-calculate thresholds for better performance + const pauseThreshold = heroHeight.value * 0.7; + const resumeThreshold = heroHeight.value * 0.4; const y = scrollY.value; + const isPlaying = isPlayingSV.value === 1; + const isPausedByScroll = pausedByScrollSV.value === 1; - if (y > pauseThreshold && isPlayingSV.value === 1 && pausedByScrollSV.value === 0) { + // Optimized pause/resume logic with minimal branching + if (y > pauseThreshold && isPlaying && !isPausedByScroll) { pausedByScrollSV.value = 1; runOnJS(setTrailerPlaying)(false); isPlayingSV.value = 0; - } else if (y < resumeThreshold && pausedByScrollSV.value === 1) { + } else if (y < resumeThreshold && isPausedByScroll) { pausedByScrollSV.value = 0; runOnJS(setTrailerPlaying)(true); isPlayingSV.value = 1; } } catch (e) { - // no-op + // Silent error handling for performance } }); @@ -1456,21 +1465,21 @@ const HeroSection: React.FC = memo(({ return ( - - + + {/* Optimized Background */} - + {/* Shimmer loading effect removed */} {/* Background thumbnail image - always rendered when available with parallax */} {shouldLoadSecondaryData && imageSource && !loadingBanner && ( - = memo(({ {/* Hidden preload trailer player - loads in background */} {shouldLoadSecondaryData && settings?.showTrailers && trailerUrl && !trailerLoading && !trailerError && !trailerPreloaded && ( - + = memo(({ {/* Visible trailer player - rendered on top with fade transition and parallax */} {shouldLoadSecondaryData && settings?.showTrailers && trailerUrl && !trailerLoading && !trailerError && trailerPreloaded && ( - = memo(({ trailerUrl={trailerUrl} autoPlay={globalTrailerPlaying} muted={trailerMuted} - style={styles.absoluteFill} + style={staticStyles.absoluteFill} hideLoadingSpinner={true} hideControls={true} onFullscreenToggle={handleFullscreenToggle} From bb6f1f32a046b1dce5d1f9a4ba4aaa54b5d1457e Mon Sep 17 00:00:00 2001 From: tapframe Date: Fri, 17 Oct 2025 22:18:17 +0530 Subject: [PATCH 11/17] anim changes --- src/components/home/HeroCarousel.tsx | 45 ++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/components/home/HeroCarousel.tsx b/src/components/home/HeroCarousel.tsx index a5dc5e3c..bf6a311c 100644 --- a/src/components/home/HeroCarousel.tsx +++ b/src/components/home/HeroCarousel.tsx @@ -55,6 +55,12 @@ const HeroCarousel: React.FC = ({ items, loading = false }) = // Optimized: update background as soon as scroll starts, without waiting for momentum end const scrollX = useSharedValue(0); const interval = CARD_WIDTH + 16; + + // Reset scroll position when component mounts/remounts + useEffect(() => { + scrollX.value = 0; + }, []); + const scrollHandler = useAnimatedScrollHandler({ onScroll: (event) => { scrollX.value = event.contentOffset.x; @@ -114,9 +120,9 @@ const HeroCarousel: React.FC = ({ items, loading = false }) = const translateX = scrollX.value; const progress = Math.abs(translateX) / (data.length * (CARD_WIDTH + 16)); - // Subtle scale animation for the entire container - const scale = 1 - progress * 0.02; - const clampedScale = Math.max(0.98, Math.min(1, scale)); + // Very subtle scale animation for the entire container + const scale = 1 - progress * 0.01; + const clampedScale = Math.max(0.99, Math.min(1, scale)); return { transform: [{ scale: clampedScale }], @@ -299,14 +305,17 @@ const HeroCarousel: React.FC = ({ items, loading = false }) = decelerationRate="fast" contentContainerStyle={contentPadding} onScroll={scrollHandler} - scrollEventThrottle={16} + scrollEventThrottle={8} disableIntervalMomentum initialNumToRender={3} windowSize={5} - maxToRenderPerBatch={3} - updateCellsBatchingPeriod={100} + maxToRenderPerBatch={2} + updateCellsBatchingPeriod={50} removeClippedSubviews={false} getItemLayout={getItemLayout} + pagingEnabled={false} + bounces={false} + overScrollMode="never" renderItem={({ item, index }) => ( = memo(({ item, colors, logoFail const bannerOpacity = useSharedValue(0); const logoOpacity = useSharedValue(0); + // Reset animations when component mounts/remounts + useEffect(() => { + bannerOpacity.value = 0; + logoOpacity.value = 0; + }, [item.id]); + const inputRange = [ (index - 1) * (CARD_WIDTH + 16), index * (CARD_WIDTH + 16), @@ -388,8 +403,8 @@ const CarouselCard: React.FC = memo(({ item, colors, logoFail const cardOffset = index * (CARD_WIDTH + 16); const distance = translateX - cardOffset; - // Subtle parallax effect for banner - const parallaxOffset = distance * 0.1; + // Reduced parallax effect to prevent displacement + const parallaxOffset = distance * 0.05; return { transform: [{ translateX: parallaxOffset }], @@ -401,8 +416,8 @@ const CarouselCard: React.FC = memo(({ item, colors, logoFail const cardOffset = index * (CARD_WIDTH + 16); const distance = translateX - cardOffset; - // Reverse parallax for info section - const parallaxOffset = -distance * 0.05; + // Minimal parallax for info section to prevent displacement + const parallaxOffset = -distance * 0.02; return { transform: [{ translateY: parallaxOffset }], @@ -411,13 +426,19 @@ const CarouselCard: React.FC = memo(({ item, colors, logoFail useEffect(() => { if (bannerLoaded) { - bannerOpacity.value = withTiming(1, { duration: 300, easing: Easing.out(Easing.cubic) }); + bannerOpacity.value = withTiming(1, { + duration: 250, + easing: Easing.out(Easing.ease) + }); } }, [bannerLoaded]); useEffect(() => { if (logoLoaded) { - logoOpacity.value = withTiming(1, { duration: 400, easing: Easing.out(Easing.cubic) }); + logoOpacity.value = withTiming(1, { + duration: 300, + easing: Easing.out(Easing.ease) + }); } }, [logoLoaded]); From 1535ef9aacf8e6cb9bf23d600cffd63bb2d4aff9 Mon Sep 17 00:00:00 2001 From: tapframe Date: Fri, 17 Oct 2025 23:19:55 +0530 Subject: [PATCH 12/17] trailer improvements --- src/components/home/HeroCarousel.tsx | 328 +++++++++++++------- src/components/metadata/TrailersSection.tsx | 118 +++++-- 2 files changed, 313 insertions(+), 133 deletions(-) diff --git a/src/components/home/HeroCarousel.tsx b/src/components/home/HeroCarousel.tsx index bf6a311c..58b13981 100644 --- a/src/components/home/HeroCarousel.tsx +++ b/src/components/home/HeroCarousel.tsx @@ -1,5 +1,5 @@ -import React, { useMemo, useState, useEffect, useCallback, memo } from 'react'; -import { View, Text, StyleSheet, Dimensions, TouchableOpacity, ViewStyle, TextStyle, ImageStyle, FlatList, StyleProp, Platform, Image } from 'react-native'; +import React, { useMemo, useState, useEffect, useCallback, memo, useRef } from 'react'; +import { View, Text, StyleSheet, Dimensions, TouchableOpacity, ViewStyle, TextStyle, ImageStyle, ScrollView, StyleProp, Platform, Image } from 'react-native'; import Animated, { FadeIn, FadeOut, Easing, useSharedValue, withTiming, useAnimatedStyle, useAnimatedScrollHandler, useAnimatedReaction, runOnJS, SharedValue } from 'react-native-reanimated'; import { LinearGradient } from 'expo-linear-gradient'; import { BlurView } from 'expo-blur'; @@ -47,6 +47,7 @@ const HeroCarousel: React.FC = ({ items, loading = false }) = const data = useMemo(() => (items && items.length ? items.slice(0, 10) : []), [items]); const [activeIndex, setActiveIndex] = useState(0); const [failedLogoIds, setFailedLogoIds] = useState>(new Set()); + const scrollViewRef = useRef(null); // Note: do not early-return before hooks. Loading UI is returned later. @@ -56,10 +57,32 @@ const HeroCarousel: React.FC = ({ items, loading = false }) = const scrollX = useSharedValue(0); const interval = CARD_WIDTH + 16; - // Reset scroll position when component mounts/remounts + // Comprehensive reset when component mounts/remounts to prevent glitching useEffect(() => { scrollX.value = 0; + setActiveIndex(0); + + // Scroll to position 0 after a brief delay to ensure ScrollView is ready + const timer = setTimeout(() => { + scrollViewRef.current?.scrollTo({ x: 0, y: 0, animated: false }); + }, 50); + + return () => clearTimeout(timer); }, []); + + // Reset scroll when data becomes available + useEffect(() => { + if (data.length > 0) { + scrollX.value = 0; + setActiveIndex(0); + + const timer = setTimeout(() => { + scrollViewRef.current?.scrollTo({ x: 0, y: 0, animated: false }); + }, 100); + + return () => clearTimeout(timer); + } + }, [data.length]); const scrollHandler = useAnimatedScrollHandler({ onScroll: (event) => { @@ -96,17 +119,6 @@ const HeroCarousel: React.FC = ({ items, loading = false }) = const contentPadding = useMemo(() => ({ paddingHorizontal: (width - CARD_WIDTH) / 2 }), []); - const keyExtractor = useCallback((item: StreamingContent) => item.id, []); - - const getItemLayout = useCallback( - (_: unknown, index: number) => { - const length = CARD_WIDTH + 16; - const offset = length * index; - return { length, offset, index }; - }, - [] - ); - const handleNavigateToMetadata = useCallback((id: string, type: any) => { navigation.navigate('Metadata', { id, type }); }, [navigation]); @@ -133,16 +145,13 @@ const HeroCarousel: React.FC = ({ items, loading = false }) = return ( }> - String(i)} + ( - + > + {[1, 2, 3].map((_, index) => ( + = ({ items, loading = false }) = - )} - /> + ))} + ); @@ -296,9 +305,8 @@ const HeroCarousel: React.FC = ({ items, loading = false }) = pointerEvents="none" /> )} - = ({ items, loading = false }) = onScroll={scrollHandler} scrollEventThrottle={8} disableIntervalMomentum - initialNumToRender={3} - windowSize={5} - maxToRenderPerBatch={2} - updateCellsBatchingPeriod={50} - removeClippedSubviews={false} - getItemLayout={getItemLayout} pagingEnabled={false} bounces={false} overScrollMode="never" - renderItem={({ item, index }) => ( - - setFailedLogoIds((prev) => new Set(prev).add(item.id))} - onPressInfo={() => handleNavigateToMetadata(item.id, item.type)} - onPressPlay={() => handleNavigateToStreams(item.id, item.type)} - scrollX={scrollX} - index={index} - /> - - )} - /> + > + {data.map((item, index) => ( + setFailedLogoIds((prev) => new Set(prev).add(item.id))} + onPressInfo={() => handleNavigateToMetadata(item.id, item.type)} + onPressPlay={() => handleNavigateToStreams(item.id, item.type)} + scrollX={scrollX} + index={index} + /> + ))} + ); @@ -356,11 +355,18 @@ const CarouselCard: React.FC = memo(({ item, colors, logoFail const bannerOpacity = useSharedValue(0); const logoOpacity = useSharedValue(0); + const genresOpacity = useSharedValue(0); + const actionsOpacity = useSharedValue(0); - // Reset animations when component mounts/remounts + // Reset animations when component mounts/remounts to prevent glitching useEffect(() => { bannerOpacity.value = 0; logoOpacity.value = 0; + genresOpacity.value = 0; + actionsOpacity.value = 0; + // Force re-render states to ensure clean state + setBannerLoaded(false); + setLogoLoaded(false); }, [item.id]); const inputRange = [ @@ -376,6 +382,38 @@ const CarouselCard: React.FC = memo(({ item, colors, logoFail const logoAnimatedStyle = useAnimatedStyle(() => ({ opacity: logoOpacity.value, })); + + const genresAnimatedStyle = useAnimatedStyle(() => { + const translateX = scrollX.value; + const cardOffset = index * (CARD_WIDTH + 16); + const distance = Math.abs(translateX - cardOffset); + const maxDistance = (CARD_WIDTH + 16) * 0.5; // Smaller threshold for smoother transition + + // Hide genres when scrolling (not centered) + const progress = Math.min(distance / maxDistance, 1); + const opacity = 1 - progress; // Linear fade out + const clampedOpacity = Math.max(0, Math.min(1, opacity)); + + return { + opacity: clampedOpacity, + }; + }); + + const actionsAnimatedStyle = useAnimatedStyle(() => { + const translateX = scrollX.value; + const cardOffset = index * (CARD_WIDTH + 16); + const distance = Math.abs(translateX - cardOffset); + const maxDistance = (CARD_WIDTH + 16) * 0.5; // Smaller threshold for smoother transition + + // Hide actions when scrolling (not centered) + const progress = Math.min(distance / maxDistance, 1); + const opacity = 1 - progress; // Linear fade out + const clampedOpacity = Math.max(0, Math.min(1, opacity)); + + return { + opacity: clampedOpacity, + }; + }); // Scroll-based animations const cardAnimatedStyle = useAnimatedStyle(() => { @@ -414,13 +452,20 @@ const CarouselCard: React.FC = memo(({ item, colors, logoFail const infoParallaxStyle = useAnimatedStyle(() => { const translateX = scrollX.value; const cardOffset = index * (CARD_WIDTH + 16); - const distance = translateX - cardOffset; + const distance = Math.abs(translateX - cardOffset); + const maxDistance = CARD_WIDTH + 16; + + // Hide info section when scrolling (not centered) + const progress = distance / maxDistance; + const opacity = 1 - progress * 2; // Fade out faster when scrolling + const clampedOpacity = Math.max(0, Math.min(1, opacity)); // Minimal parallax for info section to prevent displacement - const parallaxOffset = -distance * 0.02; + const parallaxOffset = -(translateX - cardOffset) * 0.02; return { transform: [{ translateY: parallaxOffset }], + opacity: clampedOpacity, }; }); @@ -443,75 +488,64 @@ const CarouselCard: React.FC = memo(({ item, colors, logoFail }, [logoLoaded]); return ( - - }> - - {!bannerLoaded && ( - - )} - - setBannerLoaded(true)} - /> - - - - - {item.logo && !logoFailed ? ( - + + }> + + {!bannerLoaded && ( + + )} + setLogoLoaded(true)} - onError={onLogoError} + style={styles.banner as any} + resizeMode={FastImage.resizeMode.cover} + onLoad={() => setBannerLoaded(true)} /> - ) : ( - - - {item.name} - - - )} - {item.genres && ( - + + + {/* Static genres positioned absolutely over the card */} + {item.genres && ( + + {item.genres.slice(0, 3).join(' • ')} - )} - + )} + {/* Static action buttons positioned absolutely over the card */} + + = memo(({ item, colors, logoFail Info - - - + + {/* Static logo positioned absolutely over the card */} + {item.logo && !logoFailed && ( + + + setLogoLoaded(true)} + onError={onLogoError} + /> + + + )} + {/* Static title when no logo */} + {!item.logo || logoFailed ? ( + + + + {item.name} + + + + ) : null} + + ); }); @@ -694,6 +756,46 @@ const styles = StyleSheet.create({ marginLeft: 6, fontSize: 14, }, + logoOverlay: { + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + alignItems: 'center', + justifyContent: 'flex-end', + paddingBottom: 80, // Position above genres and actions + }, + titleOverlay: { + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + alignItems: 'center', + justifyContent: 'flex-end', + paddingBottom: 90, // Position above genres and actions + }, + genresOverlay: { + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + alignItems: 'center', + justifyContent: 'flex-end', + paddingBottom: 65, // Position above actions + }, + actionsOverlay: { + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + alignItems: 'center', + justifyContent: 'flex-end', + paddingBottom: 12, // Position at bottom + }, }); export default React.memo(HeroCarousel); diff --git a/src/components/metadata/TrailersSection.tsx b/src/components/metadata/TrailersSection.tsx index db2b700a..fffa5906 100644 --- a/src/components/metadata/TrailersSection.tsx +++ b/src/components/metadata/TrailersSection.tsx @@ -33,6 +33,8 @@ interface TrailerVideo { type: string; official: boolean; published_at: string; + seasonNumber: number | null; + displayName?: string; } interface TrailersSectionProps { @@ -153,28 +155,93 @@ const TrailersSection: React.FC = memo(({ return; } - const videosEndpoint = type === 'movie' - ? `https://api.themoviedb.org/3/movie/${tmdbId}/videos?api_key=d131017ccc6e5462a81c9304d21476de&language=en-US` - : `https://api.themoviedb.org/3/tv/${tmdbId}/videos?api_key=d131017ccc6e5462a81c9304d21476de&language=en-US`; + let allVideos: any[] = []; - logger.info('TrailersSection', `Fetching videos from: ${videosEndpoint}`); + if (type === 'movie') { + // For movies, just fetch the main videos endpoint + const videosEndpoint = `https://api.themoviedb.org/3/movie/${tmdbId}/videos?api_key=d131017ccc6e5462a81c9304d21476de&language=en-US`; - const response = await fetch(videosEndpoint); - if (!response.ok) { - // 404 is normal - means no videos exist for this content - if (response.status === 404) { - logger.info('TrailersSection', `No videos found for TMDB ID ${tmdbId} (404 response)`); - setTrailers({}); // Empty trailers - section won't render - return; + logger.info('TrailersSection', `Fetching movie videos from: ${videosEndpoint}`); + + const response = await fetch(videosEndpoint); + if (!response.ok) { + // 404 is normal - means no videos exist for this content + if (response.status === 404) { + logger.info('TrailersSection', `No videos found for movie TMDB ID ${tmdbId} (404 response)`); + setTrailers({}); // Empty trailers - section won't render + return; + } + logger.error('TrailersSection', `Videos endpoint failed: ${response.status} ${response.statusText}`); + throw new Error(`Failed to fetch trailers: ${response.status}`); } - logger.error('TrailersSection', `Videos endpoint failed: ${response.status} ${response.statusText}`); - throw new Error(`Failed to fetch trailers: ${response.status}`); + + const data = await response.json(); + allVideos = data.results || []; + logger.info('TrailersSection', `Received ${allVideos.length} videos for movie TMDB ID ${tmdbId}`); + } else { + // For TV shows, fetch both main TV videos and season-specific videos + logger.info('TrailersSection', `Fetching TV show videos and season trailers for TMDB ID ${tmdbId}`); + + // Get TV show details to know how many seasons there are + const tvDetailsResponse = await fetch(basicEndpoint); + const tvDetails = await tvDetailsResponse.json(); + const numberOfSeasons = tvDetails.number_of_seasons || 0; + + logger.info('TrailersSection', `TV show has ${numberOfSeasons} seasons`); + + // Fetch main TV show videos + const tvVideosEndpoint = `https://api.themoviedb.org/3/tv/${tmdbId}/videos?api_key=d131017ccc6e5462a81c9304d21476de&language=en-US`; + const tvResponse = await fetch(tvVideosEndpoint); + + if (tvResponse.ok) { + const tvData = await tvResponse.json(); + // Add season info to main TV videos + const mainVideos = (tvData.results || []).map((video: any) => ({ + ...video, + seasonNumber: null as number | null, // null indicates main TV show videos + displayName: video.name + })); + allVideos.push(...mainVideos); + logger.info('TrailersSection', `Received ${mainVideos.length} main TV videos`); + } + + // Fetch videos from each season (skip season 0 which is specials) + const seasonPromises = []; + for (let seasonNum = 1; seasonNum <= numberOfSeasons; seasonNum++) { + seasonPromises.push( + fetch(`https://api.themoviedb.org/3/tv/${tmdbId}/season/${seasonNum}/videos?api_key=d131017ccc6e5462a81c9304d21476de&language=en-US`) + .then(res => res.json()) + .then(data => ({ + seasonNumber: seasonNum, + videos: data.results || [] + })) + .catch(err => { + logger.warn('TrailersSection', `Failed to fetch season ${seasonNum} videos:`, err); + return { seasonNumber: seasonNum, videos: [] }; + }) + ); + } + + const seasonResults = await Promise.all(seasonPromises); + + // Add season videos to the collection + seasonResults.forEach(result => { + if (result.videos.length > 0) { + const seasonVideos = result.videos.map((video: any) => ({ + ...video, + seasonNumber: result.seasonNumber as number | null, + displayName: `Season ${result.seasonNumber} - ${video.name}` + })); + allVideos.push(...seasonVideos); + logger.info('TrailersSection', `Season ${result.seasonNumber}: ${result.videos.length} videos`); + } + }); + + const totalSeasonVideos = seasonResults.reduce((sum, result) => sum + result.videos.length, 0); + logger.info('TrailersSection', `Total videos collected: ${allVideos.length} (main: ${allVideos.filter(v => v.seasonNumber === null).length}, seasons: ${totalSeasonVideos})`); } - const data = await response.json(); - logger.info('TrailersSection', `Received ${data.results?.length || 0} videos for TMDB ID ${tmdbId}`); - - const categorized = categorizeTrailers(data.results || []); + const categorized = categorizeTrailers(allVideos); const totalVideos = Object.values(categorized).reduce((sum, videos) => sum + videos.length, 0); if (totalVideos === 0) { @@ -219,10 +286,21 @@ const TrailersSection: React.FC = memo(({ categories[category].push(video); }); - // Sort within each category: official trailers first, then by published date (newest first) + // Sort within each category: season trailers first (newest seasons), then main series, official first, then by date Object.keys(categories).forEach(category => { categories[category].sort((a, b) => { - // Official trailers come first + // Season trailers come before main series trailers + if (a.seasonNumber !== null && b.seasonNumber === null) return -1; + if (a.seasonNumber === null && b.seasonNumber !== null) return 1; + + // If both have season numbers, sort by season number (newest seasons first) + if (a.seasonNumber !== null && b.seasonNumber !== null) { + if (a.seasonNumber !== b.seasonNumber) { + return b.seasonNumber - a.seasonNumber; // Higher season numbers first + } + } + + // Official trailers come first within the same season/main series group if (a.official && !b.official) return -1; if (!a.official && b.official) return 1; @@ -506,7 +584,7 @@ const TrailersSection: React.FC = memo(({ style={[styles.trailerTitle, { color: currentTheme.colors.highEmphasis }]} numberOfLines={2} > - {trailer.name} + {trailer.displayName || trailer.name} {new Date(trailer.published_at).getFullYear()} From fd5861026d9088d7be12a2acb2d04d0fa924c954 Mon Sep 17 00:00:00 2001 From: tapframe Date: Fri, 17 Oct 2025 23:41:27 +0530 Subject: [PATCH 13/17] floating header logo fetch fix --- src/components/metadata/FloatingHeader.tsx | 24 ++++++++++++---------- src/components/metadata/HeroSection.tsx | 4 ++++ src/screens/MetadataScreen.tsx | 7 ++++++- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/components/metadata/FloatingHeader.tsx b/src/components/metadata/FloatingHeader.tsx index fd3a8ac0..23193eb6 100644 --- a/src/components/metadata/FloatingHeader.tsx +++ b/src/components/metadata/FloatingHeader.tsx @@ -6,6 +6,7 @@ import { TouchableOpacity, Platform, Dimensions, + Image, } from 'react-native'; import { BlurView as ExpoBlurView } from 'expo-blur'; import { MaterialIcons, Feather } from '@expo/vector-icons'; @@ -24,7 +25,6 @@ if (Platform.OS === 'ios') { liquidGlassAvailable = false; } } -import FastImage from '@d11/react-native-fast-image'; import Animated, { useAnimatedStyle, interpolate, @@ -49,6 +49,7 @@ interface FloatingHeaderProps { headerElementsOpacity: SharedValue; safeAreaTop: number; setLogoLoadError: (error: boolean) => void; + stableLogoUri?: string | null; } const FloatingHeader: React.FC = ({ @@ -62,6 +63,7 @@ const FloatingHeader: React.FC = ({ headerElementsOpacity, safeAreaTop, setLogoLoadError, + stableLogoUri, }) => { const { currentTheme } = useTheme(); const [isHeaderInteractive, setIsHeaderInteractive] = React.useState(false); @@ -111,13 +113,13 @@ const FloatingHeader: React.FC = ({ - {metadata.logo && !logoLoadError ? ( - { - logger.warn(`[FloatingHeader] Logo failed to load: ${metadata.logo}`); + logger.warn(`[FloatingHeader] Logo failed to load: ${stableLogoUri || metadata.logo}`); setLogoLoadError(true); }} /> @@ -155,13 +157,13 @@ const FloatingHeader: React.FC = ({ - {metadata.logo && !logoLoadError ? ( - { - logger.warn(`[FloatingHeader] Logo failed to load: ${metadata.logo}`); + logger.warn(`[FloatingHeader] Logo failed to load: ${stableLogoUri || metadata.logo}`); setLogoLoadError(true); }} /> diff --git a/src/components/metadata/HeroSection.tsx b/src/components/metadata/HeroSection.tsx index 470c29e3..64fef14c 100644 --- a/src/components/metadata/HeroSection.tsx +++ b/src/components/metadata/HeroSection.tsx @@ -83,6 +83,7 @@ interface HeroSectionProps { traktSynced?: boolean; traktProgress?: number; } | null; + onStableLogoUriChange?: (logoUri: string | null) => void; type: 'movie' | 'series'; getEpisodeDetails: (episodeId: string) => { seasonNumber: string; episodeNumber: string; episodeName: string } | null; handleShowStreams: () => void; @@ -777,6 +778,7 @@ const HeroSection: React.FC = memo(({ buttonsTranslateY, watchProgressOpacity, watchProgress, + onStableLogoUriChange, type, getEpisodeDetails, handleShowStreams, @@ -966,12 +968,14 @@ const HeroSection: React.FC = memo(({ if (metadata?.logo && metadata.logo !== stableLogoUri) { setStableLogoUri(metadata.logo); + onStableLogoUriChange?.(metadata.logo); setLogoHasLoadedSuccessfully(false); // Reset for new logo logoLoadOpacity.value = 0; // reset fade for new logo setShouldShowTextFallback(false); } else if (!metadata?.logo && stableLogoUri) { // Clear logo if metadata no longer has one setStableLogoUri(null); + onStableLogoUriChange?.(null); setLogoHasLoadedSuccessfully(false); // Start a short grace period before showing text fallback setShouldShowTextFallback(false); diff --git a/src/screens/MetadataScreen.tsx b/src/screens/MetadataScreen.tsx index a922d8cf..40043dea 100644 --- a/src/screens/MetadataScreen.tsx +++ b/src/screens/MetadataScreen.tsx @@ -211,6 +211,9 @@ const MetadataScreen: React.FC = () => { const watchProgressData = useWatchProgress(id, Object.keys(groupedEpisodes).length > 0 ? 'series' : type as 'movie' | 'series', episodeId, episodes); const assetData = useMetadataAssets(metadata, id, type, imdbId, settings, setMetadata); const animations = useMetadataAnimations(safeAreaTop, watchProgressData.watchProgress); + + // Stable logo URI from HeroSection + const [stableLogoUri, setStableLogoUri] = React.useState(null); // Extract dominant color from hero image for dynamic background const heroImageUri = useMemo(() => { @@ -870,7 +873,7 @@ const MetadataScreen: React.FC = () => { {metadata && ( <> {/* Floating Header - Optimized */} - { headerElementsOpacity={animations.headerElementsOpacity} safeAreaTop={safeAreaTop} setLogoLoadError={assetData.setLogoLoadError} + stableLogoUri={stableLogoUri} /> { watchProgressOpacity={animations.watchProgressOpacity} watchProgressWidth={animations.watchProgressWidth} watchProgress={watchProgressData.watchProgress} + onStableLogoUriChange={setStableLogoUri} type={Object.keys(groupedEpisodes).length > 0 ? 'series' : type as 'movie' | 'series'} getEpisodeDetails={watchProgressData.getEpisodeDetails} handleShowStreams={handleShowStreams} From efa5d3f6292763ef71520447ba0412d6657e70db Mon Sep 17 00:00:00 2001 From: tapframe Date: Sat, 18 Oct 2025 00:41:32 +0530 Subject: [PATCH 14/17] fastimage api bug fix --- src/components/metadata/FloatingHeader.tsx | 4 ++-- src/components/player/KSPlayerCore.tsx | 2 +- src/types/metadata.ts | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/metadata/FloatingHeader.tsx b/src/components/metadata/FloatingHeader.tsx index 23193eb6..ca7ffdd0 100644 --- a/src/components/metadata/FloatingHeader.tsx +++ b/src/components/metadata/FloatingHeader.tsx @@ -204,10 +204,10 @@ const FloatingHeader: React.FC = ({ {metadata.logo && !logoLoadError ? ( - { logger.warn(`[FloatingHeader] Logo failed to load: ${metadata.logo}`); setLogoLoadError(true); diff --git a/src/components/player/KSPlayerCore.tsx b/src/components/player/KSPlayerCore.tsx index 94e65628..688af143 100644 --- a/src/components/player/KSPlayerCore.tsx +++ b/src/components/player/KSPlayerCore.tsx @@ -110,7 +110,7 @@ const KSPlayerCore: React.FC = () => { const [selectedAudioTrack, setSelectedAudioTrack] = useState(null); const [textTracks, setTextTracks] = useState([]); const [selectedTextTrack, setSelectedTextTrack] = useState(-1); - const [resizeMode, setResizeMode] = useState('stretch'); + const [resizeMode, setResizeMode] = useState('contain'); const [buffered, setBuffered] = useState(0); const [seekPosition, setSeekPosition] = useState(null); const ksPlayerRef = useRef(null); diff --git a/src/types/metadata.ts b/src/types/metadata.ts index de2338a3..be8bc396 100644 --- a/src/types/metadata.ts +++ b/src/types/metadata.ts @@ -1,6 +1,9 @@ import { TMDBEpisode } from '../services/tmdbService'; import { StreamingContent } from '../services/catalogService'; +// Re-export StreamingContent for convenience +export { StreamingContent }; + // Types for route params export type RouteParams = { id: string; From 51ae0784cf701c81d7cfa08e398ca0c37f792d29 Mon Sep 17 00:00:00 2001 From: tapframe Date: Sat, 18 Oct 2025 12:09:22 +0530 Subject: [PATCH 15/17] flashlist update --- package-lock.json | 12 +++++------- package.json | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0e9a36bf..e3dfe3b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "@react-navigation/native-stack": "^7.3.10", "@react-navigation/stack": "^7.2.10", "@sentry/react-native": "~7.3.0", - "@shopify/flash-list": "2.0.2", + "@shopify/flash-list": "^2.1.0", "@supabase/supabase-js": "^2.54.0", "@types/lodash": "^4.17.16", "@types/react-native-video": "^5.0.20", @@ -3589,13 +3589,10 @@ } }, "node_modules/@shopify/flash-list": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@shopify/flash-list/-/flash-list-2.0.2.tgz", - "integrity": "sha512-zhlrhA9eiuEzja4wxVvotgXHtqd3qsYbXkQ3rsBfOgbFA9BVeErpDE/yEwtlIviRGEqpuFj/oU5owD6ByaNX+w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@shopify/flash-list/-/flash-list-2.1.0.tgz", + "integrity": "sha512-/EIQlptG456yM5o9qNmNsmaZEFEOGvG3WGyb6GUAxSLlcKUGlPUkPI2NLW5wQSDEY4xSRa5zocUI+9xwmsM4Kg==", "license": "MIT", - "dependencies": { - "tslib": "2.8.1" - }, "peerDependencies": { "@babel/runtime": "*", "react": "*", @@ -12949,6 +12946,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, "license": "0BSD" }, "node_modules/tunnel-agent": { diff --git a/package.json b/package.json index 7f3d4927..7cbcf2a0 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@react-navigation/native-stack": "^7.3.10", "@react-navigation/stack": "^7.2.10", "@sentry/react-native": "~7.3.0", - "@shopify/flash-list": "2.0.2", + "@shopify/flash-list": "^2.1.0", "@supabase/supabase-js": "^2.54.0", "@types/lodash": "^4.17.16", "@types/react-native-video": "^5.0.20", From 8b1a40d2e2683d52c848482fbd19e82495400ff4 Mon Sep 17 00:00:00 2001 From: tapframe Date: Sat, 18 Oct 2025 13:22:34 +0530 Subject: [PATCH 16/17] ui changes --- ios/Nuvio.xcodeproj/project.pbxproj | 8 +- .../xcshareddata/xcschemes/Nuvio.xcscheme | 2 +- ios/Nuvio/Info.plist | 193 ++- ios/Nuvio/Nuvio.entitlements | 9 +- ios/Nuvio/NuvioRelease.entitlements | 9 +- package-lock.json | 16 +- package.json | 3 +- patches/react-native-video+6.17.0.patch | 1467 +++++++++++++++++ src/components/home/CatalogSection.tsx | 8 +- src/components/metadata/TrailerModal.tsx | 5 - src/components/metadata/TrailersSection.tsx | 21 - src/screens/HomeScreen.tsx | 8 +- 12 files changed, 1596 insertions(+), 153 deletions(-) create mode 100644 patches/react-native-video+6.17.0.patch diff --git a/ios/Nuvio.xcodeproj/project.pbxproj b/ios/Nuvio.xcodeproj/project.pbxproj index 4bf304a6..1d96622b 100644 --- a/ios/Nuvio.xcodeproj/project.pbxproj +++ b/ios/Nuvio.xcodeproj/project.pbxproj @@ -460,8 +460,8 @@ "-lc++", ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; - PRODUCT_BUNDLE_IDENTIFIER = com.nuvio.app; - PRODUCT_NAME = "Nuvio"; + PRODUCT_BUNDLE_IDENTIFIER = com.nuviohub.app; + PRODUCT_NAME = Nuvio; SWIFT_OBJC_BRIDGING_HEADER = "Nuvio/Nuvio-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -492,8 +492,8 @@ "-lc++", ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; - PRODUCT_BUNDLE_IDENTIFIER = "com.nuvio.app"; - PRODUCT_NAME = "Nuvio"; + PRODUCT_BUNDLE_IDENTIFIER = com.nuviohub.app; + PRODUCT_NAME = Nuvio; SWIFT_OBJC_BRIDGING_HEADER = "Nuvio/Nuvio-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/ios/Nuvio.xcodeproj/xcshareddata/xcschemes/Nuvio.xcscheme b/ios/Nuvio.xcodeproj/xcshareddata/xcschemes/Nuvio.xcscheme index d56adf85..60f9eb04 100644 --- a/ios/Nuvio.xcodeproj/xcshareddata/xcschemes/Nuvio.xcscheme +++ b/ios/Nuvio.xcodeproj/xcshareddata/xcschemes/Nuvio.xcscheme @@ -82,7 +82,7 @@ buildConfiguration = "Debug"> diff --git a/ios/Nuvio/Info.plist b/ios/Nuvio/Info.plist index d701baa9..4ab9b8d0 100644 --- a/ios/Nuvio/Info.plist +++ b/ios/Nuvio/Info.plist @@ -1,101 +1,98 @@ - - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Nuvio - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.2.5 - CFBundleSignature - ???? - CFBundleURLTypes - - - CFBundleURLSchemes - - nuvio - com.nuvio.app - - - - CFBundleURLSchemes - - exp+nuvio - - - - CFBundleVersion - 20 - LSMinimumSystemVersion - 12.0 - LSRequiresIPhoneOS - - LSSupportsOpeningDocumentsInPlace - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - NSBonjourServices - - _http._tcp - - NSLocalNetworkUsageDescription - Allow $(PRODUCT_NAME) to access your local network - NSMicrophoneUsageDescription - This app does not require microphone access. - RCTNewArchEnabled - - RCTRootViewBackgroundColor - 4278322180 - UIBackgroundModes - - audio - - UIFileSharingEnabled - - UILaunchStoryboardName - SplashScreen - UIRequiredDeviceCapabilities - - arm64 - - UIRequiresFullScreen - - UIStatusBarStyle - UIStatusBarStyleDefault - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIUserInterfaceStyle - Dark - UIViewControllerBasedStatusBarAppearance - - - \ No newline at end of file + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Nuvio + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.2.5 + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleURLSchemes + + nuvio + com.nuvio.app + + + + CFBundleURLSchemes + + exp+nuvio + + + + CFBundleVersion + 20 + LSMinimumSystemVersion + 12.0 + LSRequiresIPhoneOS + + LSSupportsOpeningDocumentsInPlace + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSBonjourServices + + _http._tcp + + RCTNewArchEnabled + + RCTRootViewBackgroundColor + 4278322180 + UIBackgroundModes + + audio + fetch + + UIFileSharingEnabled + + UILaunchStoryboardName + SplashScreen + UIRequiredDeviceCapabilities + + arm64 + + UIRequiresFullScreen + + UIStatusBarStyle + UIStatusBarStyleDefault + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIUserInterfaceStyle + Dark + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/Nuvio/Nuvio.entitlements b/ios/Nuvio/Nuvio.entitlements index a0bc443f..0c67376e 100644 --- a/ios/Nuvio/Nuvio.entitlements +++ b/ios/Nuvio/Nuvio.entitlements @@ -1,10 +1,5 @@ - - aps-environment - development - com.apple.developer.associated-domains - - - \ No newline at end of file + + diff --git a/ios/Nuvio/NuvioRelease.entitlements b/ios/Nuvio/NuvioRelease.entitlements index a0bc443f..0c67376e 100644 --- a/ios/Nuvio/NuvioRelease.entitlements +++ b/ios/Nuvio/NuvioRelease.entitlements @@ -1,10 +1,5 @@ - - aps-environment - development - com.apple.developer.associated-domains - - - \ No newline at end of file + + diff --git a/package-lock.json b/package-lock.json index e3dfe3b2..060114ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@expo/metro-runtime": "~6.1.2", "@expo/vector-icons": "^15.0.2", "@gorhom/bottom-sheet": "^5.2.6", + "@legendapp/list": "^2.0.13", "@lottiefiles/dotlottie-react": "^0.6.5", "@react-native-async-storage/async-storage": "2.2.0", "@react-native-community/blur": "^4.4.1", @@ -80,7 +81,7 @@ "react-native-svg": "15.12.1", "react-native-url-polyfill": "^2.0.0", "react-native-vector-icons": "^10.3.0", - "react-native-video": "^6.12.0", + "react-native-video": "^6.17.0", "react-native-web": "^0.21.0", "react-native-wheel-color-picker": "^1.3.1", "react-native-worklets": "^0.6.1", @@ -2813,6 +2814,19 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@legendapp/list": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@legendapp/list/-/list-2.0.13.tgz", + "integrity": "sha512-OL9rvxRDDqiQ07+QhldcRqCX5+VihtXbbZaoey0TVWJqQN5XPh9b9Buefax3/HjNRzCaYTx1lCoeW5dz20j+cA==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/@lottiefiles/dotlottie-react": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-react/-/dotlottie-react-0.6.5.tgz", diff --git a/package.json b/package.json index 7cbcf2a0..86e82cab 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@expo/metro-runtime": "~6.1.2", "@expo/vector-icons": "^15.0.2", "@gorhom/bottom-sheet": "^5.2.6", + "@legendapp/list": "^2.0.13", "@lottiefiles/dotlottie-react": "^0.6.5", "@react-native-async-storage/async-storage": "2.2.0", "@react-native-community/blur": "^4.4.1", @@ -80,7 +81,7 @@ "react-native-svg": "15.12.1", "react-native-url-polyfill": "^2.0.0", "react-native-vector-icons": "^10.3.0", - "react-native-video": "^6.12.0", + "react-native-video": "^6.17.0", "react-native-web": "^0.21.0", "react-native-wheel-color-picker": "^1.3.1", "react-native-worklets": "^0.6.1", diff --git a/patches/react-native-video+6.17.0.patch b/patches/react-native-video+6.17.0.patch new file mode 100644 index 00000000..ca97b5a9 --- /dev/null +++ b/patches/react-native-video+6.17.0.patch @@ -0,0 +1,1467 @@ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/.transforms/cde462de23ae0e930ed29ed683a0d845/results.bin b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/.transforms/cde462de23ae0e930ed29ed683a0d845/results.bin +new file mode 100644 +index 0000000..0d259dd +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/.transforms/cde462de23ae0e930ed29ed683a0d845/results.bin +@@ -0,0 +1 @@ ++o/classes +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/.transforms/cde462de23ae0e930ed29ed683a0d845/transformed/classes/classes_dex/classes.dex b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/.transforms/cde462de23ae0e930ed29ed683a0d845/transformed/classes/classes_dex/classes.dex +new file mode 100644 +index 0000000..f27c56f +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/.transforms/cde462de23ae0e930ed29ed683a0d845/transformed/classes/classes_dex/classes.dex differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/generated/source/buildConfig/debug/com/brentvatne/react/BuildConfig.java b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/generated/source/buildConfig/debug/com/brentvatne/react/BuildConfig.java +new file mode 100644 +index 0000000..b26a50e +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/generated/source/buildConfig/debug/com/brentvatne/react/BuildConfig.java +@@ -0,0 +1,22 @@ ++/** ++ * Automatically generated file. DO NOT MODIFY ++ */ ++package com.brentvatne.react; ++ ++public final class BuildConfig { ++ public static final boolean DEBUG = Boolean.parseBoolean("true"); ++ public static final String LIBRARY_PACKAGE_NAME = "com.brentvatne.react"; ++ public static final String BUILD_TYPE = "debug"; ++ // Field from default config. ++ public static final boolean IS_NEW_ARCHITECTURE_ENABLED = true; ++ // Field from default config. ++ public static final boolean USE_EXOPLAYER_DASH = true; ++ // Field from default config. ++ public static final boolean USE_EXOPLAYER_HLS = true; ++ // Field from default config. ++ public static final boolean USE_EXOPLAYER_IMA = false; ++ // Field from default config. ++ public static final boolean USE_EXOPLAYER_RTSP = false; ++ // Field from default config. ++ public static final boolean USE_EXOPLAYER_SMOOTH_STREAMING = true; ++} +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +new file mode 100644 +index 0000000..728c5a9 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +@@ -0,0 +1,7 @@ ++ ++ ++ ++ ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +new file mode 100644 +index 0000000..247891c +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +@@ -0,0 +1,18 @@ ++{ ++ "version": 3, ++ "artifactType": { ++ "type": "AAPT_FRIENDLY_MERGED_MANIFESTS", ++ "kind": "Directory" ++ }, ++ "applicationId": "com.brentvatne.react", ++ "variantName": "debug", ++ "elements": [ ++ { ++ "type": "SINGLE", ++ "filters": [], ++ "attributes": [], ++ "outputFile": "AndroidManifest.xml" ++ } ++ ], ++ "elementType": "File" ++} +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aar_main_jar/debug/syncDebugLibJars/classes.jar b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aar_main_jar/debug/syncDebugLibJars/classes.jar +new file mode 100644 +index 0000000..1f4ce80 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aar_main_jar/debug/syncDebugLibJars/classes.jar differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +new file mode 100644 +index 0000000..1211b1e +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +@@ -0,0 +1,6 @@ ++aarFormatVersion=1.0 ++aarMetadataVersion=1.0 ++minCompileSdk=1 ++minCompileSdkExtension=0 ++minAndroidGradlePluginVersion=1.0.0 ++coreLibraryDesugaringEnabled=false +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +new file mode 100644 +index 0000000..9e26dfe +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +@@ -0,0 +1 @@ ++{} +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/annotations_typedef_file/debug/extractDebugAnnotations/typedefs.txt b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/annotations_typedef_file/debug/extractDebugAnnotations/typedefs.txt +new file mode 100644 +index 0000000..e69de29 +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +new file mode 100644 +index 0000000..9ec2b04 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +new file mode 100644 +index 0000000..0889def +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +new file mode 100644 +index 0000000..b5a67e1 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +@@ -0,0 +1,44 @@ ++int color player_overlay_color 0x0 ++int color red 0x0 ++int color silver_gray 0x0 ++int color white 0x0 ++int dimen controller_wrapper_padding_top 0x0 ++int dimen full_screen_margin 0x0 ++int dimen full_screen_size 0x0 ++int dimen live_wrapper_margin_top 0x0 ++int dimen position_duration_horizontal_padding 0x0 ++int dimen position_duration_text_size 0x0 ++int dimen position_duration_width 0x0 ++int dimen seekBar_height 0x0 ++int dimen seekBar_wrapper_margin_top 0x0 ++int drawable circle 0x0 ++int id exo_duration 0x0 ++int id exo_ffwd 0x0 ++int id exo_fullscreen 0x0 ++int id exo_live_container 0x0 ++int id exo_live_icon 0x0 ++int id exo_live_label 0x0 ++int id exo_next 0x0 ++int id exo_pause 0x0 ++int id exo_play 0x0 ++int id exo_play_pause_container 0x0 ++int id exo_position 0x0 ++int id exo_prev 0x0 ++int id exo_progress 0x0 ++int id exo_rew 0x0 ++int id exo_settings 0x0 ++int layout exo_legacy_player_control_view 0x0 ++int string error_drm_not_supported 0x0 ++int string error_drm_unknown 0x0 ++int string error_drm_unsupported_scheme 0x0 ++int string error_instantiating_decoder 0x0 ++int string error_no_decoder 0x0 ++int string error_no_secure_decoder 0x0 ++int string error_querying_decoders 0x0 ++int string media_playback_notification_text 0x0 ++int string media_playback_notification_title 0x0 ++int string playback_speed 0x0 ++int string select_playback_speed 0x0 ++int string settings 0x0 ++int string unrecognized_media_format 0x0 ++int style ExoMediaButton_FullScreen 0x0 +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/drawable_circle.xml.flat b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/drawable_circle.xml.flat +new file mode 100644 +index 0000000..e62758d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/drawable_circle.xml.flat differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/layout_exo_legacy_player_control_view.xml.flat b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/layout_exo_legacy_player_control_view.xml.flat +new file mode 100644 +index 0000000..bb5b5f9 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/layout_exo_legacy_player_control_view.xml.flat differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug-mergeJavaRes/merge-state b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug-mergeJavaRes/merge-state +new file mode 100644 +index 0000000..441a1d2 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug-mergeJavaRes/merge-state differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +new file mode 100644 +index 0000000..842471c +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +@@ -0,0 +1,3 @@ ++#Thu Oct 16 20:19:39 IST 2025 ++com.brentvatne.react.react-native-video-main-6\:/drawable/circle.xml=/Users/nayifnoushad/Documents/Projects/NuvioStreaming/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/packaged_res/debug/packageDebugResources/drawable/circle.xml ++com.brentvatne.react.react-native-video-main-6\:/layout/exo_legacy_player_control_view.xml=/Users/nayifnoushad/Documents/Projects/NuvioStreaming/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/packaged_res/debug/packageDebugResources/layout/exo_legacy_player_control_view.xml +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug/packageDebugResources/merged.dir/values/values.xml b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug/packageDebugResources/merged.dir/values/values.xml +new file mode 100644 +index 0000000..e8dd9e4 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug/packageDebugResources/merged.dir/values/values.xml +@@ -0,0 +1,33 @@ ++ ++ ++ #00000000 ++ #FF0000 ++ #FFBEBEBE ++ #FFFFFF ++ 4dp ++ 4dp ++ 30dp ++ 12dp ++ 4dp ++ 14sp ++ 50dp ++ 26dp ++ 4dp ++ Protected content not supported on API levels below 18 ++ An unknown DRM error occurred ++ This device does not support the required DRM scheme ++ Unable to instantiate decoder %1$s ++ This device does not provide a decoder for %1$s ++ This device does not provide a secure decoder for %1$s ++ Unable to query device decoders ++ Preparing playback ++ Media playback ++ Playback Speed ++ Select Playback Speed ++ Settings ++ Unrecognized media format ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug/packageDebugResources/merger.xml b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug/packageDebugResources/merger.xml +new file mode 100644 +index 0000000..55ffc6b +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/debug/packageDebugResources/merger.xml +@@ -0,0 +1,5 @@ ++ ++#FFBEBEBE#00000000#FFFFFF#FF00004dp4dp12dp4dp4dp50dp26dp30dp14spThis device does not provide a decoder for %1$sThis device does not provide a secure decoder for %1$sUnable to query device decodersUnable to instantiate decoder %1$sProtected content not supported on API levels below 18Unrecognized media formatThis device does not support the required DRM schemeAn unknown DRM error occurredSettingsPlayback SpeedSelect Playback SpeedMedia playbackPreparing playback +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/mergeDebugAssets/merger.xml b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/mergeDebugAssets/merger.xml +new file mode 100644 +index 0000000..8769311 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/mergeDebugAssets/merger.xml +@@ -0,0 +1,2 @@ ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/mergeDebugJniLibFolders/merger.xml b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +new file mode 100644 +index 0000000..af687a7 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +@@ -0,0 +1,2 @@ ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/mergeDebugShaders/merger.xml b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/mergeDebugShaders/merger.xml +new file mode 100644 +index 0000000..65138a3 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/incremental/mergeDebugShaders/merger.xml +@@ -0,0 +1,2 @@ ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/react-native-video_debug.kotlin_module b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/react-native-video_debug.kotlin_module +new file mode 100644 +index 0000000..1698483 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/react-native-video_debug.kotlin_module differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/ima/ImaAdsLoader$Builder.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/ima/ImaAdsLoader$Builder.class +new file mode 100644 +index 0000000..b019110 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/ima/ImaAdsLoader$Builder.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/ima/ImaAdsLoader.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/ima/ImaAdsLoader.class +new file mode 100644 +index 0000000..5e16e53 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/ima/ImaAdsLoader.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/rtsp/RtspMediaSource$Factory.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/rtsp/RtspMediaSource$Factory.class +new file mode 100644 +index 0000000..b08faeb +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/rtsp/RtspMediaSource$Factory.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/rtsp/RtspMediaSource.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/rtsp/RtspMediaSource.class +new file mode 100644 +index 0000000..2f92e20 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/androidx/media3/exoplayer/rtsp/RtspMediaSource.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$1.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$1.class +new file mode 100644 +index 0000000..a1368f5 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$1.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$2.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$2.class +new file mode 100644 +index 0000000..ec7b745 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$2.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$3.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$3.class +new file mode 100644 +index 0000000..598654a +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$3.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$4.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$4.class +new file mode 100644 +index 0000000..803aefe +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$4.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$OnAudioFocusChangedListener.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$OnAudioFocusChangedListener.class +new file mode 100644 +index 0000000..6ec4ad1 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$OnAudioFocusChangedListener.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$RNVLoadControl.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$RNVLoadControl.class +new file mode 100644 +index 0000000..22d8796 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView$RNVLoadControl.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView.class +new file mode 100644 +index 0000000..53eee7f +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/exoplayer/ReactExoplayerView.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/react/BuildConfig.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/react/BuildConfig.class +new file mode 100644 +index 0000000..4c5c87e +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/brentvatne/react/BuildConfig.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdError.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdError.class +new file mode 100644 +index 0000000..0a9b7a7 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdError.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdErrorEvent$AdErrorListener.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdErrorEvent$AdErrorListener.class +new file mode 100644 +index 0000000..1380a05 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdErrorEvent$AdErrorListener.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdErrorEvent.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdErrorEvent.class +new file mode 100644 +index 0000000..07ab3fa +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdErrorEvent.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdEvent$AdEventListener.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdEvent$AdEventListener.class +new file mode 100644 +index 0000000..dbe9984 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdEvent$AdEventListener.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdEvent.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdEvent.class +new file mode 100644 +index 0000000..88ae34c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/AdEvent.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ConcreteImaSdkFactory.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ConcreteImaSdkFactory.class +new file mode 100644 +index 0000000..a3184b3 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ConcreteImaSdkFactory.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ConcreteImaSdkSettings.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ConcreteImaSdkSettings.class +new file mode 100644 +index 0000000..264cd83 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ConcreteImaSdkSettings.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ImaSdkFactory.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ImaSdkFactory.class +new file mode 100644 +index 0000000..46cea81 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ImaSdkFactory.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ImaSdkSettings.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ImaSdkSettings.class +new file mode 100644 +index 0000000..a4cef0d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/google/ads/interactivemedia/v3/api/ImaSdkSettings.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +new file mode 100644 +index 0000000..987e479 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +@@ -0,0 +1,46 @@ ++R_DEF: Internal format may change without notice ++local ++color player_overlay_color ++color red ++color silver_gray ++color white ++dimen controller_wrapper_padding_top ++dimen full_screen_margin ++dimen full_screen_size ++dimen live_wrapper_margin_top ++dimen position_duration_horizontal_padding ++dimen position_duration_text_size ++dimen position_duration_width ++dimen seekBar_height ++dimen seekBar_wrapper_margin_top ++drawable circle ++id exo_duration ++id exo_ffwd ++id exo_fullscreen ++id exo_live_container ++id exo_live_icon ++id exo_live_label ++id exo_next ++id exo_pause ++id exo_play ++id exo_play_pause_container ++id exo_position ++id exo_prev ++id exo_progress ++id exo_rew ++id exo_settings ++layout exo_legacy_player_control_view ++string error_drm_not_supported ++string error_drm_unknown ++string error_drm_unsupported_scheme ++string error_instantiating_decoder ++string error_no_decoder ++string error_no_secure_decoder ++string error_querying_decoders ++string media_playback_notification_text ++string media_playback_notification_title ++string playback_speed ++string select_playback_speed ++string settings ++string unrecognized_media_format ++style ExoMediaButton.FullScreen +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +new file mode 100644 +index 0000000..2300097 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +@@ -0,0 +1,7 @@ ++1 ++2 ++4 ++5 ++6 ++7 +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/merged_java_res/debug/mergeDebugJavaResource/feature-react-native-video.jar b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/merged_java_res/debug/mergeDebugJavaResource/feature-react-native-video.jar +new file mode 100644 +index 0000000..87d384d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/merged_java_res/debug/mergeDebugJavaResource/feature-react-native-video.jar differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +new file mode 100644 +index 0000000..728c5a9 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +@@ -0,0 +1,7 @@ ++ ++ ++ ++ ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +new file mode 100644 +index 0000000..0637a08 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +@@ -0,0 +1 @@ ++[] +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +new file mode 100644 +index 0000000..08f4ebe +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +@@ -0,0 +1 @@ ++0 Warning/Error +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/packaged_res/debug/packageDebugResources/drawable/circle.xml b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/packaged_res/debug/packageDebugResources/drawable/circle.xml +new file mode 100644 +index 0000000..9f06d7c +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/packaged_res/debug/packageDebugResources/drawable/circle.xml +@@ -0,0 +1,6 @@ ++ ++ ++ ++ ++ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/packaged_res/debug/packageDebugResources/layout/exo_legacy_player_control_view.xml b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/packaged_res/debug/packageDebugResources/layout/exo_legacy_player_control_view.xml +new file mode 100644 +index 0000000..e0babc4 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/packaged_res/debug/packageDebugResources/layout/exo_legacy_player_control_view.xml +@@ -0,0 +1,120 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/packaged_res/debug/packageDebugResources/values/values.xml b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/packaged_res/debug/packageDebugResources/values/values.xml +new file mode 100644 +index 0000000..e8dd9e4 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/packaged_res/debug/packageDebugResources/values/values.xml +@@ -0,0 +1,33 @@ ++ ++ ++ #00000000 ++ #FF0000 ++ #FFBEBEBE ++ #FFFFFF ++ 4dp ++ 4dp ++ 30dp ++ 12dp ++ 4dp ++ 14sp ++ 50dp ++ 26dp ++ 4dp ++ Protected content not supported on API levels below 18 ++ An unknown DRM error occurred ++ This device does not support the required DRM scheme ++ Unable to instantiate decoder %1$s ++ This device does not provide a decoder for %1$s ++ This device does not provide a secure decoder for %1$s ++ Unable to query device decoders ++ Preparing playback ++ Media playback ++ Playback Speed ++ Select Playback Speed ++ Settings ++ Unrecognized media format ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +new file mode 100644 +index 0000000..e65b062 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +new file mode 100644 +index 0000000..1cb95ed +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +@@ -0,0 +1,45 @@ ++com.brentvatne.react ++color player_overlay_color ++color red ++color silver_gray ++color white ++dimen controller_wrapper_padding_top ++dimen full_screen_margin ++dimen full_screen_size ++dimen live_wrapper_margin_top ++dimen position_duration_horizontal_padding ++dimen position_duration_text_size ++dimen position_duration_width ++dimen seekBar_height ++dimen seekBar_wrapper_margin_top ++drawable circle ++id exo_duration ++id exo_ffwd ++id exo_fullscreen ++id exo_live_container ++id exo_live_icon ++id exo_live_label ++id exo_next ++id exo_pause ++id exo_play ++id exo_play_pause_container ++id exo_position ++id exo_prev ++id exo_progress ++id exo_rew ++id exo_settings ++layout exo_legacy_player_control_view ++string error_drm_not_supported ++string error_drm_unknown ++string error_drm_unsupported_scheme ++string error_instantiating_decoder ++string error_no_decoder ++string error_no_secure_decoder ++string error_querying_decoders ++string media_playback_notification_text ++string media_playback_notification_title ++string playback_speed ++string select_playback_speed ++string settings ++string unrecognized_media_format ++style ExoMediaButton_FullScreen +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +new file mode 100644 +index 0000000..7df5bcf +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +new file mode 100644 +index 0000000..1a55594 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +new file mode 100644 +index 0000000..74ddf64 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +new file mode 100644 +index 0000000..41d6c24 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +new file mode 100644 +index 0000000..d0eda54 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +new file mode 100644 +index 0000000..8a80b7d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +new file mode 100644 +index 0000000..532458c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +new file mode 100644 +index 0000000..1d1d548 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +new file mode 100644 +index 0000000..3247724 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +new file mode 100644 +index 0000000..bba171d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +new file mode 100644 +index 0000000..5d6b64a +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +new file mode 100644 +index 0000000..045022c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +new file mode 100644 +index 0000000..8178530 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +new file mode 100644 +index 0000000..1d1d548 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +new file mode 100644 +index 0000000..3247724 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +new file mode 100644 +index 0000000..bba171d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +new file mode 100644 +index 0000000..6a45a65 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +new file mode 100644 +index 0000000..045022c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +new file mode 100644 +index 0000000..496bda2 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream +new file mode 100644 +index 0000000..a49789c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len +new file mode 100644 +index 0000000..a3d0573 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len +new file mode 100644 +index 0000000..93a595b +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +new file mode 100644 +index 0000000..9d91003 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i +new file mode 100644 +index 0000000..1598ef3 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +new file mode 100644 +index 0000000..c3975e3 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +new file mode 100644 +index 0000000..9d05b9a +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +new file mode 100644 +index 0000000..d3e09af +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +new file mode 100644 +index 0000000..b7d7395 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +new file mode 100644 +index 0000000..e3911a1 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +new file mode 100644 +index 0000000..af27d9c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab +new file mode 100644 +index 0000000..bdf584a +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream +new file mode 100644 +index 0000000..a9e6823 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream.len +new file mode 100644 +index 0000000..de8bf97 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.len +new file mode 100644 +index 0000000..2a17e6e +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at +new file mode 100644 +index 0000000..46d6744 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i +new file mode 100644 +index 0000000..2073982 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +new file mode 100644 +index 0000000..c626f49 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +new file mode 100644 +index 0000000..7214377 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +new file mode 100644 +index 0000000..86b154b +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +new file mode 100644 +index 0000000..882f24f +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values +new file mode 100644 +index 0000000..2ff3eb7 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +new file mode 100644 +index 0000000..af661f7 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.s b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.s +new file mode 100644 +index 0000000..b6551b9 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.s +@@ -0,0 +1 @@ ++ÏÒ +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +new file mode 100644 +index 0000000..0cbafa1 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +new file mode 100644 +index 0000000..85d9216 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +new file mode 100644 +index 0000000..1a55594 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +new file mode 100644 +index 0000000..74ddf64 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +new file mode 100644 +index 0000000..41d6c24 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +new file mode 100644 +index 0000000..dfc60fb +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +new file mode 100644 +index 0000000..8a80b7d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +new file mode 100644 +index 0000000..95c2c01 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +new file mode 100644 +index 0000000..90b21c4 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +new file mode 100644 +index 0000000..4cb813c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +new file mode 100644 +index 0000000..385642d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +new file mode 100644 +index 0000000..195d865 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +new file mode 100644 +index 0000000..5e4a0c0 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +new file mode 100644 +index 0000000..d98dace +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +new file mode 100644 +index 0000000..ae4ac93 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +new file mode 100644 +index 0000000..6dc1435 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +new file mode 100644 +index 0000000..42df8b9 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +new file mode 100644 +index 0000000..bc345c6 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +new file mode 100644 +index 0000000..f0c9463 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +new file mode 100644 +index 0000000..672070d +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +@@ -0,0 +1,2 @@ ++44 ++0 +\ No newline at end of file +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +new file mode 100644 +index 0000000..1878d5a +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +new file mode 100644 +index 0000000..1a55594 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +new file mode 100644 +index 0000000..74ddf64 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +new file mode 100644 +index 0000000..41d6c24 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +new file mode 100644 +index 0000000..d3fcc7e +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +new file mode 100644 +index 0000000..8a80b7d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +new file mode 100644 +index 0000000..04aeda4 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +new file mode 100644 +index 0000000..132a271 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +new file mode 100644 +index 0000000..79ad34c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +new file mode 100644 +index 0000000..41d6c24 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +new file mode 100644 +index 0000000..c834290 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +new file mode 100644 +index 0000000..1601c02 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +new file mode 100644 +index 0000000..5fc703e +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +new file mode 100644 +index 0000000..39f4cac +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +new file mode 100644 +index 0000000..e381b23 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +new file mode 100644 +index 0000000..35ed991 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +new file mode 100644 +index 0000000..a262c4a +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +new file mode 100644 +index 0000000..1bfa622 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +new file mode 100644 +index 0000000..131e265 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/last-build.bin b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/last-build.bin +new file mode 100644 +index 0000000..1fe138d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/cacheable/last-build.bin differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +new file mode 100644 +index 0000000..fb7ec91 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/outputs/aar/react-native-video-debug.aar b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/outputs/aar/react-native-video-debug.aar +new file mode 100644 +index 0000000..a704fe4 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/outputs/aar/react-native-video-debug.aar differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/outputs/logs/manifest-merger-debug-report.txt b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/outputs/logs/manifest-merger-debug-report.txt +new file mode 100644 +index 0000000..a388215 +--- /dev/null ++++ b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/outputs/logs/manifest-merger-debug-report.txt +@@ -0,0 +1,16 @@ ++-- Merging decision tree log --- ++manifest ++ADDED from /Users/nayifnoushad/Documents/Projects/NuvioStreaming/node_modules/react-native-video/android/src/main/AndroidManifestNew.xml:1:1-2:12 ++INJECTED from /Users/nayifnoushad/Documents/Projects/NuvioStreaming/node_modules/react-native-video/android/src/main/AndroidManifestNew.xml:1:1-2:12 ++ package ++ INJECTED from /Users/nayifnoushad/Documents/Projects/NuvioStreaming/node_modules/react-native-video/android/src/main/AndroidManifestNew.xml ++ xmlns:android ++ ADDED from /Users/nayifnoushad/Documents/Projects/NuvioStreaming/node_modules/react-native-video/android/src/main/AndroidManifestNew.xml:1:11-69 ++uses-sdk ++INJECTED from /Users/nayifnoushad/Documents/Projects/NuvioStreaming/node_modules/react-native-video/android/src/main/AndroidManifestNew.xml reason: use-sdk injection requested ++INJECTED from /Users/nayifnoushad/Documents/Projects/NuvioStreaming/node_modules/react-native-video/android/src/main/AndroidManifestNew.xml ++INJECTED from /Users/nayifnoushad/Documents/Projects/NuvioStreaming/node_modules/react-native-video/android/src/main/AndroidManifestNew.xml ++ android:targetSdkVersion ++ INJECTED from /Users/nayifnoushad/Documents/Projects/NuvioStreaming/node_modules/react-native-video/android/src/main/AndroidManifestNew.xml ++ android:minSdkVersion ++ INJECTED from /Users/nayifnoushad/Documents/Projects/NuvioStreaming/node_modules/react-native-video/android/src/main/AndroidManifestNew.xml +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +new file mode 100644 +index 0000000..b63c0e3 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/META-INF/react-native-video_debug.kotlin_module b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/META-INF/react-native-video_debug.kotlin_module +new file mode 100644 +index 0000000..1698483 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/META-INF/react-native-video_debug.kotlin_module differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/AdsProps$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/AdsProps$Companion.class +new file mode 100644 +index 0000000..2e5d42b +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/AdsProps$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/AdsProps.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/AdsProps.class +new file mode 100644 +index 0000000..e2b54bd +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/AdsProps.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig$Companion.class +new file mode 100644 +index 0000000..0fbaa90 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig$Live$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig$Live$Companion.class +new file mode 100644 +index 0000000..ce1128e +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig$Live$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig$Live.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig$Live.class +new file mode 100644 +index 0000000..2054200 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig$Live.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig.class +new file mode 100644 +index 0000000..7ef226b +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferConfig.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferingStrategy$BufferingStrategyEnum.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferingStrategy$BufferingStrategyEnum.class +new file mode 100644 +index 0000000..162566c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferingStrategy$BufferingStrategyEnum.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferingStrategy$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferingStrategy$Companion.class +new file mode 100644 +index 0000000..7477be8 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferingStrategy$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferingStrategy.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferingStrategy.class +new file mode 100644 +index 0000000..3516405 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/BufferingStrategy.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/CMCDProps$Companion$WhenMappings.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/CMCDProps$Companion$WhenMappings.class +new file mode 100644 +index 0000000..5145552 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/CMCDProps$Companion$WhenMappings.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/CMCDProps$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/CMCDProps$Companion.class +new file mode 100644 +index 0000000..e813d1a +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/CMCDProps$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/CMCDProps.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/CMCDProps.class +new file mode 100644 +index 0000000..e6c0538 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/CMCDProps.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ControlsConfig$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ControlsConfig$Companion.class +new file mode 100644 +index 0000000..b2e5cfc +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ControlsConfig$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ControlsConfig.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ControlsConfig.class +new file mode 100644 +index 0000000..a672b48 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ControlsConfig.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/DRMProps$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/DRMProps$Companion.class +new file mode 100644 +index 0000000..949a5b9 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/DRMProps$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/DRMProps.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/DRMProps.class +new file mode 100644 +index 0000000..8e26a44 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/DRMProps.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ResizeMode$Mode.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ResizeMode$Mode.class +new file mode 100644 +index 0000000..8c2948d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ResizeMode$Mode.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ResizeMode.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ResizeMode.class +new file mode 100644 +index 0000000..ab7c203 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ResizeMode.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrack$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrack$Companion.class +new file mode 100644 +index 0000000..3262de8 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrack$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrack.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrack.class +new file mode 100644 +index 0000000..a6b7907 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrack.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrackList$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrackList$Companion.class +new file mode 100644 +index 0000000..a41fe7d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrackList$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrackList.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrackList.class +new file mode 100644 +index 0000000..ec0f170 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SideLoadedTextTrackList.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source$Companion.class +new file mode 100644 +index 0000000..20c7316 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source$Metadata$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source$Metadata$Companion.class +new file mode 100644 +index 0000000..3a83d08 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source$Metadata$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source$Metadata.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source$Metadata.class +new file mode 100644 +index 0000000..381c5ea +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source$Metadata.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source.class +new file mode 100644 +index 0000000..763511c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Source.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SubtitleStyle$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SubtitleStyle$Companion.class +new file mode 100644 +index 0000000..1ef82f1 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SubtitleStyle$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SubtitleStyle.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SubtitleStyle.class +new file mode 100644 +index 0000000..4ebb38c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/SubtitleStyle.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/TimedMetadata.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/TimedMetadata.class +new file mode 100644 +index 0000000..81dc3f7 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/TimedMetadata.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Track.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Track.class +new file mode 100644 +index 0000000..bf9687d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/Track.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/VideoTrack.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/VideoTrack.class +new file mode 100644 +index 0000000..a011166 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/VideoTrack.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ViewType$ViewType.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ViewType$ViewType.class +new file mode 100644 +index 0000000..2dfe0a5 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ViewType$ViewType.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ViewType.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ViewType.class +new file mode 100644 +index 0000000..24c319c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/api/ViewType.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/EventTypes$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/EventTypes$Companion.class +new file mode 100644 +index 0000000..7c1c2f6 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/EventTypes$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/EventTypes.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/EventTypes.class +new file mode 100644 +index 0000000..68c48f1 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/EventTypes.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/VideoEventEmitter$EventBuilder.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/VideoEventEmitter$EventBuilder.class +new file mode 100644 +index 0000000..0dceebe +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/VideoEventEmitter$EventBuilder.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/VideoEventEmitter$VideoCustomEvent.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/VideoEventEmitter$VideoCustomEvent.class +new file mode 100644 +index 0000000..6116962 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/VideoEventEmitter$VideoCustomEvent.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/VideoEventEmitter.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/VideoEventEmitter.class +new file mode 100644 +index 0000000..1f63a29 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/react/VideoEventEmitter.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/toolbox/DebugLog.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/toolbox/DebugLog.class +new file mode 100644 +index 0000000..35fd981 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/toolbox/DebugLog.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/toolbox/ReactBridgeUtils.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/toolbox/ReactBridgeUtils.class +new file mode 100644 +index 0000000..5b3a99d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/common/toolbox/ReactBridgeUtils.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AspectRatioFrameLayout$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AspectRatioFrameLayout$Companion.class +new file mode 100644 +index 0000000..e1e118c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AspectRatioFrameLayout$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AspectRatioFrameLayout.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AspectRatioFrameLayout.class +new file mode 100644 +index 0000000..8955650 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AspectRatioFrameLayout.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AudioOutput$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AudioOutput$Companion.class +new file mode 100644 +index 0000000..fdbd8c4 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AudioOutput$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AudioOutput.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AudioOutput.class +new file mode 100644 +index 0000000..49bd1a1 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/AudioOutput.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/CMCDConfig$createCmcdConfiguration$1.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/CMCDConfig$createCmcdConfiguration$1.class +new file mode 100644 +index 0000000..1b9ff2b +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/CMCDConfig$createCmcdConfiguration$1.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/CMCDConfig.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/CMCDConfig.class +new file mode 100644 +index 0000000..24ff469 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/CMCDConfig.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ConfigurationUtils.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ConfigurationUtils.class +new file mode 100644 +index 0000000..8623659 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ConfigurationUtils.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DRMManager.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DRMManager.class +new file mode 100644 +index 0000000..c054558 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DRMManager.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DRMManagerSpec.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DRMManagerSpec.class +new file mode 100644 +index 0000000..3ba0b21 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DRMManagerSpec.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DataSourceUtil.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DataSourceUtil.class +new file mode 100644 +index 0000000..435095f +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DataSourceUtil.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DefaultReactExoplayerConfig.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DefaultReactExoplayerConfig.class +new file mode 100644 +index 0000000..7d79368 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/DefaultReactExoplayerConfig.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ExoPlayerView$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ExoPlayerView$Companion.class +new file mode 100644 +index 0000000..345dd50 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ExoPlayerView$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ExoPlayerView$playerListener$1.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ExoPlayerView$playerListener$1.class +new file mode 100644 +index 0000000..4dcc80e +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ExoPlayerView$playerListener$1.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ExoPlayerView.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ExoPlayerView.class +new file mode 100644 +index 0000000..df0ace7 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ExoPlayerView.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/FullScreenPlayerView$KeepScreenOnUpdater$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/FullScreenPlayerView$KeepScreenOnUpdater$Companion.class +new file mode 100644 +index 0000000..8bcae8d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/FullScreenPlayerView$KeepScreenOnUpdater$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/FullScreenPlayerView$KeepScreenOnUpdater.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/FullScreenPlayerView$KeepScreenOnUpdater.class +new file mode 100644 +index 0000000..550135d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/FullScreenPlayerView$KeepScreenOnUpdater.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/FullScreenPlayerView.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/FullScreenPlayerView.class +new file mode 100644 +index 0000000..257de83 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/FullScreenPlayerView.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/PictureInPictureUtil.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/PictureInPictureUtil.class +new file mode 100644 +index 0000000..9e8c1b9 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/PictureInPictureUtil.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/PictureInPictureUtilKt.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/PictureInPictureUtilKt.class +new file mode 100644 +index 0000000..2c42f4a +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/PictureInPictureUtilKt.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/PlaybackServiceBinder.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/PlaybackServiceBinder.class +new file mode 100644 +index 0000000..5ae25b4 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/PlaybackServiceBinder.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/RNVExoplayerPlugin$DefaultImpls.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/RNVExoplayerPlugin$DefaultImpls.class +new file mode 100644 +index 0000000..af3decf +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/RNVExoplayerPlugin$DefaultImpls.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/RNVExoplayerPlugin.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/RNVExoplayerPlugin.class +new file mode 100644 +index 0000000..9bc6115 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/RNVExoplayerPlugin.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/RNVSimpleCache.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/RNVSimpleCache.class +new file mode 100644 +index 0000000..659e439 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/RNVSimpleCache.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerConfig.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerConfig.class +new file mode 100644 +index 0000000..2456c95 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerConfig.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerLoadErrorHandlingPolicy.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerLoadErrorHandlingPolicy.class +new file mode 100644 +index 0000000..38ce458 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerLoadErrorHandlingPolicy.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerViewManager$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerViewManager$Companion.class +new file mode 100644 +index 0000000..bc906a9 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerViewManager$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerViewManager.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerViewManager.class +new file mode 100644 +index 0000000..07bd865 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/ReactExoplayerViewManager.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackCallback.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackCallback.class +new file mode 100644 +index 0000000..5e67aa0 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackCallback.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService$Companion$COMMAND.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService$Companion$COMMAND.class +new file mode 100644 +index 0000000..6ba65f2 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService$Companion$COMMAND.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService$Companion$WhenMappings.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService$Companion$WhenMappings.class +new file mode 100644 +index 0000000..647f782 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService$Companion$WhenMappings.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService$Companion.class +new file mode 100644 +index 0000000..0f20e85 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService.class +new file mode 100644 +index 0000000..8a576c2 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/exoplayer/VideoPlaybackService.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/RNVPlugin.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/RNVPlugin.class +new file mode 100644 +index 0000000..8a59f22 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/RNVPlugin.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/ReactNativeVideoManager$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/ReactNativeVideoManager$Companion.class +new file mode 100644 +index 0000000..32d6d1f +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/ReactNativeVideoManager$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/ReactNativeVideoManager.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/ReactNativeVideoManager.class +new file mode 100644 +index 0000000..2679ae0 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/ReactNativeVideoManager.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/ReactVideoPackage.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/ReactVideoPackage.class +new file mode 100644 +index 0000000..2af2d2c +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/ReactVideoPackage.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoDecoderInfoModule$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoDecoderInfoModule$Companion.class +new file mode 100644 +index 0000000..d8a4aa3 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoDecoderInfoModule$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoDecoderInfoModule.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoDecoderInfoModule.class +new file mode 100644 +index 0000000..8348d9d +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoDecoderInfoModule.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoManagerModule$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoManagerModule$Companion.class +new file mode 100644 +index 0000000..435293b +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoManagerModule$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoManagerModule.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoManagerModule.class +new file mode 100644 +index 0000000..c28e02b +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/react/VideoManagerModule.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/AudioBecomingNoisyReceiver.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/AudioBecomingNoisyReceiver.class +new file mode 100644 +index 0000000..990ca48 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/AudioBecomingNoisyReceiver.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/BecomingNoisyListener$Companion$NO_OP$1.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/BecomingNoisyListener$Companion$NO_OP$1.class +new file mode 100644 +index 0000000..07a503b +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/BecomingNoisyListener$Companion$NO_OP$1.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/BecomingNoisyListener$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/BecomingNoisyListener$Companion.class +new file mode 100644 +index 0000000..efa3ee3 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/BecomingNoisyListener$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/BecomingNoisyListener.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/BecomingNoisyListener.class +new file mode 100644 +index 0000000..75d1cd4 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/BecomingNoisyListener.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/PictureInPictureReceiver$Companion.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/PictureInPictureReceiver$Companion.class +new file mode 100644 +index 0000000..535aad5 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/PictureInPictureReceiver$Companion.class differ +diff --git a/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/PictureInPictureReceiver.class b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/PictureInPictureReceiver.class +new file mode 100644 +index 0000000..0143f64 +Binary files /dev/null and b/node_modules/react-native-video/android/buildOutput_a15d4dee7fc4eda61b91308cbb6a2e72/tmp/kotlin-classes/debug/com/brentvatne/receiver/PictureInPictureReceiver.class differ +diff --git a/node_modules/react-native-video/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/node_modules/react-native-video/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +index f175dec..87e436a 100644 +--- a/node_modules/react-native-video/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java ++++ b/node_modules/react-native-video/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +@@ -726,7 +726,7 @@ public class ReactExoplayerView extends FrameLayout implements + + DefaultRenderersFactory renderersFactory = + new DefaultRenderersFactory(getContext()) +- .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF) ++ .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER) + .setEnableDecoderFallback(true) + .forceEnableMediaCodecAsynchronousQueueing(); + diff --git a/src/components/home/CatalogSection.tsx b/src/components/home/CatalogSection.tsx index 77fd6af2..7639a9f0 100644 --- a/src/components/home/CatalogSection.tsx +++ b/src/components/home/CatalogSection.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useMemo, useRef } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, Platform, Dimensions } from 'react-native'; -import { FlashList } from '@shopify/flash-list'; +import { LegendList } from '@legendapp/list'; import { NavigationProp, useNavigation } from '@react-navigation/native'; import { MaterialIcons } from '@expo/vector-icons'; import { LinearGradient } from 'expo-linear-gradient'; @@ -98,7 +98,7 @@ const CatalogSection = ({ catalog }: CatalogSectionProps) => { - { ItemSeparatorComponent={ItemSeparator} onEndReachedThreshold={0.7} onEndReached={() => {}} - scrollEventThrottle={64} - removeClippedSubviews={true} + recycleItems={true} + maintainVisibleContentPosition /> ); diff --git a/src/components/metadata/TrailerModal.tsx b/src/components/metadata/TrailerModal.tsx index 1c116574..c18e131e 100644 --- a/src/components/metadata/TrailerModal.tsx +++ b/src/components/metadata/TrailerModal.tsx @@ -310,11 +310,6 @@ const TrailerModal: React.FC = memo(({ {contentTitle} - - - {trailer.size}p HD - - diff --git a/src/components/metadata/TrailersSection.tsx b/src/components/metadata/TrailersSection.tsx index fffa5906..c059a59a 100644 --- a/src/components/metadata/TrailersSection.tsx +++ b/src/components/metadata/TrailersSection.tsx @@ -570,12 +570,6 @@ const TrailersSection: React.FC = memo(({ /> {/* Subtle Gradient Overlay */} - {/* Quality Badge */} - - - {trailer.size}p - - {/* Trailer Info */} @@ -797,21 +791,6 @@ const styles = StyleSheet.create({ }, - // Badges - qualityBadge: { - position: 'absolute', - bottom: 8, - right: 8, - backgroundColor: 'rgba(0,0,0,0.8)', - paddingHorizontal: 6, - paddingVertical: 2, - borderRadius: 8, - }, - qualityText: { - color: '#fff', - fontSize: 10, - fontWeight: '600', - }, // Trailer Info Styles trailerInfo: { diff --git a/src/screens/HomeScreen.tsx b/src/screens/HomeScreen.tsx index d3784e4d..ca1c5967 100644 --- a/src/screens/HomeScreen.tsx +++ b/src/screens/HomeScreen.tsx @@ -19,7 +19,7 @@ import { InteractionManager, AppState } from 'react-native'; -import { FlashList } from '@shopify/flash-list'; +import { LegendList } from '@legendapp/list'; import { useNavigation, useFocusEffect } from '@react-navigation/native'; import { NavigationProp } from '@react-navigation/native'; import { RootStackParamList } from '../navigation/AppNavigator'; @@ -764,7 +764,7 @@ const HomeScreen = () => { backgroundColor="transparent" translucent /> - { ListFooterComponent={ListFooterComponent} onEndReached={handleLoadMoreCatalogs} onEndReachedThreshold={0.6} - removeClippedSubviews={true} - scrollEventThrottle={64} + recycleItems={true} + maintainVisibleContentPosition onScroll={handleScroll} /> {/* Toasts are rendered globally at root */} From 0a04ba5743b942d64e5169fc0050c1fc406bb030 Mon Sep 17 00:00:00 2001 From: tapframe Date: Sat, 18 Oct 2025 14:58:22 +0530 Subject: [PATCH 17/17] cache changes --- babel.config.js | 1 + package-lock.json | 3 +- package.json | 1 + src/hooks/useMetadata.ts | 97 ++--- src/services/hybridCacheService.ts | 267 -------------- src/services/localScraperCacheService.ts | 437 ----------------------- src/services/localScraperService.ts | 205 ++++------- src/services/stremioService.ts | 13 +- 8 files changed, 108 insertions(+), 916 deletions(-) delete mode 100644 src/services/hybridCacheService.ts delete mode 100644 src/services/localScraperCacheService.ts diff --git a/babel.config.js b/babel.config.js index a5c5a10b..a31657b0 100644 --- a/babel.config.js +++ b/babel.config.js @@ -4,6 +4,7 @@ module.exports = function (api) { presets: ['babel-preset-expo'], plugins: [ 'react-native-worklets/plugin', + 'react-native-boost/plugin', ], env: { production: { diff --git a/package-lock.json b/package-lock.json index 060114ce..79e673e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,6 @@ "@expo/metro-runtime": "~6.1.2", "@expo/vector-icons": "^15.0.2", "@gorhom/bottom-sheet": "^5.2.6", - "@legendapp/list": "^2.0.13", "@lottiefiles/dotlottie-react": "^0.6.5", "@react-native-async-storage/async-storage": "2.2.0", "@react-native-community/blur": "^4.4.1", @@ -81,7 +80,7 @@ "react-native-svg": "15.12.1", "react-native-url-polyfill": "^2.0.0", "react-native-vector-icons": "^10.3.0", - "react-native-video": "^6.17.0", + "react-native-video": "^6.12.0", "react-native-web": "^0.21.0", "react-native-wheel-color-picker": "^1.3.1", "react-native-worklets": "^0.6.1", diff --git a/package.json b/package.json index 86e82cab..6c96b1e0 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "posthog-react-native": "^4.4.0", "react": "19.1.0", "react-native": "0.81.4", + "react-native-boost": "^0.6.2", "react-native-bottom-tabs": "^0.12.2", "react-native-gesture-handler": "~2.28.0", "react-native-get-random-values": "^1.11.0", diff --git a/src/hooks/useMetadata.ts b/src/hooks/useMetadata.ts index fb66db71..3c9ad638 100644 --- a/src/hooks/useMetadata.ts +++ b/src/hooks/useMetadata.ts @@ -107,28 +107,6 @@ interface UseMetadataReturn { imdbId: string | null; scraperStatuses: ScraperStatus[]; activeFetchingScrapers: string[]; - clearScraperCache: () => Promise; - invalidateScraperCache: (scraperId: string) => Promise; - invalidateContentCache: (type: string, tmdbId: string, season?: number, episode?: number) => Promise; - getScraperCacheStats: () => Promise<{ - local: { - totalEntries: number; - totalSize: number; - oldestEntry: number | null; - newestEntry: number | null; - }; - global: { - totalEntries: number; - totalSize: number; - oldestEntry: number | null; - newestEntry: number | null; - hitRate: number; - }; - combined: { - totalEntries: number; - hitRate: number; - }; - }>; } export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadataReturn => { @@ -287,9 +265,9 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat // Optimize streams before storing const optimizedStreams = optimizeStreams(streams); streamCountRef.current += optimizedStreams.length; - + if (__DEV__) logger.log(`📊 [${logPrefix}:${sourceName}] Optimized ${streams.length} → ${optimizedStreams.length} streams, total: ${streamCountRef.current}`); - + // Use debounced update to prevent rapid state changes debouncedStreamUpdate(() => { const updateState = (prevState: GroupedStreams): GroupedStreams => { @@ -302,7 +280,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat } }; }; - + // Track response order for addons setAddonResponseOrder(prevOrder => { if (!prevOrder.includes(addonId)) { @@ -310,7 +288,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat } return prevOrder; }); - + if (isEpisode) { setEpisodeStreams(updateState); setLoadingEpisodeStreams(false); @@ -320,7 +298,38 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat } }); } else { - if (__DEV__) logger.log(`🤷 [${logPrefix}:${sourceName}] No streams found for addon ${addonName} (${addonId})`); + // Even providers with no streams should be added to the streams object + // This ensures streamsEmpty becomes false and UI shows available streams progressively + if (__DEV__) logger.log(`🤷 [${logPrefix}:${sourceName}] No streams found for addon ${addonName} (${addonId})`); + + debouncedStreamUpdate(() => { + const updateState = (prevState: GroupedStreams): GroupedStreams => { + if (__DEV__) logger.log(`🔄 [${logPrefix}:${sourceName}] Adding empty provider ${addonName} (${addonId}) to state`); + return { + ...prevState, + [addonId]: { + addonName: addonName, + streams: [] // Empty array for providers with no streams + } + }; + }; + + // Track response order for addons + setAddonResponseOrder(prevOrder => { + if (!prevOrder.includes(addonId)) { + return [...prevOrder, addonId]; + } + return prevOrder; + }); + + if (isEpisode) { + setEpisodeStreams(updateState); + setLoadingEpisodeStreams(false); + } else { + setGroupedStreams(updateState); + setLoadingStreams(false); + } + }); } } else { // Handle case where callback provides null streams without error (e.g., empty results) @@ -1974,36 +1983,6 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat }; }, [cleanupStreams]); - // Cache management methods - const clearScraperCache = useCallback(async () => { - await localScraperService.clearScraperCache(); - }, []); - - const invalidateScraperCache = useCallback(async (scraperId: string) => { - await localScraperService.invalidateScraperCache(scraperId); - }, []); - - const invalidateContentCache = useCallback(async (type: string, tmdbId: string, season?: number, episode?: number) => { - await localScraperService.invalidateContentCache(type, tmdbId, season, episode); - }, []); - - const getScraperCacheStats = useCallback(async () => { - const localStats = await localScraperService.getCacheStats(); - return { - local: localStats.local, - global: { - totalEntries: 0, - totalSize: 0, - oldestEntry: null, - newestEntry: null, - hitRate: 0 - }, - combined: { - totalEntries: localStats.local.totalEntries, - hitRate: 0 - } - }; - }, []); return { metadata, @@ -2038,9 +2017,5 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat imdbId, scraperStatuses, activeFetchingScrapers, - clearScraperCache, - invalidateScraperCache, - invalidateContentCache, - getScraperCacheStats, }; }; \ No newline at end of file diff --git a/src/services/hybridCacheService.ts b/src/services/hybridCacheService.ts deleted file mode 100644 index a7045a97..00000000 --- a/src/services/hybridCacheService.ts +++ /dev/null @@ -1,267 +0,0 @@ -import { localScraperCacheService, CachedScraperResult } from './localScraperCacheService'; -import { logger } from '../utils/logger'; -import { Stream } from '../types/streams'; - -export interface HybridCacheResult { - validResults: Array; - expiredScrapers: string[]; - allExpired: boolean; - source: 'local'; -} - -export interface HybridCacheStats { - local: { - totalEntries: number; - totalSize: number; - oldestEntry: number | null; - newestEntry: number | null; - }; -} - -class HybridCacheService { - private static instance: HybridCacheService; - // Global caching removed; local-only - - private constructor() {} - - public static getInstance(): HybridCacheService { - if (!HybridCacheService.instance) { - HybridCacheService.instance = new HybridCacheService(); - } - return HybridCacheService.instance; - } - - /** - * Get cached results (local-only) - */ - async getCachedResults( - type: string, - tmdbId: string, - season?: number, - episode?: number, - userSettings?: { enableLocalScrapers?: boolean; enabledScrapers?: Set } - ): Promise { - try { - // Filter function to check if scraper is enabled for current user - const isScraperEnabled = (scraperId: string): boolean => { - if (!userSettings?.enableLocalScrapers) return false; - if (userSettings?.enabledScrapers) { - return userSettings.enabledScrapers.has(scraperId); - } - // If no specific scraper settings, assume all are enabled if local scrapers are enabled - return true; - }; - - // Local cache only - const localResults = await localScraperCacheService.getCachedResults(type, tmdbId, season, episode); - - // Filter results based on user settings - const filteredLocalResults = { - ...localResults, - validResults: localResults.validResults.filter(result => isScraperEnabled(result.scraperId)), - expiredScrapers: localResults.expiredScrapers.filter(scraperId => isScraperEnabled(scraperId)) - }; - - logger.log(`[HybridCache] Using local cache: ${filteredLocalResults.validResults.length} results (filtered from ${localResults.validResults.length})`); - return { - ...filteredLocalResults, - source: 'local' - }; - - } catch (error) { - logger.error('[HybridCache] Error getting cached results:', error); - return { - validResults: [], - expiredScrapers: [], - allExpired: true, - source: 'local' - }; - } - } - - /** - * Cache results (local-only) - */ - async cacheResults( - type: string, - tmdbId: string, - results: Array<{ - scraperId: string; - scraperName: string; - streams: Stream[] | null; - error: Error | null; - }>, - season?: number, - episode?: number - ): Promise { - try { - // Cache in local storage - const localPromises = results.map(result => - localScraperCacheService.cacheScraperResult( - type, tmdbId, result.scraperId, result.scraperName, - result.streams, result.error, season, episode - ) - ); - await Promise.all(localPromises); - logger.log(`[HybridCache] Cached ${results.length} results in local cache`); - - } catch (error) { - logger.error('[HybridCache] Error caching results:', error); - } - } - - /** - * Cache a single scraper result - */ - async cacheScraperResult( - type: string, - tmdbId: string, - scraperId: string, - scraperName: string, - streams: Stream[] | null, - error: Error | null, - season?: number, - episode?: number - ): Promise { - await this.cacheResults(type, tmdbId, [{ - scraperId, - scraperName, - streams, - error - }], season, episode); - } - - /** - * Get list of scrapers that need to be re-run (expired, failed, or not cached) - */ - async getScrapersToRerun( - type: string, - tmdbId: string, - availableScrapers: Array<{ id: string; name: string }>, - season?: number, - episode?: number, - userSettings?: { enableLocalScrapers?: boolean; enabledScrapers?: Set } - ): Promise { - const { validResults, expiredScrapers } = await this.getCachedResults(type, tmdbId, season, episode, userSettings); - - const validScraperIds = new Set(validResults.map(r => r.scraperId)); - const expiredScraperIds = new Set(expiredScrapers); - - // Get scrapers that previously failed (returned no streams) - const failedScraperIds = new Set( - validResults - .filter(r => !r.success || r.streams.length === 0) - .map(r => r.scraperId) - ); - - // Return scrapers that are: - // 1. Not cached at all - // 2. Expired - // 3. Previously failed (regardless of cache status) - const scrapersToRerun = availableScrapers - .filter(scraper => - !validScraperIds.has(scraper.id) || - expiredScraperIds.has(scraper.id) || - failedScraperIds.has(scraper.id) - ) - .map(scraper => scraper.id); - - logger.log(`[HybridCache] Scrapers to re-run: ${scrapersToRerun.join(', ')} (not cached: ${availableScrapers.filter(s => !validScraperIds.has(s.id)).length}, expired: ${expiredScrapers.length}, failed: ${failedScraperIds.size})`); - - return scrapersToRerun; - } - - /** - * Get all valid cached streams - */ - async getCachedStreams( - type: string, - tmdbId: string, - season?: number, - episode?: number, - userSettings?: { enableLocalScrapers?: boolean; enabledScrapers?: Set } - ): Promise { - const { validResults } = await this.getCachedResults(type, tmdbId, season, episode, userSettings); - - // Flatten all valid streams - const allStreams: Stream[] = []; - for (const result of validResults) { - if (result.success && result.streams) { - allStreams.push(...result.streams); - } - } - - return allStreams; - } - - /** - * Invalidate cache for specific content (local-only) - */ - async invalidateContent( - type: string, - tmdbId: string, - season?: number, - episode?: number - ): Promise { - try { - await localScraperCacheService.invalidateContent(type, tmdbId, season, episode); - logger.log(`[HybridCache] Invalidated cache for ${type}:${tmdbId}`); - } catch (error) { - logger.error('[HybridCache] Error invalidating cache:', error); - } - } - - /** - * Invalidate cache for specific scraper (local-only) - */ - async invalidateScraper(scraperId: string): Promise { - try { - await localScraperCacheService.invalidateScraper(scraperId); - logger.log(`[HybridCache] Invalidated cache for scraper ${scraperId}`); - } catch (error) { - logger.error('[HybridCache] Error invalidating scraper cache:', error); - } - } - - /** - * Clear all cached results (local-only) - */ - async clearAllCache(): Promise { - try { - await localScraperCacheService.clearAllCache(); - logger.log('[HybridCache] Cleared all local cache'); - } catch (error) { - logger.error('[HybridCache] Error clearing cache:', error); - } - } - - /** - * Get cache statistics (local-only) - */ - async getCacheStats(): Promise { - try { - const localStats = await localScraperCacheService.getCacheStats(); - return { local: localStats }; - } catch (error) { - logger.error('[HybridCache] Error getting cache stats:', error); - return { local: { totalEntries: 0, totalSize: 0, oldestEntry: null, newestEntry: null } }; - } - } - - /** - * Clean up old entries (local-only) - */ - async cleanupOldEntries(): Promise { - try { - await localScraperCacheService.clearAllCache(); - logger.log('[HybridCache] Cleaned up old entries'); - } catch (error) { - logger.error('[HybridCache] Error cleaning up old entries:', error); - } - } - - // Configuration APIs removed; local-only -} - -export const hybridCacheService = HybridCacheService.getInstance(); -export default hybridCacheService; diff --git a/src/services/localScraperCacheService.ts b/src/services/localScraperCacheService.ts deleted file mode 100644 index e00eb6e9..00000000 --- a/src/services/localScraperCacheService.ts +++ /dev/null @@ -1,437 +0,0 @@ -import AsyncStorage from '@react-native-async-storage/async-storage'; -import { logger } from '../utils/logger'; -import { Stream } from '../types/streams'; - -export interface CachedScraperResult { - streams: Stream[]; - timestamp: number; - success: boolean; - error?: string; - scraperId: string; - scraperName: string; -} - -export interface CachedContentResult { - contentKey: string; // e.g., "movie:123" or "tv:123:1:2" - results: CachedScraperResult[]; - timestamp: number; - ttl: number; -} - -class LocalScraperCacheService { - private static instance: LocalScraperCacheService; - private readonly CACHE_KEY_PREFIX = 'local-scraper-cache'; - private readonly DEFAULT_TTL_MS = 30 * 60 * 1000; // 30 minutes default TTL - private readonly MAX_CACHE_SIZE = 200; // Maximum number of cached content items - private readonly FAILED_RETRY_TTL_MS = 5 * 60 * 1000; // 5 minutes for failed scrapers - private readonly SUCCESS_TTL_MS = 60 * 60 * 1000; // 1 hour for successful scrapers - - private constructor() {} - - public static getInstance(): LocalScraperCacheService { - if (!LocalScraperCacheService.instance) { - LocalScraperCacheService.instance = new LocalScraperCacheService(); - } - return LocalScraperCacheService.instance; - } - - /** - * Generate cache key for content - */ - private getContentKey(type: string, tmdbId: string, season?: number, episode?: number): string { - if (season !== undefined && episode !== undefined) { - return `${type}:${tmdbId}:${season}:${episode}`; - } - return `${type}:${tmdbId}`; - } - - /** - * Generate AsyncStorage key for cached content - */ - private getStorageKey(contentKey: string): string { - return `${this.CACHE_KEY_PREFIX}:${contentKey}`; - } - - /** - * Check if cached result is still valid based on TTL - */ - private isCacheValid(timestamp: number, ttl: number): boolean { - return Date.now() - timestamp < ttl; - } - - /** - * Get cached results for content, filtering out expired results - */ - async getCachedResults( - type: string, - tmdbId: string, - season?: number, - episode?: number - ): Promise<{ - validResults: CachedScraperResult[]; - expiredScrapers: string[]; - allExpired: boolean; - }> { - try { - const contentKey = this.getContentKey(type, tmdbId, season, episode); - const storageKey = this.getStorageKey(contentKey); - - const cachedData = await AsyncStorage.getItem(storageKey); - if (!cachedData) { - return { - validResults: [], - expiredScrapers: [], - allExpired: true - }; - } - - const parsed: CachedContentResult = JSON.parse(cachedData); - - // Check if the entire cache entry is expired - if (!this.isCacheValid(parsed.timestamp, parsed.ttl)) { - // Remove expired entry - await AsyncStorage.removeItem(storageKey); - return { - validResults: [], - expiredScrapers: parsed.results.map(r => r.scraperId), - allExpired: true - }; - } - - // Filter valid results and identify expired scrapers - const validResults: CachedScraperResult[] = []; - const expiredScrapers: string[] = []; - - for (const result of parsed.results) { - // Use different TTL based on success/failure - const ttl = result.success ? this.SUCCESS_TTL_MS : this.FAILED_RETRY_TTL_MS; - - if (this.isCacheValid(result.timestamp, ttl)) { - validResults.push(result); - } else { - expiredScrapers.push(result.scraperId); - } - } - - logger.log(`[LocalScraperCache] Retrieved ${validResults.length} valid results, ${expiredScrapers.length} expired scrapers for ${contentKey}`); - - return { - validResults, - expiredScrapers, - allExpired: validResults.length === 0 - }; - - } catch (error) { - logger.error('[LocalScraperCache] Error getting cached results:', error); - return { - validResults: [], - expiredScrapers: [], - allExpired: true - }; - } - } - - /** - * Cache results for specific scrapers - */ - async cacheResults( - type: string, - tmdbId: string, - results: CachedScraperResult[], - season?: number, - episode?: number - ): Promise { - try { - const contentKey = this.getContentKey(type, tmdbId, season, episode); - const storageKey = this.getStorageKey(contentKey); - - // Get existing cached data - const existingData = await AsyncStorage.getItem(storageKey); - let cachedContent: CachedContentResult; - - if (existingData) { - cachedContent = JSON.parse(existingData); - - // Update existing results or add new ones - for (const newResult of results) { - const existingIndex = cachedContent.results.findIndex(r => r.scraperId === newResult.scraperId); - if (existingIndex >= 0) { - // Update existing result - cachedContent.results[existingIndex] = newResult; - } else { - // Add new result - cachedContent.results.push(newResult); - } - } - } else { - // Create new cache entry - cachedContent = { - contentKey, - results, - timestamp: Date.now(), - ttl: this.DEFAULT_TTL_MS - }; - } - - // Update timestamp - cachedContent.timestamp = Date.now(); - - // Store updated cache - await AsyncStorage.setItem(storageKey, JSON.stringify(cachedContent)); - - // Clean up old cache entries if we exceed the limit - await this.cleanupOldEntries(); - - logger.log(`[LocalScraperCache] Cached ${results.length} results for ${contentKey}`); - - } catch (error) { - logger.error('[LocalScraperCache] Error caching results:', error); - } - } - - /** - * Cache a single scraper result - */ - async cacheScraperResult( - type: string, - tmdbId: string, - scraperId: string, - scraperName: string, - streams: Stream[] | null, - error: Error | null, - season?: number, - episode?: number - ): Promise { - const result: CachedScraperResult = { - streams: streams || [], - timestamp: Date.now(), - success: !error && streams !== null, - error: error?.message, - scraperId, - scraperName - }; - - await this.cacheResults(type, tmdbId, [result], season, episode); - } - - /** - * Get list of scrapers that need to be re-run (expired, failed, or not cached) - */ - async getScrapersToRerun( - type: string, - tmdbId: string, - availableScrapers: Array<{ id: string; name: string }>, - season?: number, - episode?: number - ): Promise { - const { validResults, expiredScrapers } = await this.getCachedResults(type, tmdbId, season, episode); - - const validScraperIds = new Set(validResults.map(r => r.scraperId)); - const expiredScraperIds = new Set(expiredScrapers); - - // Get scrapers that previously failed (returned no streams) - const failedScraperIds = new Set( - validResults - .filter(r => !r.success || r.streams.length === 0) - .map(r => r.scraperId) - ); - - // Return scrapers that are: - // 1. Not cached at all - // 2. Expired - // 3. Previously failed (regardless of cache status) - const scrapersToRerun = availableScrapers - .filter(scraper => - !validScraperIds.has(scraper.id) || - expiredScraperIds.has(scraper.id) || - failedScraperIds.has(scraper.id) - ) - .map(scraper => scraper.id); - - logger.log(`[LocalScraperCache] Scrapers to re-run: ${scrapersToRerun.join(', ')} (not cached: ${availableScrapers.filter(s => !validScraperIds.has(s.id)).length}, expired: ${expiredScrapers.length}, failed: ${failedScraperIds.size})`); - - return scrapersToRerun; - } - - /** - * Get all valid cached streams for content - */ - async getCachedStreams( - type: string, - tmdbId: string, - season?: number, - episode?: number - ): Promise { - const { validResults } = await this.getCachedResults(type, tmdbId, season, episode); - - // Flatten all valid streams - const allStreams: Stream[] = []; - for (const result of validResults) { - if (result.success && result.streams) { - allStreams.push(...result.streams); - } - } - - return allStreams; - } - - /** - * Invalidate cache for specific content - */ - async invalidateContent( - type: string, - tmdbId: string, - season?: number, - episode?: number - ): Promise { - try { - const contentKey = this.getContentKey(type, tmdbId, season, episode); - const storageKey = this.getStorageKey(contentKey); - - await AsyncStorage.removeItem(storageKey); - logger.log(`[LocalScraperCache] Invalidated cache for ${contentKey}`); - } catch (error) { - logger.error('[LocalScraperCache] Error invalidating cache:', error); - } - } - - /** - * Invalidate cache for specific scraper across all content - */ - async invalidateScraper(scraperId: string): Promise { - try { - const keys = await AsyncStorage.getAllKeys(); - const cacheKeys = keys.filter(key => key.startsWith(this.CACHE_KEY_PREFIX)); - - for (const key of cacheKeys) { - const cachedData = await AsyncStorage.getItem(key); - if (cachedData) { - const parsed: CachedContentResult = JSON.parse(cachedData); - - // Remove results from this scraper - parsed.results = parsed.results.filter(r => r.scraperId !== scraperId); - - if (parsed.results.length === 0) { - // Remove entire cache entry if no results left - await AsyncStorage.removeItem(key); - } else { - // Update cache with remaining results - await AsyncStorage.setItem(key, JSON.stringify(parsed)); - } - } - } - - logger.log(`[LocalScraperCache] Invalidated cache for scraper ${scraperId}`); - } catch (error) { - logger.error('[LocalScraperCache] Error invalidating scraper cache:', error); - } - } - - /** - * Clear all cached results - */ - async clearAllCache(): Promise { - try { - const keys = await AsyncStorage.getAllKeys(); - const cacheKeys = keys.filter(key => key.startsWith(this.CACHE_KEY_PREFIX)); - - await AsyncStorage.multiRemove(cacheKeys); - logger.log(`[LocalScraperCache] Cleared ${cacheKeys.length} cache entries`); - } catch (error) { - logger.error('[LocalScraperCache] Error clearing cache:', error); - } - } - - /** - * Clean up old cache entries to stay within size limit - */ - private async cleanupOldEntries(): Promise { - try { - const keys = await AsyncStorage.getAllKeys(); - const cacheKeys = keys.filter(key => key.startsWith(this.CACHE_KEY_PREFIX)); - - if (cacheKeys.length <= this.MAX_CACHE_SIZE) { - return; // No cleanup needed - } - - // Get all cache entries with their timestamps - const entriesWithTimestamps = await Promise.all( - cacheKeys.map(async (key) => { - const data = await AsyncStorage.getItem(key); - if (data) { - const parsed: CachedContentResult = JSON.parse(data); - return { key, timestamp: parsed.timestamp }; - } - return { key, timestamp: 0 }; - }) - ); - - // Sort by timestamp (oldest first) - entriesWithTimestamps.sort((a, b) => a.timestamp - b.timestamp); - - // Remove oldest entries - const entriesToRemove = entriesWithTimestamps.slice(0, cacheKeys.length - this.MAX_CACHE_SIZE); - const keysToRemove = entriesToRemove.map(entry => entry.key); - - if (keysToRemove.length > 0) { - await AsyncStorage.multiRemove(keysToRemove); - logger.log(`[LocalScraperCache] Cleaned up ${keysToRemove.length} old cache entries`); - } - - } catch (error) { - logger.error('[LocalScraperCache] Error cleaning up cache:', error); - } - } - - /** - * Get cache statistics - */ - async getCacheStats(): Promise<{ - totalEntries: number; - totalSize: number; - oldestEntry: number | null; - newestEntry: number | null; - }> { - try { - const keys = await AsyncStorage.getAllKeys(); - const cacheKeys = keys.filter(key => key.startsWith(this.CACHE_KEY_PREFIX)); - - let totalSize = 0; - let oldestTimestamp: number | null = null; - let newestTimestamp: number | null = null; - - for (const key of cacheKeys) { - const data = await AsyncStorage.getItem(key); - if (data) { - totalSize += data.length; - const parsed: CachedContentResult = JSON.parse(data); - - if (oldestTimestamp === null || parsed.timestamp < oldestTimestamp) { - oldestTimestamp = parsed.timestamp; - } - if (newestTimestamp === null || parsed.timestamp > newestTimestamp) { - newestTimestamp = parsed.timestamp; - } - } - } - - return { - totalEntries: cacheKeys.length, - totalSize, - oldestEntry: oldestTimestamp, - newestEntry: newestTimestamp - }; - } catch (error) { - logger.error('[LocalScraperCache] Error getting cache stats:', error); - return { - totalEntries: 0, - totalSize: 0, - oldestEntry: null, - newestEntry: null - }; - } - } -} - -export const localScraperCacheService = LocalScraperCacheService.getInstance(); -export default localScraperCacheService; diff --git a/src/services/localScraperService.ts b/src/services/localScraperService.ts index e8f1467a..ff7e801f 100644 --- a/src/services/localScraperService.ts +++ b/src/services/localScraperService.ts @@ -4,8 +4,6 @@ import { Platform } from 'react-native'; import { logger } from '../utils/logger'; import { Stream } from '../types/streams'; import { cacheService } from './cacheService'; -import { localScraperCacheService } from './localScraperCacheService'; -import { hybridCacheService } from './hybridCacheService'; import CryptoJS from 'crypto-js'; // Types for local scrapers @@ -862,86 +860,44 @@ class LocalScraperService { } } - // Execute scrapers for streams with caching + // Execute scrapers for streams async getStreams(type: string, tmdbId: string, season?: number, episode?: number, callback?: ScraperCallback): Promise { await this.ensureInitialized(); - + // Get available scrapers from manifest (respects manifestEnabled) const availableScrapers = await this.getAvailableScrapers(); const enabledScrapers = availableScrapers - .filter(scraper => - scraper.enabled && - scraper.manifestEnabled !== false && + .filter(scraper => + scraper.enabled && + scraper.manifestEnabled !== false && scraper.supportedTypes.includes(type as 'movie' | 'tv') ); - + if (enabledScrapers.length === 0) { logger.log('[LocalScraperService] No enabled scrapers found for type:', type); return; } - // Get current user settings for enabled scrapers - const userSettings = await this.getUserScraperSettings(); - - // Check cache for existing results (hybrid: global first, then local) - const { validResults, expiredScrapers, allExpired, source } = await hybridCacheService.getCachedResults(type, tmdbId, season, episode, userSettings); - - // Immediately return cached results for valid scrapers - if (validResults.length > 0) { - logger.log(`[LocalScraperService] Returning ${validResults.length} cached results for ${type}:${tmdbId} (source: ${source})`); - - for (const cachedResult of validResults) { - if (cachedResult.success && cachedResult.streams.length > 0) { - // Streams are already in the correct format, just pass them through - if (callback) { - callback(cachedResult.streams, cachedResult.scraperId, cachedResult.scraperName, null); - } - } else if (callback) { - // Return error for failed cached results - const error = cachedResult.error ? new Error(cachedResult.error) : new Error('Scraper failed'); - callback(null, cachedResult.scraperId, cachedResult.scraperName, error); - } - } - } - - // Determine which scrapers need to be re-run - const scrapersToRerun = enabledScrapers.filter(scraper => { - const hasValidResult = validResults.some(r => r.scraperId === scraper.id); - const isExpired = expiredScrapers.includes(scraper.id); - const hasFailedResult = validResults.some(r => r.scraperId === scraper.id && (!r.success || r.streams.length === 0)); - - return !hasValidResult || isExpired || hasFailedResult; - }); - - if (scrapersToRerun.length === 0) { - logger.log('[LocalScraperService] All scrapers have valid cached results'); - return; - } - - logger.log(`[LocalScraperService] Re-running ${scrapersToRerun.length} scrapers for ${type}:${tmdbId}`, { - totalEnabled: enabledScrapers.length, - expired: expiredScrapers.length, - failed: validResults.filter(r => !r.success || r.streams.length === 0).length, - notCached: enabledScrapers.length - validResults.length, - scrapersToRerun: scrapersToRerun.map(s => s.name) + logger.log(`[LocalScraperService] Executing ${enabledScrapers.length} scrapers for ${type}:${tmdbId}`, { + scrapers: enabledScrapers.map(s => s.name) }); // Generate a lightweight request id for tracing const requestId = `rs_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`; - // Execute only scrapers that need to be re-run - for (const scraper of scrapersToRerun) { - this.executeScraperWithCaching(scraper, type, tmdbId, season, episode, callback, requestId); + // Execute all enabled scrapers + for (const scraper of enabledScrapers) { + this.executeScraper(scraper, type, tmdbId, season, episode, callback, requestId); } } - // Execute individual scraper with caching - private async executeScraperWithCaching( - scraper: ScraperInfo, - type: string, - tmdbId: string, - season?: number, - episode?: number, + // Execute individual scraper + private async executeScraper( + scraper: ScraperInfo, + type: string, + tmdbId: string, + season?: number, + episode?: number, callback?: ScraperCallback, requestId?: string ): Promise { @@ -950,10 +906,10 @@ class LocalScraperService { if (!code) { throw new Error(`No code found for scraper ${scraper.id}`); } - + // Load per-scraper settings const scraperSettings = await this.getScraperSettings(scraper.id); - + // Build single-flight key const flightKey = `${scraper.id}|${type}|${tmdbId}|${season ?? ''}|${episode ?? ''}`; @@ -980,60 +936,23 @@ class LocalScraperService { } const results = await promise; - + // Convert results to Nuvio Stream format const streams = this.convertToStreams(results, scraper); - - // Cache the successful result (hybrid: both local and global) - await hybridCacheService.cacheScraperResult( - type, - tmdbId, - scraper.id, - scraper.name, - streams, - null, - season, - episode - ); - + if (callback) { callback(streams, scraper.id, scraper.name, null); } - + } catch (error) { logger.error('[LocalScraperService] Scraper', scraper.name, 'failed:', error); - - // Cache the failed result (hybrid: both local and global) - await hybridCacheService.cacheScraperResult( - type, - tmdbId, - scraper.id, - scraper.name, - null, - error as Error, - season, - episode - ); - + if (callback) { callback(null, scraper.id, scraper.name, error as Error); } } } - // Execute individual scraper (legacy method - kept for compatibility) - private async executeScraper( - scraper: ScraperInfo, - type: string, - tmdbId: string, - season?: number, - episode?: number, - callback?: ScraperCallback, - requestId?: string - ): Promise { - // Delegate to the caching version - return this.executeScraperWithCaching(scraper, type, tmdbId, season, episode, callback, requestId); - } // Execute scraper code in sandboxed environment private async executeSandboxed(code: string, params: any): Promise { @@ -1161,7 +1080,7 @@ class LocalScraperService { ...options.headers }, data: options.body, - timeout: 60000, + timeout: 120000, // Increased to 2 minutes for complex scrapers validateStatus: () => true // Don't throw on HTTP error status codes }; @@ -1201,7 +1120,7 @@ class LocalScraperService { }, // Add axios for HTTP requests axios: axios.create({ - timeout: 30000, + timeout: 120000, // Increased to 2 minutes for complex scrapers headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } @@ -1217,27 +1136,29 @@ class LocalScraperService { SCRAPER_ID: params?.scraperId }; - // Execute the scraper code without timeout + // Execute the scraper code with 1 minute timeout + const SCRAPER_EXECUTION_TIMEOUT_MS = 60000; // 1 minute + const executionPromise = new Promise((resolve, reject) => { try { // Create function from code const func = new Function('sandbox', 'params', 'PRIMARY_KEY', 'TMDB_API_KEY', ` const { console, setTimeout, clearTimeout, Promise, JSON, Date, Math, parseInt, parseFloat, encodeURIComponent, decodeURIComponent, require, axios, fetch, module, exports, global, URL_VALIDATION_ENABLED, SCRAPER_SETTINGS, SCRAPER_ID } = sandbox; - + // Inject MovieBox constants into global scope global.PRIMARY_KEY = PRIMARY_KEY; global.TMDB_API_KEY = TMDB_API_KEY; window.PRIMARY_KEY = PRIMARY_KEY; window.TMDB_API_KEY = TMDB_API_KEY; - + // Expose per-scraper context to plugin globals global.SCRAPER_SETTINGS = SCRAPER_SETTINGS; global.SCRAPER_ID = SCRAPER_ID; window.SCRAPER_SETTINGS = SCRAPER_SETTINGS; window.SCRAPER_ID = SCRAPER_ID; - + ${code} - + // Call the main function (assuming it's exported) if (typeof getStreams === 'function') { return getStreams(params.tmdbId, params.mediaType, params.season, params.episode); @@ -1249,9 +1170,9 @@ class LocalScraperService { throw new Error('No getStreams function found in scraper'); } `); - + const result = func(sandbox, params, MOVIEBOX_PRIMARY_KEY, MOVIEBOX_TMDB_API_KEY); - + // Handle both sync and async results if (result && typeof result.then === 'function') { result.then(resolve).catch(reject); @@ -1262,8 +1183,14 @@ class LocalScraperService { reject(error); } }); - - return await executionPromise; + + // Apply 1-minute timeout to prevent hanging scrapers + return await Promise.race([ + executionPromise, + new Promise((_, reject) => + setTimeout(() => reject(new Error(`Scraper execution timed out after ${SCRAPER_EXECUTION_TIMEOUT_MS}ms`)), SCRAPER_EXECUTION_TIMEOUT_MS) + ) + ]); } catch (error) { logger.error('[LocalScraperService] Sandbox execution failed:', error); @@ -1365,6 +1292,19 @@ class LocalScraperService { // Check if local scrapers are available async hasScrapers(): Promise { await this.ensureInitialized(); + + // Get user settings to check if local scrapers are enabled + const userSettings = await this.getUserScraperSettings(); + if (!userSettings.enableLocalScrapers) { + return false; + } + + // Check if there are any enabled scrapers based on user settings + if (userSettings.enabledScrapers && userSettings.enabledScrapers.size > 0) { + return true; + } + + // Fallback: check if any scrapers are enabled in the internal state return Array.from(this.installedScrapers.values()).some(scraper => scraper.enabled); } @@ -1384,8 +1324,11 @@ class LocalScraperService { }; } - // Get user settings from AsyncStorage - const settingsData = await AsyncStorage.getItem('app_settings'); + // Get user settings from AsyncStorage (scoped with fallback) + const scope = (await AsyncStorage.getItem('@user:current')) || 'local'; + const scopedSettingsJson = await AsyncStorage.getItem(`@user:${scope}:app_settings`); + const legacySettingsJson = await AsyncStorage.getItem('app_settings'); + const settingsData = scopedSettingsJson || legacySettingsJson; const settings = settingsData ? JSON.parse(settingsData) : {}; // Get enabled scrapers based on current user settings @@ -1408,32 +1351,6 @@ class LocalScraperService { } } - // Cache management methods (hybrid: local + global) - async clearScraperCache(): Promise { - await hybridCacheService.clearAllCache(); - logger.log('[LocalScraperService] Cleared all scraper cache (local + global)'); - } - - async invalidateScraperCache(scraperId: string): Promise { - await hybridCacheService.invalidateScraper(scraperId); - logger.log('[LocalScraperService] Invalidated cache for scraper:', scraperId); - } - - async invalidateContentCache(type: string, tmdbId: string, season?: number, episode?: number): Promise { - await hybridCacheService.invalidateContent(type, tmdbId, season, episode); - logger.log('[LocalScraperService] Invalidated cache for content:', `${type}:${tmdbId}`); - } - - async getCacheStats(): Promise<{ - local: { - totalEntries: number; - totalSize: number; - oldestEntry: number | null; - newestEntry: number | null; - }; - }> { - return await hybridCacheService.getCacheStats(); - } } export const localScraperService = LocalScraperService.getInstance(); diff --git a/src/services/stremioService.ts b/src/services/stremioService.ts index 49593b08..c1a39478 100644 --- a/src/services/stremioService.ts +++ b/src/services/stremioService.ts @@ -1235,13 +1235,16 @@ class StremioService { // Execute local scrapers asynchronously with TMDB ID (when available) if (tmdbId) { localScraperService.getStreams(scraperType, tmdbId, season, episode, (streams, scraperId, scraperName, error) => { - if (error) { - if (callback) { + // Always call callback to ensure UI updates, regardless of result + if (callback) { + if (error) { callback(null, scraperId, scraperName, error); - } - } else if (streams && streams.length > 0) { - if (callback) { + } else if (streams && streams.length > 0) { callback(streams, scraperId, scraperName, null); + } else { + // Handle case where scraper completed successfully but returned no streams + // This ensures the scraper is removed from "fetching" state in UI + callback([], scraperId, scraperName, null); } } });