Add internal providers toggle to settings and update HDRezka service logic

This commit is contained in:
tapframe 2025-05-27 22:16:43 +05:30
parent 259d071e95
commit 10aa799626
4 changed files with 67 additions and 6 deletions

View file

@ -34,6 +34,7 @@ export interface AppSettings {
selectedHeroCatalogs: string[]; // Array of catalog IDs to display in hero section selectedHeroCatalogs: string[]; // Array of catalog IDs to display in hero section
logoSourcePreference: 'metahub' | 'tmdb'; // Preferred source for title logos logoSourcePreference: 'metahub' | 'tmdb'; // Preferred source for title logos
tmdbLanguagePreference: string; // Preferred language for TMDB logos (ISO 639-1 code) tmdbLanguagePreference: string; // Preferred language for TMDB logos (ISO 639-1 code)
enableInternalProviders: boolean; // Toggle for internal providers like HDRezka
} }
export const DEFAULT_SETTINGS: AppSettings = { export const DEFAULT_SETTINGS: AppSettings = {
@ -50,6 +51,7 @@ export const DEFAULT_SETTINGS: AppSettings = {
selectedHeroCatalogs: [], // Empty array means all catalogs are selected selectedHeroCatalogs: [], // Empty array means all catalogs are selected
logoSourcePreference: 'metahub', // Default to Metahub as first source logoSourcePreference: 'metahub', // Default to Metahub as first source
tmdbLanguagePreference: 'en', // Default to English tmdbLanguagePreference: 'en', // Default to English
enableInternalProviders: true, // Enable internal providers by default
}; };
const SETTINGS_STORAGE_KEY = 'app_settings'; const SETTINGS_STORAGE_KEY = 'app_settings';

View file

@ -406,6 +406,17 @@ const SettingsScreen: React.FC = () => {
onPress={() => navigation.navigate('CatalogSettings')} onPress={() => navigation.navigate('CatalogSettings')}
badge={catalogCount} badge={catalogCount}
/> />
<SettingItem
title="Internal Providers"
description="Enable or disable built-in providers like HDRezka"
icon="source"
renderControl={() => (
<CustomSwitch
value={settings.enableInternalProviders}
onValueChange={(value) => updateSetting('enableInternalProviders', value)}
/>
)}
/>
<SettingItem <SettingItem
title="Home Screen" title="Home Screen"
description="Customize layout and content" description="Customize layout and content"

View file

@ -318,6 +318,13 @@ export const StreamsScreen = () => {
logger.log("🏁 Stream loading finished. Processing results."); logger.log("🏁 Stream loading finished. Processing results.");
const currentStreamsData = type === 'series' ? episodeStreams : groupedStreams; const currentStreamsData = type === 'series' ? episodeStreams : groupedStreams;
// Find all providers that returned streams
const providersWithStreams = Object.entries(currentStreamsData)
.filter(([_, data]) => data.streams && data.streams.length > 0)
.map(([providerId]) => providerId);
logger.log(`📊 Providers with streams: ${providersWithStreams.join(', ')}`);
// Update simple loading flag: all expected providers are no longer loading // Update simple loading flag: all expected providers are no longer loading
setLoadingProviders(prevLoading => { setLoadingProviders(prevLoading => {
@ -334,8 +341,8 @@ export const StreamsScreen = () => {
expectedProviders.forEach(providerId => { expectedProviders.forEach(providerId => {
if (newStatus[providerId]) { // Ensure the provider entry exists if (newStatus[providerId]) { // Ensure the provider entry exists
const providerHasStreams = currentStreamsData[providerId] && const providerHasStreams = currentStreamsData[providerId] &&
currentStreamsData[providerId].streams && currentStreamsData[providerId].streams &&
currentStreamsData[providerId].streams.length > 0; currentStreamsData[providerId].streams.length > 0;
newStatus[providerId] = { newStatus[providerId] = {
...newStatus[providerId], // Preserve timeStarted ...newStatus[providerId], // Preserve timeStarted
@ -362,14 +369,33 @@ export const StreamsScreen = () => {
}); });
// Update the set of available providers based on what actually loaded streams // Update the set of available providers based on what actually loaded streams
const providersWithStreams = new Set(Object.keys(currentStreamsData)); const providersWithStreamsSet = new Set(providersWithStreams);
setAvailableProviders(providersWithStreams); setAvailableProviders(providersWithStreamsSet);
// Reset loadStartTime to signify the end of this loading cycle // Reset loadStartTime to signify the end of this loading cycle
setLoadStartTime(0); setLoadStartTime(0);
} }
}, [loadingStreams, loadingEpisodeStreams, groupedStreams, episodeStreams, type /* loadStartTime is intentionally omitted from deps here */]); }, [loadingStreams, loadingEpisodeStreams, groupedStreams, episodeStreams, type /* loadStartTime is intentionally omitted from deps here */]);
// Add useEffect to update availableProviders whenever streams change
useEffect(() => {
if (!loadingStreams && !loadingEpisodeStreams) {
const streams = type === 'series' ? episodeStreams : groupedStreams;
// Only include providers that actually have streams
const providers = new Set(
Object.entries(streams)
.filter(([_, data]) => data.streams && data.streams.length > 0)
.map(([providerId]) => providerId)
);
setAvailableProviders(providers);
// Also reset the selected provider to 'all' if the current selection is no longer available
if (selectedProvider !== 'all' && !providers.has(selectedProvider)) {
setSelectedProvider('all');
}
}
}, [type, groupedStreams, episodeStreams, loadingStreams, loadingEpisodeStreams, selectedProvider]);
React.useEffect(() => { React.useEffect(() => {
if (type === 'series' && episodeId) { if (type === 'series' && episodeId) {
logger.log(`🎬 Loading episode streams for: ${episodeId}`); logger.log(`🎬 Loading episode streams for: ${episodeId}`);
@ -628,10 +654,20 @@ export const StreamsScreen = () => {
const filterItems = useMemo(() => { const filterItems = useMemo(() => {
const installedAddons = stremioService.getInstalledAddons(); const installedAddons = stremioService.getInstalledAddons();
const streams = type === 'series' ? episodeStreams : groupedStreams; const streams = type === 'series' ? episodeStreams : groupedStreams;
// Make sure we include all providers with streams, not just those in availableProviders
const allProviders = new Set([
...availableProviders,
...Object.keys(streams).filter(key =>
streams[key] &&
streams[key].streams &&
streams[key].streams.length > 0
)
]);
return [ return [
{ id: 'all', name: 'All Providers' }, { id: 'all', name: 'All Providers' },
...Array.from(availableProviders) ...Array.from(allProviders)
.sort((a, b) => { .sort((a, b) => {
// Always put HDRezka at the top // Always put HDRezka at the top
if (a === 'hdrezka') return -1; if (a === 'hdrezka') return -1;

View file

@ -2,6 +2,8 @@ import { logger } from '../utils/logger';
import { Stream } from '../types/metadata'; import { Stream } from '../types/metadata';
import { tmdbService } from './tmdbService'; import { tmdbService } from './tmdbService';
import axios from 'axios'; import axios from 'axios';
import { settingsEmitter } from '../hooks/useSettings';
import AsyncStorage from '@react-native-async-storage/async-storage';
// Use node-fetch if available, otherwise fallback to global fetch // Use node-fetch if available, otherwise fallback to global fetch
let fetchImpl: typeof fetch; let fetchImpl: typeof fetch;
@ -418,6 +420,16 @@ class HDRezkaService {
try { try {
logger.log(`[HDRezka] Getting streams for ${mediaType} with ID: ${mediaId}`); logger.log(`[HDRezka] Getting streams for ${mediaType} with ID: ${mediaId}`);
// First check if internal providers are enabled
const settingsJson = await AsyncStorage.getItem('app_settings');
if (settingsJson) {
const settings = JSON.parse(settingsJson);
if (settings.enableInternalProviders === false) {
logger.log('[HDRezka] Internal providers are disabled in settings, skipping HDRezka');
return [];
}
}
// First, extract the actual title from TMDB if this is an ID // First, extract the actual title from TMDB if this is an ID
let title = mediaId; let title = mediaId;
let year: number | undefined = undefined; let year: number | undefined = undefined;