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;