mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-27 03:22:53 +00:00
Added option to enable/disable tmdb enriched metadata for addons
This commit is contained in:
parent
b0b309b0f1
commit
2a89695b0b
3 changed files with 104 additions and 29 deletions
|
|
@ -12,6 +12,7 @@ import { usePersistentSeasons } from './usePersistentSeasons';
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
import { Stream } from '../types/metadata';
|
import { Stream } from '../types/metadata';
|
||||||
import { storageService } from '../services/storageService';
|
import { storageService } from '../services/storageService';
|
||||||
|
import { useSettings } from './useSettings';
|
||||||
|
|
||||||
// Constants for timeouts and retries
|
// Constants for timeouts and retries
|
||||||
const API_TIMEOUT = 10000; // 10 seconds
|
const API_TIMEOUT = 10000; // 10 seconds
|
||||||
|
|
@ -109,6 +110,7 @@ interface UseMetadataReturn {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadataReturn => {
|
export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadataReturn => {
|
||||||
|
const { settings } = useSettings();
|
||||||
const [metadata, setMetadata] = useState<StreamingContent | null>(null);
|
const [metadata, setMetadata] = useState<StreamingContent | null>(null);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
@ -300,6 +302,11 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
if (__DEV__) logger.log('[loadCast] Starting cast fetch for:', id);
|
if (__DEV__) logger.log('[loadCast] Starting cast fetch for:', id);
|
||||||
setLoadingCast(true);
|
setLoadingCast(true);
|
||||||
try {
|
try {
|
||||||
|
if (!settings.enrichMetadataWithTMDB) {
|
||||||
|
if (__DEV__) logger.log('[loadCast] TMDB enrichment disabled by settings');
|
||||||
|
setLoadingCast(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Check cache first
|
// Check cache first
|
||||||
const cachedCast = cacheService.getCast(id, type);
|
const cachedCast = cacheService.getCast(id, type);
|
||||||
if (cachedCast) {
|
if (cachedCast) {
|
||||||
|
|
@ -394,6 +401,22 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
// Handle TMDB-specific IDs
|
// Handle TMDB-specific IDs
|
||||||
let actualId = id;
|
let actualId = id;
|
||||||
if (id.startsWith('tmdb:')) {
|
if (id.startsWith('tmdb:')) {
|
||||||
|
// If enrichment disabled, resolve to an addon-friendly ID (IMDb) before calling addons
|
||||||
|
if (!settings.enrichMetadataWithTMDB) {
|
||||||
|
const tmdbRaw = id.split(':')[1];
|
||||||
|
try {
|
||||||
|
if (__DEV__) logger.log('[loadMetadata] enrichment=OFF; resolving TMDB→Stremio ID', { type, tmdbId: tmdbRaw });
|
||||||
|
const stremioId = await catalogService.getStremioId(type === 'series' ? 'tv' : 'movie', tmdbRaw);
|
||||||
|
if (stremioId) {
|
||||||
|
actualId = stremioId;
|
||||||
|
if (__DEV__) logger.log('[loadMetadata] resolved TMDB→Stremio ID', { actualId });
|
||||||
|
} else {
|
||||||
|
if (__DEV__) logger.warn('[loadMetadata] failed to resolve TMDB→Stremio ID; addon fetch may fail', { type, tmdbId: tmdbRaw });
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (__DEV__) logger.error('[loadMetadata] error resolving TMDB→Stremio ID', e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
const tmdbId = id.split(':')[1];
|
const tmdbId = id.split(':')[1];
|
||||||
// For TMDB IDs, we need to handle metadata differently
|
// For TMDB IDs, we need to handle metadata differently
|
||||||
if (type === 'movie') {
|
if (type === 'movie') {
|
||||||
|
|
@ -539,9 +562,11 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
logger.error('Failed to fetch TV show details from TMDB:', error);
|
logger.error('Failed to fetch TV show details from TMDB:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load all data in parallel
|
// Load all data in parallel
|
||||||
|
if (__DEV__) logger.log('[loadMetadata] fetching addon metadata', { type, actualId, addonId });
|
||||||
const [content, castData] = await Promise.allSettled([
|
const [content, castData] = await Promise.allSettled([
|
||||||
// Load content with timeout and retry
|
// Load content with timeout and retry
|
||||||
withRetry(async () => {
|
withRetry(async () => {
|
||||||
|
|
@ -553,6 +578,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
if (actualId.startsWith('tt')) {
|
if (actualId.startsWith('tt')) {
|
||||||
setImdbId(actualId);
|
setImdbId(actualId);
|
||||||
}
|
}
|
||||||
|
if (__DEV__) logger.log('[loadMetadata] addon metadata fetched', { hasResult: Boolean(result) });
|
||||||
return result;
|
return result;
|
||||||
}),
|
}),
|
||||||
// Start loading cast immediately in parallel
|
// Start loading cast immediately in parallel
|
||||||
|
|
@ -560,6 +586,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (content.status === 'fulfilled' && content.value) {
|
if (content.status === 'fulfilled' && content.value) {
|
||||||
|
if (__DEV__) logger.log('[loadMetadata] addon metadata:success', { id: content.value?.id, type: content.value?.type, name: content.value?.name });
|
||||||
setMetadata(content.value);
|
setMetadata(content.value);
|
||||||
// Check if item is in library
|
// Check if item is in library
|
||||||
const isInLib = catalogService.getLibraryItems().some(item => item.id === id);
|
const isInLib = catalogService.getLibraryItems().some(item => item.id === id);
|
||||||
|
|
@ -571,6 +598,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
// Update cache
|
// Update cache
|
||||||
cacheService.setMetadata(id, type, content.value);
|
cacheService.setMetadata(id, type, content.value);
|
||||||
} else {
|
} else {
|
||||||
|
if (__DEV__) logger.warn('[loadMetadata] addon metadata:not found or failed', { status: content.status, reason: (content as any)?.reason?.message });
|
||||||
throw new Error('Content not found');
|
throw new Error('Content not found');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -636,29 +664,33 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
|
|
||||||
if (__DEV__) logger.log(`📺 Processed addon episodes into ${Object.keys(groupedAddonEpisodes).length} seasons`);
|
if (__DEV__) logger.log(`📺 Processed addon episodes into ${Object.keys(groupedAddonEpisodes).length} seasons`);
|
||||||
|
|
||||||
// Fetch season posters from TMDB
|
// Fetch season posters from TMDB only if enrichment is enabled; otherwise skip quietly
|
||||||
try {
|
if (settings.enrichMetadataWithTMDB) {
|
||||||
const tmdbIdToUse = tmdbId || (id.startsWith('tt') ? await tmdbService.findTMDBIdByIMDB(id) : null);
|
try {
|
||||||
if (tmdbIdToUse) {
|
const tmdbIdToUse = tmdbId || (id.startsWith('tt') ? await tmdbService.findTMDBIdByIMDB(id) : null);
|
||||||
if (!tmdbId) setTmdbId(tmdbIdToUse);
|
if (tmdbIdToUse) {
|
||||||
const showDetails = await tmdbService.getTVShowDetails(tmdbIdToUse);
|
if (!tmdbId) setTmdbId(tmdbIdToUse);
|
||||||
if (showDetails?.seasons) {
|
const showDetails = await tmdbService.getTVShowDetails(tmdbIdToUse);
|
||||||
Object.keys(groupedAddonEpisodes).forEach(seasonStr => {
|
if (showDetails?.seasons) {
|
||||||
const seasonNum = parseInt(seasonStr, 10);
|
Object.keys(groupedAddonEpisodes).forEach(seasonStr => {
|
||||||
const seasonInfo = showDetails.seasons.find(s => s.season_number === seasonNum);
|
const seasonNum = parseInt(seasonStr, 10);
|
||||||
const seasonPosterPath = seasonInfo?.poster_path;
|
const seasonInfo = showDetails.seasons.find(s => s.season_number === seasonNum);
|
||||||
if (seasonPosterPath) {
|
const seasonPosterPath = seasonInfo?.poster_path;
|
||||||
groupedAddonEpisodes[seasonNum] = groupedAddonEpisodes[seasonNum].map(ep => ({
|
if (seasonPosterPath) {
|
||||||
...ep,
|
groupedAddonEpisodes[seasonNum] = groupedAddonEpisodes[seasonNum].map(ep => ({
|
||||||
season_poster_path: seasonPosterPath,
|
...ep,
|
||||||
}));
|
season_poster_path: seasonPosterPath,
|
||||||
}
|
}));
|
||||||
});
|
}
|
||||||
if (__DEV__) logger.log('🖼️ Successfully fetched and attached TMDB season posters to addon episodes.');
|
});
|
||||||
|
if (__DEV__) logger.log('🖼️ Successfully fetched and attached TMDB season posters to addon episodes.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to fetch TMDB season posters for addon episodes:', error);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} else {
|
||||||
logger.error('Failed to fetch TMDB season posters for addon episodes:', error);
|
if (__DEV__) logger.log('[loadSeriesData] TMDB enrichment disabled; skipping season poster fetch');
|
||||||
}
|
}
|
||||||
|
|
||||||
setGroupedEpisodes(groupedAddonEpisodes);
|
setGroupedEpisodes(groupedAddonEpisodes);
|
||||||
|
|
@ -680,6 +712,10 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to get TMDB ID for additional metadata (cast, etc.) but don't override episodes
|
// Try to get TMDB ID for additional metadata (cast, etc.) but don't override episodes
|
||||||
|
if (!settings.enrichMetadataWithTMDB) {
|
||||||
|
if (__DEV__) logger.log('[loadSeriesData] TMDB enrichment disabled; skipping TMDB episode fallback (preserving current episodes)');
|
||||||
|
return;
|
||||||
|
}
|
||||||
const tmdbIdResult = await tmdbService.findTMDBIdByIMDB(id);
|
const tmdbIdResult = await tmdbService.findTMDBIdByIMDB(id);
|
||||||
if (tmdbIdResult) {
|
if (tmdbIdResult) {
|
||||||
setTmdbId(tmdbIdResult);
|
setTmdbId(tmdbIdResult);
|
||||||
|
|
@ -1078,11 +1114,11 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
if (metadata?.imdb_id) {
|
if (metadata?.imdb_id) {
|
||||||
// Replace the series ID in episodeId with the IMDb ID
|
// Replace the series ID in episodeId with the IMDb ID
|
||||||
const [, season, episode] = episodeId.split(':');
|
const [, season, episode] = episodeId.split(':');
|
||||||
stremioEpisodeId = `series:${metadata.imdb_id}:${season}:${episode}`;
|
stremioEpisodeId = `${metadata.imdb_id}:${season}:${episode}`;
|
||||||
if (__DEV__) console.log('✅ [loadEpisodeStreams] Using IMDb ID from metadata for Stremio episode:', stremioEpisodeId);
|
if (__DEV__) console.log('✅ [loadEpisodeStreams] Using IMDb ID from metadata for Stremio episode:', stremioEpisodeId);
|
||||||
} else if (imdbId) {
|
} else if (imdbId) {
|
||||||
const [, season, episode] = episodeId.split(':');
|
const [, season, episode] = episodeId.split(':');
|
||||||
stremioEpisodeId = `series:${imdbId}:${season}:${episode}`;
|
stremioEpisodeId = `${imdbId}:${season}:${episode}`;
|
||||||
if (__DEV__) console.log('✅ [loadEpisodeStreams] Using stored IMDb ID for Stremio episode:', stremioEpisodeId);
|
if (__DEV__) console.log('✅ [loadEpisodeStreams] Using stored IMDb ID for Stremio episode:', stremioEpisodeId);
|
||||||
} else {
|
} else {
|
||||||
// Convert TMDB ID to IMDb ID for Stremio addons
|
// Convert TMDB ID to IMDb ID for Stremio addons
|
||||||
|
|
@ -1091,7 +1127,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
|
|
||||||
if (externalIds?.imdb_id) {
|
if (externalIds?.imdb_id) {
|
||||||
const [, season, episode] = episodeId.split(':');
|
const [, season, episode] = episodeId.split(':');
|
||||||
stremioEpisodeId = `series:${externalIds.imdb_id}:${season}:${episode}`;
|
stremioEpisodeId = `${externalIds.imdb_id}:${season}:${episode}`;
|
||||||
if (__DEV__) console.log('✅ [loadEpisodeStreams] Converted TMDB to IMDb ID for Stremio episode:', stremioEpisodeId);
|
if (__DEV__) console.log('✅ [loadEpisodeStreams] Converted TMDB to IMDb ID for Stremio episode:', stremioEpisodeId);
|
||||||
} else {
|
} else {
|
||||||
if (__DEV__) console.log('⚠️ [loadEpisodeStreams] No IMDb ID found for TMDB ID, using original episode ID:', stremioEpisodeId);
|
if (__DEV__) console.log('⚠️ [loadEpisodeStreams] No IMDb ID found for TMDB ID, using original episode ID:', stremioEpisodeId);
|
||||||
|
|
@ -1105,6 +1141,12 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
if (__DEV__) console.log('📝 [loadEpisodeStreams] Converting IMDB ID to TMDB ID...');
|
if (__DEV__) console.log('📝 [loadEpisodeStreams] Converting IMDB ID to TMDB ID...');
|
||||||
tmdbId = await withTimeout(tmdbService.findTMDBIdByIMDB(id), API_TIMEOUT);
|
tmdbId = await withTimeout(tmdbService.findTMDBIdByIMDB(id), API_TIMEOUT);
|
||||||
if (__DEV__) console.log('✅ [loadEpisodeStreams] Converted to TMDB ID:', tmdbId);
|
if (__DEV__) console.log('✅ [loadEpisodeStreams] Converted to TMDB ID:', tmdbId);
|
||||||
|
// Normalize episode id to 'tt:season:episode' format for addons that expect tt prefix
|
||||||
|
const parts = episodeId.split(':');
|
||||||
|
if (parts.length === 3 && parts[0] === 'series') {
|
||||||
|
stremioEpisodeId = `${id}:${parts[1]}:${parts[2]}`;
|
||||||
|
if (__DEV__) console.log('🔧 [loadEpisodeStreams] Normalized episode ID for addons:', stremioEpisodeId);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tmdbId = id;
|
tmdbId = id;
|
||||||
if (__DEV__) console.log('ℹ️ [loadEpisodeStreams] Using ID as both TMDB and Stremio ID:', tmdbId);
|
if (__DEV__) console.log('ℹ️ [loadEpisodeStreams] Using ID as both TMDB and Stremio ID:', tmdbId);
|
||||||
|
|
@ -1212,6 +1254,10 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
}, [metadata?.videos, type]);
|
}, [metadata?.videos, type]);
|
||||||
|
|
||||||
const loadRecommendations = useCallback(async () => {
|
const loadRecommendations = useCallback(async () => {
|
||||||
|
if (!settings.enrichMetadataWithTMDB) {
|
||||||
|
if (__DEV__) console.log('[useMetadata] enrichment disabled; skip recommendations');
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!tmdbId) return;
|
if (!tmdbId) return;
|
||||||
|
|
||||||
setLoadingRecommendations(true);
|
setLoadingRecommendations(true);
|
||||||
|
|
@ -1240,6 +1286,10 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
// Fetch TMDB ID if needed and then recommendations
|
// Fetch TMDB ID if needed and then recommendations
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchTmdbIdAndRecommendations = async () => {
|
const fetchTmdbIdAndRecommendations = async () => {
|
||||||
|
if (!settings.enrichMetadataWithTMDB) {
|
||||||
|
if (__DEV__) console.log('[useMetadata] enrichment disabled; skip TMDB id extraction and certification (extract path)');
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (metadata && !tmdbId) {
|
if (metadata && !tmdbId) {
|
||||||
try {
|
try {
|
||||||
const tmdbService = TMDBService.getInstance();
|
const tmdbService = TMDBService.getInstance();
|
||||||
|
|
@ -1268,23 +1318,29 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchTmdbIdAndRecommendations();
|
fetchTmdbIdAndRecommendations();
|
||||||
}, [metadata, id]);
|
}, [metadata, id, settings.enrichMetadataWithTMDB]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (tmdbId) {
|
if (tmdbId) {
|
||||||
if (__DEV__) console.log('[useMetadata] tmdbId available; loading recommendations and enabling certification checks', { tmdbId });
|
if (settings.enrichMetadataWithTMDB) {
|
||||||
loadRecommendations();
|
if (__DEV__) console.log('[useMetadata] tmdbId available; loading recommendations and enabling certification checks', { tmdbId });
|
||||||
|
loadRecommendations();
|
||||||
|
}
|
||||||
// Reset recommendations when tmdbId changes
|
// Reset recommendations when tmdbId changes
|
||||||
return () => {
|
return () => {
|
||||||
setRecommendations([]);
|
setRecommendations([]);
|
||||||
setLoadingRecommendations(true);
|
setLoadingRecommendations(true);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, [tmdbId, loadRecommendations]);
|
}, [tmdbId, loadRecommendations, settings.enrichMetadataWithTMDB]);
|
||||||
|
|
||||||
// Ensure certification is attached whenever a TMDB id is known and metadata lacks it
|
// Ensure certification is attached whenever a TMDB id is known and metadata lacks it
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const maybeAttachCertification = async () => {
|
const maybeAttachCertification = async () => {
|
||||||
|
if (!settings.enrichMetadataWithTMDB) {
|
||||||
|
if (__DEV__) console.log('[useMetadata] enrichment disabled; skip certification (attach path)');
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (!metadata) {
|
if (!metadata) {
|
||||||
if (__DEV__) console.warn('[useMetadata] skip certification attach: metadata not ready');
|
if (__DEV__) console.warn('[useMetadata] skip certification attach: metadata not ready');
|
||||||
|
|
@ -1311,7 +1367,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
maybeAttachCertification();
|
maybeAttachCertification();
|
||||||
}, [tmdbId, metadata, type]);
|
}, [tmdbId, metadata, type, settings.enrichMetadataWithTMDB]);
|
||||||
|
|
||||||
// Reset tmdbId when id changes
|
// Reset tmdbId when id changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,8 @@ export interface AppSettings {
|
||||||
trailerMuted: boolean; // Default to muted for better user experience
|
trailerMuted: boolean; // Default to muted for better user experience
|
||||||
// AI
|
// AI
|
||||||
aiChatEnabled: boolean; // Enable/disable Ask AI and AI features
|
aiChatEnabled: boolean; // Enable/disable Ask AI and AI features
|
||||||
|
// Metadata enrichment
|
||||||
|
enrichMetadataWithTMDB: boolean; // Use TMDB to enrich metadata (cast, certification, posters, fallbacks)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_SETTINGS: AppSettings = {
|
export const DEFAULT_SETTINGS: AppSettings = {
|
||||||
|
|
@ -124,6 +126,8 @@ export const DEFAULT_SETTINGS: AppSettings = {
|
||||||
trailerMuted: true, // Default to muted for better user experience
|
trailerMuted: true, // Default to muted for better user experience
|
||||||
// AI
|
// AI
|
||||||
aiChatEnabled: false,
|
aiChatEnabled: false,
|
||||||
|
// Metadata enrichment
|
||||||
|
enrichMetadataWithTMDB: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SETTINGS_STORAGE_KEY = 'app_settings';
|
const SETTINGS_STORAGE_KEY = 'app_settings';
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import { logger } from '../utils/logger';
|
||||||
import { useTheme } from '../contexts/ThemeContext';
|
import { useTheme } from '../contexts/ThemeContext';
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import CustomAlert from '../components/CustomAlert';
|
import CustomAlert from '../components/CustomAlert';
|
||||||
|
// (duplicate import removed)
|
||||||
|
|
||||||
const TMDB_API_KEY_STORAGE_KEY = 'tmdb_api_key';
|
const TMDB_API_KEY_STORAGE_KEY = 'tmdb_api_key';
|
||||||
const USE_CUSTOM_TMDB_API_KEY = 'use_custom_tmdb_api_key';
|
const USE_CUSTOM_TMDB_API_KEY = 'use_custom_tmdb_api_key';
|
||||||
|
|
@ -48,6 +49,7 @@ const TMDBSettingsScreen = () => {
|
||||||
const apiKeyInputRef = useRef<TextInput>(null);
|
const apiKeyInputRef = useRef<TextInput>(null);
|
||||||
const { currentTheme } = useTheme();
|
const { currentTheme } = useTheme();
|
||||||
const insets = useSafeAreaInsets();
|
const insets = useSafeAreaInsets();
|
||||||
|
const { settings, updateSetting } = useSettings();
|
||||||
|
|
||||||
const openAlert = (
|
const openAlert = (
|
||||||
title: string,
|
title: string,
|
||||||
|
|
@ -288,6 +290,19 @@ const TMDBSettingsScreen = () => {
|
||||||
keyboardShouldPersistTaps="handled"
|
keyboardShouldPersistTaps="handled"
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
>
|
>
|
||||||
|
<View style={[styles.switchCard, { backgroundColor: currentTheme.colors.elevation2 }]}>
|
||||||
|
<View style={styles.switchTextContainer}>
|
||||||
|
<Text style={[styles.switchTitle, { color: currentTheme.colors.text }]}>Enrich Metadata with TMDb</Text>
|
||||||
|
<Text style={[styles.switchDescription, { color: currentTheme.colors.mediumEmphasis }]}>When enabled, the app augments addon metadata with TMDb for cast, certification, logos/posters, and episode fallback. Disable to strictly use addon metadata only.</Text>
|
||||||
|
</View>
|
||||||
|
<Switch
|
||||||
|
value={settings.enrichMetadataWithTMDB}
|
||||||
|
onValueChange={(v) => updateSetting('enrichMetadataWithTMDB', v)}
|
||||||
|
trackColor={{ false: 'rgba(255,255,255,0.1)', true: currentTheme.colors.primary }}
|
||||||
|
thumbColor={Platform.OS === 'android' ? (settings.enrichMetadataWithTMDB ? currentTheme.colors.white : currentTheme.colors.white) : ''}
|
||||||
|
ios_backgroundColor={'rgba(255,255,255,0.1)'}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
<View style={[styles.switchCard, { backgroundColor: currentTheme.colors.elevation2 }]}>
|
<View style={[styles.switchCard, { backgroundColor: currentTheme.colors.elevation2 }]}>
|
||||||
<View style={styles.switchTextContainer}>
|
<View style={styles.switchTextContainer}>
|
||||||
<Text style={[styles.switchTitle, { color: currentTheme.colors.text }]}>Use Custom TMDb API Key</Text>
|
<Text style={[styles.switchTitle, { color: currentTheme.colors.text }]}>Use Custom TMDb API Key</Text>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue