diff --git a/src/screens/PluginsScreen.tsx b/src/screens/PluginsScreen.tsx index 0fc774a..cafd48a 100644 --- a/src/screens/PluginsScreen.tsx +++ b/src/screens/PluginsScreen.tsx @@ -1273,6 +1273,27 @@ const PluginsScreen: React.FC = () => { const handleToggleLocalScrapers = async (enabled: boolean) => { await updateSetting('enableLocalScrapers', enabled); + + // If enabling local scrapers, refresh repository and reload scrapers + if (enabled) { + try { + setIsRefreshing(true); + logger.log('[PluginsScreen] Enabling local scrapers - refreshing repository...'); + + // Refresh repository to ensure scrapers are available + await localScraperService.refreshRepository(); + + // Reload scrapers to get the latest state + await loadScrapers(); + + logger.log('[PluginsScreen] Local scrapers enabled and repository refreshed'); + } catch (error) { + logger.error('[PluginsScreen] Failed to refresh repository when enabling local scrapers:', error); + // Don't show error to user as the toggle still succeeded + } finally { + setIsRefreshing(false); + } + } }; const handleToggleUrlValidation = async (enabled: boolean) => { diff --git a/src/screens/StreamsScreen.tsx b/src/screens/StreamsScreen.tsx index b8d22b6..582566d 100644 --- a/src/screens/StreamsScreen.tsx +++ b/src/screens/StreamsScreen.tsx @@ -1481,14 +1481,28 @@ export const StreamsScreen = () => { const installedAddons = stremioService.getInstalledAddons(); const streams = metadata?.videos && metadata.videos.length > 1 && selectedEpisode ? episodeStreams : groupedStreams; - // Make sure we include all providers with streams, not just those in availableProviders + // Only include providers that actually have streams + const providersWithStreams = Object.keys(streams).filter(key => { + const providerData = streams[key]; + if (!providerData || !providerData.streams) { + return false; + } + + // For addons, show them even if they have no streams (they might be loading) + const isInstalledAddon = installedAddons.some(addon => addon.id === key); + if (isInstalledAddon) { + return true; + } + + // For plugins, only show if they have actual streams + return providerData.streams.length > 0; + }); + const allProviders = new Set([ - ...availableProviders, - ...Object.keys(streams).filter(key => - streams[key] && - streams[key].streams && - streams[key].streams.length > 0 - ) + ...Array.from(availableProviders).filter((provider: string) => + streams[provider] && streams[provider].streams && streams[provider].streams.length > 0 + ), + ...providersWithStreams ]); // In grouped mode, separate addons and plugins @@ -1519,7 +1533,7 @@ export const StreamsScreen = () => { filterChips.push({ id: provider, name: installedAddon?.name || provider }); }); - // Add single grouped plugins chip if there are any plugins + // Add single grouped plugins chip if there are any plugins with streams if (pluginProviders.length > 0) { filterChips.push({ id: 'grouped-plugins', name: localScraperService.getRepositoryName() }); } @@ -1774,6 +1788,11 @@ export const StreamsScreen = () => { }); } + // Exclude providers with no streams at all + if (filteredStreams.length === 0) { + return null; // Return null to exclude this section completely + } + if (isEmptyDueToQualityFilter) { return null; // Return null to exclude this section completely } diff --git a/src/services/localScraperService.ts b/src/services/localScraperService.ts index ff7e801..bbd37f9 100644 --- a/src/services/localScraperService.ts +++ b/src/services/localScraperService.ts @@ -864,6 +864,30 @@ class LocalScraperService { async getStreams(type: string, tmdbId: string, season?: number, episode?: number, callback?: ScraperCallback): Promise { await this.ensureInitialized(); + // Check if local scrapers are enabled + const userSettings = await this.getUserScraperSettings(); + if (!userSettings.enableLocalScrapers) { + logger.log('[LocalScraperService] Local scrapers are disabled'); + return; + } + + // If no repository is configured, return early + if (!this.repositoryUrl) { + logger.log('[LocalScraperService] No repository URL configured'); + return; + } + + // If no scrapers are installed, try to refresh repository + if (this.installedScrapers.size === 0) { + logger.log('[LocalScraperService] No scrapers installed, attempting to refresh repository'); + try { + await this.performRepositoryRefresh(); + } catch (error) { + logger.error('[LocalScraperService] Failed to refresh repository for getStreams:', error); + return; + } + } + // Get available scrapers from manifest (respects manifestEnabled) const availableScrapers = await this.getAvailableScrapers(); const enabledScrapers = availableScrapers @@ -1299,6 +1323,23 @@ class LocalScraperService { return false; } + // If no repository is configured, return false + if (!this.repositoryUrl) { + logger.log('[LocalScraperService] No repository URL configured'); + return false; + } + + // If no scrapers are installed, try to refresh repository + if (this.installedScrapers.size === 0) { + logger.log('[LocalScraperService] No scrapers installed, attempting to refresh repository'); + try { + await this.performRepositoryRefresh(); + } catch (error) { + logger.error('[LocalScraperService] Failed to refresh repository for hasScrapers check:', error); + return false; + } + } + // Check if there are any enabled scrapers based on user settings if (userSettings.enabledScrapers && userSettings.enabledScrapers.size > 0) { return true;