diff --git a/App.tsx b/App.tsx index ca88199a..f5e30c39 100644 --- a/App.tsx +++ b/App.tsx @@ -40,10 +40,10 @@ Sentry.init({ // For more information, visit: https://docs.sentry.io/platforms/react-native/data-management/data-collected/ sendDefaultPii: true, - // Configure Session Replay - replaysSessionSampleRate: 0.1, - replaysOnErrorSampleRate: 1, - integrations: [Sentry.mobileReplayIntegration(), Sentry.feedbackIntegration()], + // Configure Session Replay (disabled for performance) + replaysSessionSampleRate: 0, + replaysOnErrorSampleRate: 0, + integrations: [Sentry.feedbackIntegration()], // uncomment the line below to enable Spotlight (https://spotlightjs.com) // spotlight: __DEV__, diff --git a/app.json b/app.json index 29458b3a..eb84a1a4 100644 --- a/app.json +++ b/app.json @@ -33,7 +33,8 @@ "UIFileSharingEnabled": true }, "bundleIdentifier": "com.nuvio.app", - "associatedDomains": [] + "associatedDomains": [], + "jsEngine": "hermes" }, "android": { "adaptiveIcon": { @@ -52,7 +53,8 @@ "armeabi-v7a", "x86", "x86_64" - ] + ], + "jsEngine": "hermes" }, "extra": { diff --git a/src/components/player/AndroidVideoPlayer.tsx b/src/components/player/AndroidVideoPlayer.tsx index 715a7362..bf268d63 100644 --- a/src/components/player/AndroidVideoPlayer.tsx +++ b/src/components/player/AndroidVideoPlayer.tsx @@ -1,5 +1,5 @@ import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react'; -import { View, TouchableOpacity, Dimensions, Animated, ActivityIndicator, Platform, NativeModules, StatusBar, Text, Image, StyleSheet, Modal } from 'react-native'; +import { View, TouchableOpacity, TouchableWithoutFeedback, Dimensions, Animated, ActivityIndicator, Platform, NativeModules, StatusBar, Text, Image, StyleSheet, Modal } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import Video, { VideoRef, SelectedTrack, SelectedTrackType, BufferingStrategyType } from 'react-native-video'; import { useNavigation, useRoute, RouteProp } from '@react-navigation/native'; @@ -435,6 +435,17 @@ const AndroidVideoPlayer: React.FC = () => { // Removed the 100ms delay backgroundFadeAnim.setValue(0); }); + + // Fallback: ensure animation completes even if something goes wrong + setTimeout(() => { + if (!isOpeningAnimationComplete) { + logger.warn('[AndroidVideoPlayer] Opening animation fallback triggered'); + setIsOpeningAnimationComplete(true); + openingScaleAnim.setValue(1); + openingFadeAnim.setValue(1); + backgroundFadeAnim.setValue(0); + } + }, 1000); // 1 second fallback }; useEffect(() => { @@ -2035,6 +2046,14 @@ const AndroidVideoPlayer: React.FC = () => { + {/* Tap-capture overlay above the Video to toggle controls (Android fix) */} + + + + { }; const handleUseDefaultRepo = () => { - const defaultUrl = 'https://raw.githubusercontent.com/tapframe/nuvio-providers/refs/heads/master'; + const defaultUrl = 'https://raw.githubusercontent.com/tapframe/nuvio-providers/refs/heads/main'; setRepositoryUrl(defaultUrl); }; @@ -1178,18 +1178,36 @@ const PluginsScreen: React.FC = () => { {/* Quick Setup for New Users */} {!hasRepository && ( - Quick Setup + 🚀 Quick Start with Official Plugins - Get started with plugins in 3 easy steps! Enable local scrapers, set up a repository, and start streaming. + Get instant access to 9+ premium streaming scrapers from Tapframe's official repository. Enable local scrapers and start streaming movies and TV shows immediately. { - setExpandedSections(prev => ({ ...prev, repository: true })); - setShowHelpModal(true); + onPress={async () => { + try { + setIsLoading(true); + // Add the official tapframe repository + const tapframeInfo = localScraperService.getTapframeRepositoryInfo(); + const repoId = await localScraperService.addRepository(tapframeInfo); + + // Switch to the new repository and refresh it + await localScraperService.setCurrentRepository(repoId); + await loadRepositories(); + await loadScrapers(); + + Alert.alert('Success', 'Official repository added! Enable local scrapers above to start using plugins.'); + } catch (error) { + logger.error('[PluginsScreen] Failed to add tapframe repository:', error); + Alert.alert('Error', 'Failed to add official repository'); + } finally { + setIsLoading(false); + } }} > - Get Started + + {isLoading ? 'Adding Repository...' : 'Add Official Repository'} + )} @@ -1309,6 +1327,31 @@ const PluginsScreen: React.FC = () => { )} + {/* Add Official Repository Button */} + {!localScraperService.hasTapframeRepository() && ( + { + try { + setIsLoading(true); + const tapframeInfo = localScraperService.getTapframeRepositoryInfo(); + const repoId = await localScraperService.addRepository(tapframeInfo); + await loadRepositories(); + Alert.alert('Success', 'Official repository added successfully!'); + } catch (error) { + logger.error('[PluginsScreen] Failed to add tapframe repository:', error); + Alert.alert('Error', 'Failed to add official repository'); + } finally { + setIsLoading(false); + } + }} + disabled={!settings.enableLocalScrapers || isLoading} + > + + Add Official Repository + + )} + {/* Add Repository Button */} { if (this.initialized) return; - + try { + // Ensure tapframe repository is available + await this.ensureTapframeRepository(); // Load repositories const repositoriesData = await AsyncStorage.getItem(this.REPOSITORIES_KEY); if (repositoriesData) { const repos = JSON.parse(repositoriesData); this.repositories = new Map(Object.entries(repos)); } else { - // Migrate from old single repository format + // Migrate from old single repository format or create default tapframe repository const storedRepoUrl = await AsyncStorage.getItem(this.REPOSITORY_KEY); if (storedRepoUrl) { const defaultRepo: RepositoryInfo = { @@ -116,9 +118,26 @@ class LocalScraperService { this.repositories.set('default', defaultRepo); this.currentRepositoryId = 'default'; await this.saveRepositories(); + } else { + // Create default tapframe repository for new users + const tapframeRepo: RepositoryInfo = { + id: 'tapframe-nuvio-providers', + name: 'Tapframe\'s Repo', + url: 'https://raw.githubusercontent.com/tapframe/nuvio-providers/refs/heads/main', + description: 'Official Nuvio streaming plugins repository by Tapframe', + isDefault: true, + enabled: true, + lastUpdated: Date.now() + }; + this.repositories.set('tapframe-nuvio-providers', tapframeRepo); + this.currentRepositoryId = 'tapframe-nuvio-providers'; + await this.saveRepositories(); } } + // Ensure tapframe repository is available for existing users too + await this.ensureTapframeRepository(); + // Load current repository const currentRepoId = await AsyncStorage.getItem('current-repository-id'); if (currentRepoId && this.repositories.has(currentRepoId)) { @@ -233,6 +252,93 @@ class LocalScraperService { } } + /** + * Ensure the tapframe repository is available for all users + */ + public async ensureTapframeRepository(): Promise { + const tapframeRepoId = 'tapframe-nuvio-providers'; + const tapframeRepoUrl = 'https://raw.githubusercontent.com/tapframe/nuvio-providers/refs/heads/main'; + + // Check if tapframe repository already exists + if (this.repositories.has(tapframeRepoId)) { + const existingRepo = this.repositories.get(tapframeRepoId)!; + // Update URL if it changed + if (existingRepo.url !== tapframeRepoUrl) { + existingRepo.url = tapframeRepoUrl; + existingRepo.name = 'Tapframe\'s Repo'; + existingRepo.description = 'Official Nuvio streaming plugins repository by Tapframe'; + await this.saveRepositories(); + } + return; + } + + // Check if any repository with the same URL already exists + for (const [id, repo] of this.repositories) { + if (repo.url === tapframeRepoUrl) { + // Update existing repository to use the tapframe ID and info + repo.id = tapframeRepoId; + repo.name = 'Tapframe\'s Repo'; + repo.description = 'Official Nuvio streaming plugins repository by Tapframe'; + repo.isDefault = true; + this.repositories.delete(id); + this.repositories.set(tapframeRepoId, repo); + await this.saveRepositories(); + return; + } + } + + // Create new tapframe repository + const tapframeRepo: RepositoryInfo = { + id: tapframeRepoId, + name: 'Tapframe\'s Repo', + url: tapframeRepoUrl, + description: 'Official Nuvio streaming plugins repository by Tapframe', + isDefault: true, + enabled: true, + lastUpdated: Date.now() + }; + + this.repositories.set(tapframeRepoId, tapframeRepo); + await this.saveRepositories(); + } + + /** + * Get the official tapframe repository info + */ + public getTapframeRepositoryInfo(): RepositoryInfo { + return { + id: 'tapframe-nuvio-providers', + name: 'Tapframe\'s Repo', + url: 'https://raw.githubusercontent.com/tapframe/nuvio-providers/refs/heads/main', + description: 'Official Nuvio streaming plugins repository by Tapframe', + isDefault: true, + enabled: true, + lastUpdated: Date.now() + }; + } + + /** + * Check if the tapframe repository is available + */ + public hasTapframeRepository(): boolean { + const tapframeRepoId = 'tapframe-nuvio-providers'; + const tapframeRepoUrl = 'https://raw.githubusercontent.com/tapframe/nuvio-providers/refs/heads/main'; + + // Check if tapframe repository exists by ID + if (this.repositories.has(tapframeRepoId)) { + return true; + } + + // Check if any repository has the tapframe URL + for (const repo of this.repositories.values()) { + if (repo.url === tapframeRepoUrl) { + return true; + } + } + + return false; + } + // Set repository URL async setRepositoryUrl(url: string): Promise { this.repositoryUrl = url;