mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-24 03:27:43 +00:00
logs cleanup
This commit is contained in:
parent
b15b01d1f5
commit
741550d72d
20 changed files with 218 additions and 413 deletions
2
App.tsx
2
App.tsx
|
|
@ -195,11 +195,9 @@ const ThemedApp = () => {
|
|||
|
||||
// Initialize memory monitoring service to prevent OutOfMemoryError
|
||||
memoryMonitorService; // Just accessing it starts the monitoring
|
||||
console.log('Memory monitoring service initialized');
|
||||
|
||||
// Initialize AI service
|
||||
await aiService.initialize();
|
||||
console.log('AI service initialized');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error initializing app:', error);
|
||||
|
|
|
|||
|
|
@ -76,9 +76,7 @@ const LoadingSpinner: React.FC<LoadingSpinnerProps> = ({
|
|||
renderMode: 'SOFTWARE' as any, // Fallback to software rendering if hardware fails
|
||||
})}
|
||||
// Error handling
|
||||
onAnimationFinish={() => {
|
||||
if (__DEV__) console.log('Lottie animation finished');
|
||||
}}
|
||||
onAnimationFinish={() => {}}
|
||||
onAnimationFailure={(error) => {
|
||||
if (__DEV__) console.warn('Lottie animation failed:', error);
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -76,9 +76,7 @@ const LoadingSpinner: React.FC<LoadingSpinnerProps> = ({
|
|||
renderMode: 'SOFTWARE' as any, // Fallback to software rendering if hardware fails
|
||||
})}
|
||||
// Error handling
|
||||
onAnimationFinish={() => {
|
||||
if (__DEV__) console.log('Lottie animation finished');
|
||||
}}
|
||||
onAnimationFinish={() => {}}
|
||||
onAnimationFailure={(error) => {
|
||||
if (__DEV__) console.warn('Lottie animation failed:', error);
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import Animated, {
|
|||
Extrapolate,
|
||||
} from 'react-native-reanimated';
|
||||
import { useTheme } from '../../contexts/ThemeContext';
|
||||
import { isMDBListEnabled } from '../../screens/MDBListSettingsScreen';
|
||||
import { isMDBListEnabled } from '../../services/mdblistConstants';
|
||||
import { getAgeRatingColor } from '../../utils/ageRatingColors';
|
||||
import AgeRatingBadge from '../common/AgeRatingBadge';
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { useTheme } from '../../contexts/ThemeContext';
|
|||
import FastImage from '@d11/react-native-fast-image';
|
||||
import { useMDBListRatings } from '../../hooks/useMDBListRatings';
|
||||
import { mmkvStorage } from '../../services/mmkvStorage';
|
||||
import { isMDBListEnabled, RATING_PROVIDERS_STORAGE_KEY } from '../../screens/MDBListSettingsScreen';
|
||||
import { isMDBListEnabled, RATING_PROVIDERS_STORAGE_KEY } from '../../services/mdblistConstants';
|
||||
|
||||
// Import SVG icons
|
||||
import LetterboxdIcon from '../../../assets/rating-icons/letterboxd.svg';
|
||||
|
|
|
|||
|
|
@ -15,10 +15,18 @@ import { useFocusEffect } from '@react-navigation/native';
|
|||
import Animated, { FadeIn, FadeOut, SlideInRight, SlideOutLeft } from 'react-native-reanimated';
|
||||
import { TraktService } from '../../services/traktService';
|
||||
import { watchedService } from '../../services/watchedService';
|
||||
import { logger } from '../../utils/logger';
|
||||
import { mmkvStorage } from '../../services/mmkvStorage';
|
||||
import { MalSync } from '../../services/mal/MalSync';
|
||||
|
||||
const noop = (..._args: unknown[]) => {};
|
||||
const logger = {
|
||||
log: noop,
|
||||
error: noop,
|
||||
warn: noop,
|
||||
info: noop,
|
||||
debug: noop,
|
||||
};
|
||||
|
||||
// ... other imports
|
||||
const BREAKPOINTS = {
|
||||
phone: 0,
|
||||
|
|
@ -212,10 +220,10 @@ const SeriesContentComponent: React.FC<SeriesContentProps> = ({
|
|||
const savedMode = await mmkvStorage.getItem('global_season_view_mode');
|
||||
if (savedMode === 'text' || savedMode === 'posters') {
|
||||
setSeasonViewMode(savedMode);
|
||||
if (__DEV__) console.log('[SeriesContent] Loaded global view mode:', savedMode);
|
||||
if (__DEV__) logger.log('[SeriesContent] Loaded global view mode:', savedMode);
|
||||
}
|
||||
} catch (error) {
|
||||
if (__DEV__) console.log('[SeriesContent] Error loading global view mode preference:', error);
|
||||
if (__DEV__) logger.log('[SeriesContent] Error loading global view mode preference:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -239,7 +247,7 @@ const SeriesContentComponent: React.FC<SeriesContentProps> = ({
|
|||
const updateViewMode = (newMode: 'posters' | 'text') => {
|
||||
setSeasonViewMode(newMode);
|
||||
mmkvStorage.setItem('global_season_view_mode', newMode).catch((error: any) => {
|
||||
if (__DEV__) console.log('[SeriesContent] Error saving global view mode preference:', error);
|
||||
if (__DEV__) logger.log('[SeriesContent] Error saving global view mode preference:', error);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -491,7 +499,7 @@ const SeriesContentComponent: React.FC<SeriesContentProps> = ({
|
|||
useEffect(() => {
|
||||
return () => {
|
||||
// Clear any pending timeouts
|
||||
if (__DEV__) console.log('[SeriesContent] Component unmounted, cleaning up memory');
|
||||
if (__DEV__) logger.log('[SeriesContent] Component unmounted, cleaning up memory');
|
||||
|
||||
// Force garbage collection if available (development only)
|
||||
if (__DEV__ && global.gc) {
|
||||
|
|
@ -854,7 +862,7 @@ const SeriesContentComponent: React.FC<SeriesContentProps> = ({
|
|||
onPress={() => {
|
||||
const newMode = seasonViewMode === 'posters' ? 'text' : 'posters';
|
||||
updateViewMode(newMode);
|
||||
if (__DEV__) console.log('[SeriesContent] View mode changed to:', newMode, 'Current ref value:', seasonViewMode);
|
||||
if (__DEV__) logger.log('[SeriesContent] View mode changed to:', newMode, 'Current ref value:', seasonViewMode);
|
||||
}}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -17,12 +17,20 @@ import FastImage from '@d11/react-native-fast-image';
|
|||
import { useTheme } from '../../contexts/ThemeContext';
|
||||
import { useSettings } from '../../hooks/useSettings';
|
||||
import { useTrailer } from '../../contexts/TrailerContext';
|
||||
import { logger } from '../../utils/logger';
|
||||
import TrailerService from '../../services/trailerService';
|
||||
import { TMDBService } from '../../services/tmdbService';
|
||||
import TrailerModal from './TrailerModal';
|
||||
import Animated, { useSharedValue, withTiming, withDelay, useAnimatedStyle } from 'react-native-reanimated';
|
||||
|
||||
const noop = (..._args: unknown[]) => {};
|
||||
const logger = {
|
||||
log: noop,
|
||||
error: noop,
|
||||
warn: noop,
|
||||
info: noop,
|
||||
debug: noop,
|
||||
};
|
||||
|
||||
// Enhanced responsive breakpoints for Trailers Section
|
||||
const BREAKPOINTS = {
|
||||
phone: 0,
|
||||
|
|
|
|||
|
|
@ -216,11 +216,9 @@ export const CampaignManager: React.FC = () => {
|
|||
|
||||
const checkForCampaigns = useCallback(async () => {
|
||||
try {
|
||||
console.log('[CampaignManager] Checking for campaigns...');
|
||||
await new Promise(resolve => setTimeout(resolve, 1500));
|
||||
|
||||
const campaign = await campaignService.getActiveCampaign();
|
||||
console.log('[CampaignManager] Got campaign:', campaign?.id, campaign?.type);
|
||||
|
||||
if (campaign) {
|
||||
setActiveCampaign(campaign);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import { mdblistService, MDBListRatings } from '../services/mdblistService';
|
||||
import { logger } from '../utils/logger';
|
||||
import { isMDBListEnabled } from '../screens/MDBListSettingsScreen';
|
||||
import { isMDBListEnabled } from '../services/mdblistConstants';
|
||||
|
||||
export const useMDBListRatings = (imdbId: string, mediaType: 'movie' | 'show') => {
|
||||
const [ratings, setRatings] = useState<MDBListRatings | null>(null);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import { cacheService } from '../services/cacheService';
|
|||
import { localScraperService, ScraperInfo } from '../services/pluginService';
|
||||
import { Cast, Episode, GroupedEpisodes, GroupedStreams } from '../types/metadata';
|
||||
import { TMDBService } from '../services/tmdbService';
|
||||
import { logger } from '../utils/logger';
|
||||
import { usePersistentSeasons } from './usePersistentSeasons';
|
||||
import { mmkvStorage } from '../services/mmkvStorage';
|
||||
import { Stream } from '../types/metadata';
|
||||
|
|
@ -15,6 +14,15 @@ import { storageService } from '../services/storageService';
|
|||
import { useSettings } from './useSettings';
|
||||
import { MalSync } from '../services/mal/MalSync';
|
||||
|
||||
const noop = (..._args: unknown[]) => {};
|
||||
const logger = {
|
||||
log: noop,
|
||||
error: noop,
|
||||
warn: noop,
|
||||
info: noop,
|
||||
debug: noop,
|
||||
};
|
||||
|
||||
// Constants for timeouts and retries
|
||||
const API_TIMEOUT = 10000; // 10 seconds
|
||||
const MAX_RETRIES = 1; // Reduced since stremioService already retries
|
||||
|
|
@ -163,8 +171,6 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
|
||||
// Memory optimization: Stream cleanup and garbage collection
|
||||
const cleanupStreams = useCallback(() => {
|
||||
if (__DEV__) console.log('[useMetadata] Running stream cleanup to free memory');
|
||||
|
||||
// Clear preloaded streams cache
|
||||
setPreloadedStreams({});
|
||||
setPreloadedEpisodeStreams({});
|
||||
|
|
@ -222,25 +228,11 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
(streams, addonId, addonName, error, installationId) => {
|
||||
const processTime = Date.now() - sourceStartTime;
|
||||
|
||||
console.log('🔍 [processStremioSource] Callback received:', {
|
||||
addonId,
|
||||
addonName,
|
||||
installationId,
|
||||
streamCount: streams?.length || 0,
|
||||
error: error?.message || null,
|
||||
processTime
|
||||
});
|
||||
|
||||
// ALWAYS remove from active fetching list when callback is received
|
||||
// This ensures that even failed scrapers are removed from the "Fetching from:" chip
|
||||
if (addonName) {
|
||||
setActiveFetchingScrapers(prev => {
|
||||
const updated = prev.filter(name => name !== addonName);
|
||||
console.log('🔍 [processStremioSource] Removing from activeFetchingScrapers:', {
|
||||
addonName,
|
||||
before: prev,
|
||||
after: updated
|
||||
});
|
||||
return updated;
|
||||
});
|
||||
}
|
||||
|
|
@ -496,18 +488,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
|
||||
const loadMetadata = async () => {
|
||||
try {
|
||||
console.log('🚀 [useMetadata] loadMetadata CALLED for:', { id, type });
|
||||
console.log('🔍 [useMetadata] loadMetadata started:', {
|
||||
id,
|
||||
type,
|
||||
addonId,
|
||||
loadAttempts,
|
||||
maxRetries: MAX_RETRIES,
|
||||
settingsLoaded: settingsLoaded
|
||||
});
|
||||
|
||||
if (loadAttempts >= MAX_RETRIES) {
|
||||
console.log('🔍 [useMetadata] Max retries exceeded:', { loadAttempts, maxRetries: MAX_RETRIES });
|
||||
setError(`Failed to load content after ${MAX_RETRIES + 1} attempts. Please check your connection and try again.`);
|
||||
setLoading(false);
|
||||
return;
|
||||
|
|
@ -520,14 +501,6 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
// Check metadata screen cache
|
||||
const cachedScreen = cacheService.getMetadataScreen(id, normalizedType);
|
||||
if (cachedScreen) {
|
||||
console.log('🔍 [useMetadata] Using cached metadata:', {
|
||||
id,
|
||||
type,
|
||||
hasMetadata: !!cachedScreen.metadata,
|
||||
hasCast: !!cachedScreen.cast,
|
||||
hasEpisodes: !!cachedScreen.episodes,
|
||||
tmdbId: cachedScreen.tmdbId
|
||||
});
|
||||
setMetadata(cachedScreen.metadata);
|
||||
setCast(cachedScreen.cast);
|
||||
if (normalizedType === 'series' && cachedScreen.episodes) {
|
||||
|
|
@ -545,7 +518,6 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
setLoading(false);
|
||||
return;
|
||||
} else {
|
||||
console.log('🔍 [useMetadata] No cached metadata found, proceeding with fresh fetch');
|
||||
}
|
||||
|
||||
// Handle TMDB-specific IDs
|
||||
|
|
@ -556,7 +528,6 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
// STRICT MODE: Do NOT convert to IMDb/Cinemeta.
|
||||
// We want to force the app to use AnimeKitsu (or other MAL-compatible addons) for metadata.
|
||||
// This ensures we get correct Season/Episode mapping (Separate entries) instead of Cinemeta's "S1E26" mess.
|
||||
console.log('🔍 [useMetadata] Keeping MAL ID for metadata fetch:', id);
|
||||
|
||||
// Note: Stream fetching (stremioService) WILL still convert this to IMDb secretly
|
||||
// to ensure Torrentio works, but the Metadata UI will stay purely MAL-based.
|
||||
|
|
@ -564,13 +535,10 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
|
||||
if (id.startsWith('tmdb:')) {
|
||||
// Always try the original TMDB ID first - let addons decide if they support it
|
||||
console.log('🔍 [useMetadata] TMDB ID detected, trying original ID first:', { originalId: id });
|
||||
|
||||
// If enrichment disabled, try original ID first, then fallback to conversion if needed
|
||||
if (!settings.enrichMetadataWithTMDB) {
|
||||
// Keep the original TMDB ID - let the addon system handle it dynamically
|
||||
actualId = id;
|
||||
console.log('🔍 [useMetadata] TMDB enrichment disabled, using original TMDB ID:', { actualId });
|
||||
} else {
|
||||
const tmdbId = id.split(':')[1];
|
||||
// For TMDB IDs, we need to handle metadata differently
|
||||
|
|
@ -730,7 +698,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
|
||||
// Load series data (episodes)
|
||||
setTmdbId(parseInt(tmdbId));
|
||||
loadSeriesData().catch((error) => { if (__DEV__) console.error(error); });
|
||||
loadSeriesData().catch((error) => { if (__DEV__) logger.error(error); });
|
||||
|
||||
(async () => {
|
||||
const items = await catalogService.getLibraryItems();
|
||||
|
|
@ -749,7 +717,6 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
}
|
||||
|
||||
// Load all data in parallel
|
||||
console.log('🔍 [useMetadata] Starting parallel data fetch:', { type, actualId, addonId, apiTimeout: API_TIMEOUT });
|
||||
if (__DEV__) logger.log('[loadMetadata] fetching addon metadata', { type, actualId, addonId });
|
||||
|
||||
let contentResult: any = null;
|
||||
|
|
@ -761,7 +728,6 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
if (preferExternal) {
|
||||
// Try external meta addons first
|
||||
try {
|
||||
console.log('🔍 [useMetadata] Trying external meta addons first');
|
||||
const [content, castData] = await Promise.allSettled([
|
||||
withRetry(async () => {
|
||||
// Get all installed addons
|
||||
|
|
@ -791,20 +757,17 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
);
|
||||
|
||||
if (result) {
|
||||
console.log('🔍 [useMetadata] Got metadata from external addon:', addon.name);
|
||||
if (actualId.startsWith('tt')) {
|
||||
setImdbId(actualId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('🔍 [useMetadata] External addon failed:', addon.name, error);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If no external addon worked, fall back to catalog addon
|
||||
console.log('🔍 [useMetadata] No external meta addon worked, falling back to catalog addon');
|
||||
const result = await withTimeout(
|
||||
catalogService.getEnhancedContentDetails(normalizedType, actualId, addonId),
|
||||
API_TIMEOUT
|
||||
|
|
@ -819,39 +782,29 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
|
||||
contentResult = content;
|
||||
if (content.status === 'fulfilled' && content.value) {
|
||||
console.log('🔍 [useMetadata] Successfully got metadata with external meta addon priority');
|
||||
if (__DEV__) {
|
||||
logger.log('[useMetadata] External meta addon priority success');
|
||||
}
|
||||
} else {
|
||||
console.log('🔍 [useMetadata] External meta addon priority failed, will try fallback');
|
||||
lastError = (content as any)?.reason;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('🔍 [useMetadata] External meta addon attempt failed:', { error: error instanceof Error ? error.message : String(error) });
|
||||
lastError = error;
|
||||
}
|
||||
} else {
|
||||
// Original behavior: try with original ID first
|
||||
try {
|
||||
console.log('🔍 [useMetadata] Attempting metadata fetch with original ID:', { type, actualId, addonId });
|
||||
const [content, castData] = await Promise.allSettled([
|
||||
// Load content with timeout and retry
|
||||
withRetry(async () => {
|
||||
console.log('⚡ [useMetadata] Calling catalogService.getEnhancedContentDetails...');
|
||||
console.log('🔍 [useMetadata] Calling catalogService.getEnhancedContentDetails:', { type, actualId, addonId });
|
||||
const result = await withTimeout(
|
||||
catalogService.getEnhancedContentDetails(normalizedType, actualId, addonId),
|
||||
API_TIMEOUT
|
||||
);
|
||||
console.log('✅ [useMetadata] catalogService returned:', result ? 'DATA' : 'NULL');
|
||||
// Store the actual ID used (could be IMDB)
|
||||
if (actualId.startsWith('tt')) {
|
||||
setImdbId(actualId);
|
||||
}
|
||||
console.log('🔍 [useMetadata] catalogService.getEnhancedContentDetails result:', {
|
||||
hasResult: Boolean(result),
|
||||
resultId: result?.id,
|
||||
resultName: result?.name,
|
||||
resultType: result?.type
|
||||
});
|
||||
if (__DEV__) logger.log('[loadMetadata] addon metadata fetched', { hasResult: Boolean(result) });
|
||||
return result;
|
||||
}),
|
||||
|
|
@ -861,13 +814,13 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
|
||||
contentResult = content;
|
||||
if (content.status === 'fulfilled' && content.value) {
|
||||
console.log('🔍 [useMetadata] Successfully got metadata with original ID');
|
||||
if (__DEV__) {
|
||||
logger.log('[useMetadata] Original ID metadata fetch succeeded');
|
||||
}
|
||||
} else {
|
||||
console.log('🔍 [useMetadata] Original ID failed, will try fallback conversion');
|
||||
lastError = (content as any)?.reason;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('🔍 [useMetadata] Original ID attempt failed:', { error: error instanceof Error ? error.message : String(error) });
|
||||
lastError = error;
|
||||
}
|
||||
}
|
||||
|
|
@ -875,12 +828,10 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
// If original TMDB ID failed and enrichment is disabled, try ID conversion as fallback
|
||||
if (!contentResult || (contentResult.status === 'fulfilled' && !contentResult.value) || contentResult.status === 'rejected') {
|
||||
if (id.startsWith('tmdb:') && !settings.enrichMetadataWithTMDB) {
|
||||
console.log('🔍 [useMetadata] Original TMDB ID failed, trying ID conversion fallback');
|
||||
const tmdbRaw = id.split(':')[1];
|
||||
try {
|
||||
const stremioId = await catalogService.getStremioId(normalizedType === 'series' ? 'tv' : 'movie', tmdbRaw);
|
||||
if (stremioId && stremioId !== id) {
|
||||
console.log('🔍 [useMetadata] Trying converted ID:', { originalId: id, convertedId: stremioId });
|
||||
const [content, castData] = await Promise.allSettled([
|
||||
withRetry(async () => {
|
||||
const result = await withTimeout(
|
||||
|
|
@ -897,7 +848,9 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
contentResult = content;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('🔍 [useMetadata] ID conversion fallback also failed:', { error: e instanceof Error ? e.message : String(e) });
|
||||
if (__DEV__) {
|
||||
logger.log('[useMetadata] ID conversion fallback failed');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -905,22 +858,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const content = contentResult || { status: 'rejected' as const, reason: lastError || new Error('No content result') };
|
||||
const castData = { status: 'fulfilled' as const, value: undefined };
|
||||
|
||||
console.log('🔍 [useMetadata] Promise.allSettled results:', {
|
||||
contentStatus: content.status,
|
||||
contentFulfilled: content.status === 'fulfilled',
|
||||
hasContentValue: content.status === 'fulfilled' ? !!content.value : false,
|
||||
castStatus: castData.status,
|
||||
castFulfilled: castData.status === 'fulfilled'
|
||||
});
|
||||
|
||||
if (content.status === 'fulfilled' && content.value) {
|
||||
console.log('🔍 [useMetadata] Content fetch successful:', {
|
||||
id: content.value?.id,
|
||||
type: content.value?.type,
|
||||
name: content.value?.name,
|
||||
hasDescription: !!content.value?.description,
|
||||
hasPoster: !!content.value?.poster
|
||||
});
|
||||
if (__DEV__) logger.log('[loadMetadata] addon metadata:success', { id: content.value?.id, type: content.value?.type, name: content.value?.name });
|
||||
|
||||
// Start with addon metadata
|
||||
|
|
@ -1025,7 +963,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (__DEV__) console.log('[useMetadata] failed to merge TMDB title/description', e);
|
||||
if (__DEV__) logger.log('[useMetadata] failed to merge TMDB title/description', e);
|
||||
}
|
||||
|
||||
// Centralized logo fetching logic
|
||||
|
|
@ -1050,7 +988,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
// Use TMDB logo if found, otherwise fall back to addon logo
|
||||
finalMetadata.logo = logoUrl || addonLogo || undefined;
|
||||
if (__DEV__) {
|
||||
console.log('[useMetadata] Logo fetch result:', {
|
||||
logger.log('[useMetadata] Logo fetch result:', {
|
||||
contentType,
|
||||
tmdbIdForLogo,
|
||||
preferredLanguage,
|
||||
|
|
@ -1062,13 +1000,13 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
} else {
|
||||
// No TMDB ID, fall back to addon logo
|
||||
finalMetadata.logo = addonLogo || undefined;
|
||||
if (__DEV__) console.log('[useMetadata] No TMDB ID found for logo, using addon logo');
|
||||
if (__DEV__) logger.log('[useMetadata] No TMDB ID found for logo, using addon logo');
|
||||
}
|
||||
} else {
|
||||
// When enrichment or logos is OFF, use addon logo
|
||||
finalMetadata.logo = addonLogo || finalMetadata.logo || undefined;
|
||||
if (__DEV__) {
|
||||
console.log('[useMetadata] TMDB logo enrichment disabled, using addon logo:', {
|
||||
logger.log('[useMetadata] TMDB logo enrichment disabled, using addon logo:', {
|
||||
hasAddonLogo: !!finalMetadata.logo,
|
||||
enrichmentEnabled: settings.enrichMetadataWithTMDB,
|
||||
logosEnabled: settings.tmdbEnrichLogos
|
||||
|
|
@ -1077,7 +1015,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
}
|
||||
} catch (error) {
|
||||
// Handle error silently, keep existing logo behavior
|
||||
if (__DEV__) console.error('[useMetadata] Unexpected error in logo fetch:', error);
|
||||
if (__DEV__) logger.error('[useMetadata] Unexpected error in logo fetch:', error);
|
||||
finalMetadata.logo = undefined;
|
||||
}
|
||||
|
||||
|
|
@ -1114,17 +1052,8 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const reason = (content as any)?.reason;
|
||||
const reasonMessage = reason?.message || String(reason);
|
||||
|
||||
console.log('🔍 [useMetadata] Content fetch failed:', {
|
||||
status: content.status,
|
||||
reason: reasonMessage,
|
||||
fullReason: reason,
|
||||
isAxiosError: reason?.isAxiosError,
|
||||
responseStatus: reason?.response?.status,
|
||||
responseData: reason?.response?.data
|
||||
});
|
||||
|
||||
if (__DEV__) {
|
||||
console.log('[loadMetadata] addon metadata:not found or failed', {
|
||||
logger.log('[loadMetadata] addon metadata:not found or failed', {
|
||||
status: content.status,
|
||||
reason: reasonMessage,
|
||||
fullReason: reason
|
||||
|
|
@ -1139,28 +1068,23 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
reasonMessage.includes('Network Error') ||
|
||||
reasonMessage.includes('Request failed')
|
||||
)) {
|
||||
console.log('🔍 [useMetadata] Detected server/network error, preserving original error');
|
||||
// This was a server/network error, preserve the original error message
|
||||
throw reason instanceof Error ? reason : new Error(reasonMessage);
|
||||
} else {
|
||||
console.log('🔍 [useMetadata] Detected content not found error, throwing generic error');
|
||||
// This was likely a content not found error
|
||||
throw new Error('Content not found');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('🔍 [useMetadata] loadMetadata caught error:', {
|
||||
errorMessage: error instanceof Error ? error.message : String(error),
|
||||
errorType: typeof error,
|
||||
isAxiosError: (error as any)?.isAxiosError,
|
||||
responseStatus: (error as any)?.response?.status,
|
||||
responseData: (error as any)?.response?.data,
|
||||
stack: error instanceof Error ? error.stack : undefined
|
||||
});
|
||||
|
||||
if (__DEV__) {
|
||||
console.error('Failed to load metadata:', error);
|
||||
console.log('Error message being set:', error instanceof Error ? error.message : String(error));
|
||||
logger.log('[loadMetadata] failed with error', {
|
||||
errorMessage: error instanceof Error ? error.message : String(error),
|
||||
errorType: typeof error,
|
||||
isAxiosError: (error as any)?.isAxiosError,
|
||||
responseStatus: (error as any)?.response?.status,
|
||||
responseData: (error as any)?.response?.data,
|
||||
stack: error instanceof Error ? error.stack : undefined
|
||||
});
|
||||
}
|
||||
|
||||
// Preserve the original error details for better error parsing
|
||||
|
|
@ -1173,7 +1097,6 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
setGroupedEpisodes({});
|
||||
setEpisodes([]);
|
||||
} finally {
|
||||
console.log('🔍 [useMetadata] loadMetadata completed, setting loading to false');
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
|
@ -1309,7 +1232,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
if (__DEV__) logger.log('[useMetadata] merged episode names/overviews from TMDB (batch)');
|
||||
}
|
||||
} catch (e) {
|
||||
if (__DEV__) console.log('[useMetadata] failed to merge episode text from TMDB', e);
|
||||
if (__DEV__) logger.log('[useMetadata] failed to merge episode text from TMDB', e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1477,7 +1400,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (__DEV__) console.error('Failed to load episodes:', error);
|
||||
if (__DEV__) logger.error('Failed to load episodes:', error);
|
||||
} finally {
|
||||
setLoadingSeasons(false);
|
||||
}
|
||||
|
|
@ -1531,7 +1454,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
}
|
||||
|
||||
if (allEmbeddedStreams.length > 0) {
|
||||
if (__DEV__) console.log(`✅ [extractEmbeddedStreams] Found ${allEmbeddedStreams.length} embedded streams from ${addonName}`);
|
||||
if (__DEV__) logger.log(`✅ [extractEmbeddedStreams] Found ${allEmbeddedStreams.length} embedded streams from ${addonName}`);
|
||||
|
||||
// Add to grouped streams
|
||||
setGroupedStreams(prevStreams => ({
|
||||
|
|
@ -1566,7 +1489,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
);
|
||||
|
||||
if (episodeVideo && episodeVideo.streams && episodeVideo.streams.length > 0) {
|
||||
if (__DEV__) console.log(`✅ [extractEmbeddedStreams] Found embedded streams for episode ${episodeToUse}`);
|
||||
if (__DEV__) logger.log(`✅ [extractEmbeddedStreams] Found embedded streams for episode ${episodeToUse}`);
|
||||
|
||||
const episodeStreamsList: Stream[] = episodeVideo.streams.map((stream: any) => ({
|
||||
...stream,
|
||||
|
|
@ -1592,7 +1515,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const loadStreams = async () => {
|
||||
const startTime = Date.now();
|
||||
try {
|
||||
if (__DEV__) console.log('🚀 [loadStreams] START - Loading streams for:', id);
|
||||
if (__DEV__) logger.log('🚀 [loadStreams] START - Loading streams for:', id);
|
||||
updateLoadingState();
|
||||
|
||||
// Reset scraper tracking
|
||||
|
|
@ -1600,22 +1523,22 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
setActiveFetchingScrapers([]);
|
||||
setAddonResponseOrder([]); // Reset response order
|
||||
|
||||
if (__DEV__) console.log('🔍 [loadStreams] Getting TMDB ID for:', id);
|
||||
if (__DEV__) logger.log('🔍 [loadStreams] Getting TMDB ID for:', id);
|
||||
let tmdbId;
|
||||
let stremioId = id;
|
||||
let effectiveStreamType: string = type;
|
||||
|
||||
if (id.startsWith('tmdb:')) {
|
||||
tmdbId = id.split(':')[1];
|
||||
if (__DEV__) console.log('✅ [loadStreams] Using TMDB ID from ID:', tmdbId);
|
||||
if (__DEV__) logger.log('✅ [loadStreams] Using TMDB ID from ID:', tmdbId);
|
||||
|
||||
// Try to get IMDb ID from metadata first, then convert if needed
|
||||
if (metadata?.imdb_id) {
|
||||
stremioId = metadata.imdb_id;
|
||||
if (__DEV__) console.log('✅ [loadStreams] Using IMDb ID from metadata for Stremio:', stremioId);
|
||||
if (__DEV__) logger.log('✅ [loadStreams] Using IMDb ID from metadata for Stremio:', stremioId);
|
||||
} else if (imdbId) {
|
||||
stremioId = imdbId;
|
||||
if (__DEV__) console.log('✅ [loadStreams] Using stored IMDb ID for Stremio:', stremioId);
|
||||
if (__DEV__) logger.log('✅ [loadStreams] Using stored IMDb ID for Stremio:', stremioId);
|
||||
} else {
|
||||
// Convert TMDB ID to IMDb ID for Stremio addons (they expect IMDb format)
|
||||
try {
|
||||
|
|
@ -1629,28 +1552,28 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
|
||||
if (externalIds?.imdb_id) {
|
||||
stremioId = externalIds.imdb_id;
|
||||
if (__DEV__) console.log('✅ [loadStreams] Converted TMDB to IMDb ID for Stremio:', stremioId);
|
||||
if (__DEV__) logger.log('✅ [loadStreams] Converted TMDB to IMDb ID for Stremio:', stremioId);
|
||||
} else {
|
||||
if (__DEV__) console.log('⚠️ [loadStreams] No IMDb ID found for TMDB ID, using original:', stremioId);
|
||||
if (__DEV__) logger.log('⚠️ [loadStreams] No IMDb ID found for TMDB ID, using original:', stremioId);
|
||||
}
|
||||
} catch (error) {
|
||||
if (__DEV__) console.log('⚠️ [loadStreams] Failed to convert TMDB to IMDb, using original ID:', error);
|
||||
if (__DEV__) logger.log('⚠️ [loadStreams] Failed to convert TMDB to IMDb, using original ID:', error);
|
||||
}
|
||||
}
|
||||
} else if (id.startsWith('tt')) {
|
||||
// This is already an IMDB ID, perfect for Stremio
|
||||
stremioId = id;
|
||||
if (settings.enrichMetadataWithTMDB) {
|
||||
if (__DEV__) console.log('📝 [loadStreams] Converting IMDB ID to TMDB ID...');
|
||||
if (__DEV__) logger.log('📝 [loadStreams] Converting IMDB ID to TMDB ID...');
|
||||
tmdbId = await withTimeout(tmdbService.findTMDBIdByIMDB(id), API_TIMEOUT);
|
||||
if (__DEV__) console.log('✅ [loadStreams] Converted to TMDB ID:', tmdbId);
|
||||
if (__DEV__) logger.log('✅ [loadStreams] Converted to TMDB ID:', tmdbId);
|
||||
} else {
|
||||
if (__DEV__) console.log('📝 [loadStreams] TMDB enrichment disabled, skipping IMDB to TMDB conversion');
|
||||
if (__DEV__) logger.log('📝 [loadStreams] TMDB enrichment disabled, skipping IMDB to TMDB conversion');
|
||||
}
|
||||
} else {
|
||||
tmdbId = id;
|
||||
stremioId = id;
|
||||
if (__DEV__) console.log('ℹ️ [loadStreams] Using ID as both TMDB and Stremio ID:', tmdbId);
|
||||
if (__DEV__) logger.log('ℹ️ [loadStreams] Using ID as both TMDB and Stremio ID:', tmdbId);
|
||||
}
|
||||
|
||||
// Initialize scraper tracking
|
||||
|
|
@ -1710,14 +1633,14 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
if (fallback.length > 0) {
|
||||
effectiveStreamType = fallbackType;
|
||||
eligibleStreamAddons = fallback;
|
||||
if (__DEV__) console.log(`[useMetadata.loadStreams] No addons for '${requestedStreamType}', falling back to '${fallbackType}'`);
|
||||
if (__DEV__) logger.log(`[useMetadata.loadStreams] No addons for '${requestedStreamType}', falling back to '${fallbackType}'`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const streamAddons = eligibleStreamAddons;
|
||||
if (__DEV__) console.log('[useMetadata.loadStreams] Eligible stream addons:', streamAddons.map(a => a.id), { requestedStreamType, effectiveStreamType });
|
||||
if (__DEV__) logger.log('[useMetadata.loadStreams] Eligible stream addons:', streamAddons.map(a => a.id), { requestedStreamType, effectiveStreamType });
|
||||
|
||||
// Initialize scraper statuses for tracking
|
||||
const initialStatuses: ScraperStatus[] = [];
|
||||
|
|
@ -1764,11 +1687,11 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
setLoadingStreams(false);
|
||||
}
|
||||
} catch (error) {
|
||||
if (__DEV__) console.error('Failed to initialize scraper tracking:', error);
|
||||
if (__DEV__) logger.error('Failed to initialize scraper tracking:', error);
|
||||
}
|
||||
|
||||
// Start Stremio request using the converted ID format
|
||||
if (__DEV__) console.log('🎬 [loadStreams] Using ID for Stremio addons:', stremioId);
|
||||
if (__DEV__) logger.log('🎬 [loadStreams] Using ID for Stremio addons:', stremioId);
|
||||
// Use the effective type we selected when building the eligible addon list.
|
||||
// This stays aligned with Stremio manifest filtering rules and avoids hard-mapping non-standard types.
|
||||
processStremioSource(effectiveStreamType, stremioId, false);
|
||||
|
|
@ -1807,7 +1730,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
}, 60000);
|
||||
|
||||
} catch (error) {
|
||||
if (__DEV__) console.error('❌ [loadStreams] Failed to load streams:', error);
|
||||
if (__DEV__) logger.error('❌ [loadStreams] Failed to load streams:', error);
|
||||
// Preserve the original error details for better error parsing
|
||||
const errorMessage = error instanceof Error ? error.message : 'Failed to load streams';
|
||||
setError(errorMessage);
|
||||
|
|
@ -1818,7 +1741,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const loadEpisodeStreams = async (episodeId: string) => {
|
||||
const startTime = Date.now();
|
||||
try {
|
||||
if (__DEV__) console.log('🚀 [loadEpisodeStreams] START - Loading episode streams for:', episodeId);
|
||||
if (__DEV__) logger.log('🚀 [loadEpisodeStreams] START - Loading episode streams for:', episodeId);
|
||||
updateEpisodeLoadingState();
|
||||
|
||||
// Reset scraper tracking for episodes
|
||||
|
|
@ -1861,7 +1784,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const fallback = pickStreamCapableAddons(fallbackType);
|
||||
if (fallback.length > 0) {
|
||||
streamAddons = fallback;
|
||||
if (__DEV__) console.log(`[useMetadata.loadEpisodeStreams] No addons for '${requestedEpisodeType}', falling back to '${fallbackType}'`);
|
||||
if (__DEV__) logger.log(`[useMetadata.loadEpisodeStreams] No addons for '${requestedEpisodeType}', falling back to '${fallbackType}'`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1912,12 +1835,12 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
setLoadingEpisodeStreams(false);
|
||||
}
|
||||
} catch (error) {
|
||||
if (__DEV__) console.error('Failed to initialize episode scraper tracking:', error);
|
||||
if (__DEV__) logger.error('Failed to initialize episode scraper tracking:', error);
|
||||
}
|
||||
|
||||
// Get TMDB ID for external sources and determine the correct ID for Stremio addons
|
||||
const isImdb = id.startsWith('tt');
|
||||
if (__DEV__) console.log('🔍 [loadEpisodeStreams] Getting TMDB ID for:', id);
|
||||
if (__DEV__) logger.log('🔍 [loadEpisodeStreams] Getting TMDB ID for:', id);
|
||||
let tmdbId;
|
||||
let stremioEpisodeId = episodeId; // Default to original episode ID
|
||||
let isCollection = false;
|
||||
|
|
@ -1965,13 +1888,13 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
showIdStr = parts.join(':');
|
||||
}
|
||||
|
||||
if (__DEV__) console.log(`🔍 [loadEpisodeStreams] Parsed ID: show=${showIdStr}, s=${seasonNum}, e=${episodeNum}`);
|
||||
if (__DEV__) logger.log(`🔍 [loadEpisodeStreams] Parsed ID: show=${showIdStr}, s=${seasonNum}, e=${episodeNum}`);
|
||||
} catch (e) {
|
||||
if (__DEV__) console.warn('⚠️ [loadEpisodeStreams] Failed to parse episode ID:', episodeId);
|
||||
if (__DEV__) logger.warn('⚠️ [loadEpisodeStreams] Failed to parse episode ID:', episodeId);
|
||||
}
|
||||
|
||||
if (isCollection && collectionAddon) {
|
||||
if (__DEV__) console.log(`🎬 [loadEpisodeStreams] Detected collection from addon: ${collectionAddon.name}, treating episodes as individual movies`);
|
||||
if (__DEV__) logger.log(`🎬 [loadEpisodeStreams] Detected collection from addon: ${collectionAddon.name}, treating episodes as individual movies`);
|
||||
|
||||
// For collections, extract the individual movie ID from the episodeId
|
||||
// episodeId format for collections: "tt7888964" (IMDb ID of individual movie)
|
||||
|
|
@ -1981,7 +1904,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
tmdbId = await withTimeout(tmdbService.findTMDBIdByIMDB(episodeId), API_TIMEOUT);
|
||||
}
|
||||
stremioEpisodeId = episodeId; // Use the IMDb ID directly for Stremio addons
|
||||
if (__DEV__) console.log('✅ [loadEpisodeStreams] Collection movie - using IMDb ID:', episodeId, 'TMDB ID:', tmdbId);
|
||||
if (__DEV__) logger.log('✅ [loadEpisodeStreams] Collection movie - using IMDb ID:', episodeId, 'TMDB ID:', tmdbId);
|
||||
} else {
|
||||
// Fallback: try to verify if it's a tmdb id
|
||||
const isTmdb = episodeId.startsWith('tmdb:') || !isNaN(Number(episodeId));
|
||||
|
|
@ -1992,20 +1915,20 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
} else {
|
||||
stremioEpisodeId = episodeId;
|
||||
}
|
||||
if (__DEV__) console.log('⚠️ [loadEpisodeStreams] Collection movie - using episodeId as-is:', episodeId);
|
||||
if (__DEV__) logger.log('⚠️ [loadEpisodeStreams] Collection movie - using episodeId as-is:', episodeId);
|
||||
}
|
||||
} else if (id.startsWith('tmdb:')) {
|
||||
tmdbId = id.split(':')[1];
|
||||
if (__DEV__) console.log('✅ [loadEpisodeStreams] Using TMDB ID from ID:', tmdbId);
|
||||
if (__DEV__) logger.log('✅ [loadEpisodeStreams] Using TMDB ID from ID:', tmdbId);
|
||||
|
||||
// Try to get IMDb ID from metadata first, then convert if needed
|
||||
if (metadata?.imdb_id) {
|
||||
// Use format: imdb_id:season:episode
|
||||
stremioEpisodeId = `${metadata.imdb_id}:${seasonNum}:${episodeNum}`;
|
||||
if (__DEV__) console.log('✅ [loadEpisodeStreams] Using IMDb ID from metadata for Stremio episode:', stremioEpisodeId);
|
||||
if (__DEV__) logger.log('✅ [loadEpisodeStreams] Using IMDb ID from metadata for Stremio episode:', stremioEpisodeId);
|
||||
} else if (imdbId) {
|
||||
stremioEpisodeId = `${imdbId}:${seasonNum}:${episodeNum}`;
|
||||
if (__DEV__) console.log('✅ [loadEpisodeStreams] Using stored IMDb ID for Stremio episode:', stremioEpisodeId);
|
||||
if (__DEV__) logger.log('✅ [loadEpisodeStreams] Using stored IMDb ID for Stremio episode:', stremioEpisodeId);
|
||||
} else {
|
||||
// Convert TMDB ID to IMDb ID for Stremio addons
|
||||
try {
|
||||
|
|
@ -2013,27 +1936,27 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
|
||||
if (externalIds?.imdb_id) {
|
||||
stremioEpisodeId = `${externalIds.imdb_id}:${seasonNum}:${episodeNum}`;
|
||||
if (__DEV__) console.log('✅ [loadEpisodeStreams] Converted TMDB to IMDb ID for Stremio episode:', stremioEpisodeId);
|
||||
if (__DEV__) logger.log('✅ [loadEpisodeStreams] Converted TMDB to IMDb ID for Stremio episode:', stremioEpisodeId);
|
||||
} else {
|
||||
// Fallback to TMDB format if conversions fail
|
||||
// e.g. tmdb:123:1:1
|
||||
stremioEpisodeId = `${id}:${seasonNum}:${episodeNum}`;
|
||||
if (__DEV__) console.log('⚠️ [loadEpisodeStreams] No IMDb ID found for TMDB ID, using TMDB episode ID:', stremioEpisodeId);
|
||||
if (__DEV__) logger.log('⚠️ [loadEpisodeStreams] No IMDb ID found for TMDB ID, using TMDB episode ID:', stremioEpisodeId);
|
||||
}
|
||||
} catch (error) {
|
||||
stremioEpisodeId = `${id}:${seasonNum}:${episodeNum}`;
|
||||
if (__DEV__) console.log('⚠️ [loadEpisodeStreams] Failed to convert TMDB to IMDb, using TMDB episode ID:', error);
|
||||
if (__DEV__) logger.log('⚠️ [loadEpisodeStreams] Failed to convert TMDB to IMDb, using TMDB episode ID:', error);
|
||||
}
|
||||
}
|
||||
} else if (isImdb) {
|
||||
// This is already an IMDB ID, perfect for Stremio
|
||||
if (settings.enrichMetadataWithTMDB) {
|
||||
if (__DEV__) console.log('📝 [loadEpisodeStreams] Converting IMDB ID to TMDB ID...');
|
||||
if (__DEV__) logger.log('📝 [loadEpisodeStreams] Converting IMDB ID to TMDB ID...');
|
||||
tmdbId = await withTimeout(tmdbService.findTMDBIdByIMDB(id), API_TIMEOUT);
|
||||
} else {
|
||||
if (__DEV__) console.log('📝 [loadEpisodeStreams] TMDB enrichment disabled, skipping IMDB to TMDB conversion');
|
||||
if (__DEV__) logger.log('📝 [loadEpisodeStreams] TMDB enrichment disabled, skipping IMDB to TMDB conversion');
|
||||
}
|
||||
if (__DEV__) console.log('✅ [loadEpisodeStreams] Converted to TMDB ID:', tmdbId);
|
||||
if (__DEV__) logger.log('✅ [loadEpisodeStreams] Converted to TMDB ID:', tmdbId);
|
||||
|
||||
// Ensure consistent format or fallback to episodeId if parsing failed.
|
||||
// If the episode's namespace differs from the show's tt id (e.g. kitsu:48363:8
|
||||
|
|
@ -2048,7 +1971,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const baseId = showIdStr && showIdStr !== id ? showIdStr : id;
|
||||
stremioEpisodeId = `${baseId}:${seasonNum}:${episodeNum}`;
|
||||
}
|
||||
if (__DEV__) console.log('🔧 [loadEpisodeStreams] Normalized episode ID for addons:', stremioEpisodeId);
|
||||
if (__DEV__) logger.log('🔧 [loadEpisodeStreams] Normalized episode ID for addons:', stremioEpisodeId);
|
||||
} else {
|
||||
tmdbId = id;
|
||||
// If season/episode parsing failed (empty strings), use the raw episode ID
|
||||
|
|
@ -2067,22 +1990,22 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const baseId = showIdStr && showIdStr !== id ? showIdStr : id;
|
||||
stremioEpisodeId = `${baseId}:${seasonNum}:${episodeNum}`;
|
||||
}
|
||||
if (__DEV__) console.log('ℹ️ [loadEpisodeStreams] Using ID as both TMDB and Stremio ID:', tmdbId, '| stremioEpisodeId:', stremioEpisodeId);
|
||||
if (__DEV__) logger.log('ℹ️ [loadEpisodeStreams] Using ID as both TMDB and Stremio ID:', tmdbId, '| stremioEpisodeId:', stremioEpisodeId);
|
||||
}
|
||||
|
||||
// Extract episode info from the episodeId for logging
|
||||
const episodeQuery = `?s=${seasonNum}&e=${episodeNum}`;
|
||||
if (__DEV__) console.log(`ℹ️ [loadEpisodeStreams] Episode query: ${episodeQuery}`);
|
||||
if (__DEV__) logger.log(`ℹ️ [loadEpisodeStreams] Episode query: ${episodeQuery}`);
|
||||
|
||||
if (__DEV__) console.log('🔄 [loadEpisodeStreams] Starting stream requests');
|
||||
if (__DEV__) logger.log('🔄 [loadEpisodeStreams] Starting stream requests');
|
||||
|
||||
// Start Stremio request using the converted episode ID format
|
||||
if (__DEV__) console.log('🎬 [loadEpisodeStreams] Using episode ID for Stremio addons:', stremioEpisodeId);
|
||||
if (__DEV__) logger.log('🎬 [loadEpisodeStreams] Using episode ID for Stremio addons:', stremioEpisodeId);
|
||||
|
||||
// For collections, treat episodes as individual movies, not series
|
||||
// For other types (e.g. StreamsPPV), preserve the original type unless it's explicitly 'series' logic we want
|
||||
const contentType = isCollection ? 'movie' : type;
|
||||
if (__DEV__) console.log(`🎬 [loadEpisodeStreams] Using content type: ${contentType} for ${isCollection ? 'collection' : type}`);
|
||||
if (__DEV__) logger.log(`🎬 [loadEpisodeStreams] Using content type: ${contentType} for ${isCollection ? 'collection' : type}`);
|
||||
|
||||
processStremioSource(contentType, stremioEpisodeId, true);
|
||||
|
||||
|
|
@ -2121,7 +2044,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
}, 60000);
|
||||
|
||||
} catch (error) {
|
||||
if (__DEV__) console.error('❌ [loadEpisodeStreams] Failed to load episode streams:', error);
|
||||
if (__DEV__) logger.error('❌ [loadEpisodeStreams] Failed to load episode streams:', error);
|
||||
// Preserve the original error details for better error parsing
|
||||
const errorMessage = error instanceof Error ? error.message : 'Failed to load episode streams';
|
||||
setError(errorMessage);
|
||||
|
|
@ -2187,7 +2110,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
// This will be handled by the StreamsScreen component
|
||||
// The useMetadata hook focuses on metadata and episodes
|
||||
} catch (error) {
|
||||
if (__DEV__) console.log('[useMetadata] Error checking cached streams on mount:', error);
|
||||
if (__DEV__) logger.log('[useMetadata] Error checking cached streams on mount:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2206,7 +2129,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
useEffect(() => {
|
||||
if (metadata && metadata.videos && metadata.videos.length > 0) {
|
||||
logger.log(`🎬 Metadata updated with ${metadata.videos.length} episodes, reloading series data`);
|
||||
loadSeriesData().catch((error) => { if (__DEV__) console.error(error); });
|
||||
loadSeriesData().catch((error) => { if (__DEV__) logger.error(error); });
|
||||
// Also extract embedded streams from metadata videos (PPV-style addons)
|
||||
extractEmbeddedStreams();
|
||||
}
|
||||
|
|
@ -2214,7 +2137,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
|
||||
const loadRecommendations = useCallback(async () => {
|
||||
if (!settings.enrichMetadataWithTMDB) {
|
||||
if (__DEV__) console.log('[useMetadata] enrichment disabled; skip recommendations');
|
||||
if (__DEV__) logger.log('[useMetadata] enrichment disabled; skip recommendations');
|
||||
return;
|
||||
}
|
||||
if (!tmdbId) return;
|
||||
|
|
@ -2236,7 +2159,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
|
||||
setRecommendations(formattedRecommendations);
|
||||
} catch (error) {
|
||||
if (__DEV__) console.error('Failed to load recommendations:', error);
|
||||
if (__DEV__) logger.error('Failed to load recommendations:', error);
|
||||
setRecommendations([]);
|
||||
} finally {
|
||||
setLoadingRecommendations(false);
|
||||
|
|
@ -2253,7 +2176,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
// For anime IDs we always try to resolve tmdbId and imdbId regardless of enrichment setting,
|
||||
// because they're needed for Trakt scrobbling even when TMDB enrichment is disabled.
|
||||
if (!settings.enrichMetadataWithTMDB && !isAnimeId) {
|
||||
if (__DEV__) console.log('[useMetadata] enrichment disabled; skip TMDB id extraction (extract path)');
|
||||
if (__DEV__) logger.log('[useMetadata] enrichment disabled; skip TMDB id extraction (extract path)');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2262,7 +2185,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const tmdbSvc = TMDBService.getInstance();
|
||||
const fetchedTmdbId = await tmdbSvc.extractTMDBIdFromStremioId(id);
|
||||
if (fetchedTmdbId) {
|
||||
if (__DEV__) console.log('[useMetadata] extracted TMDB id from content id', { id, fetchedTmdbId });
|
||||
if (__DEV__) logger.log('[useMetadata] extracted TMDB id from content id', { id, fetchedTmdbId });
|
||||
setTmdbId(fetchedTmdbId);
|
||||
|
||||
// For anime IDs, also resolve the IMDb ID from TMDB external IDs so Trakt can scrobble
|
||||
|
|
@ -2270,11 +2193,11 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
try {
|
||||
const externalIds = await tmdbSvc.getShowExternalIds(fetchedTmdbId);
|
||||
if (externalIds?.imdb_id) {
|
||||
if (__DEV__) console.log('[useMetadata] resolved imdbId for anime via TMDB', { id, imdbId: externalIds.imdb_id });
|
||||
if (__DEV__) logger.log('[useMetadata] resolved imdbId for anime via TMDB', { id, imdbId: externalIds.imdb_id });
|
||||
setImdbId(externalIds.imdb_id);
|
||||
}
|
||||
} catch (e) {
|
||||
if (__DEV__) console.warn('[useMetadata] could not resolve imdbId from TMDB for anime ID', { id });
|
||||
if (__DEV__) logger.warn('[useMetadata] could not resolve imdbId from TMDB for anime ID', { id });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2289,24 +2212,24 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
if (settings.tmdbEnrichCertification) {
|
||||
const certification = await tmdbSvc.getCertification(normalizedType, fetchedTmdbId);
|
||||
if (certification) {
|
||||
if (__DEV__) console.log('[useMetadata] fetched certification via TMDB id (extract path)', { type, fetchedTmdbId, certification });
|
||||
if (__DEV__) logger.log('[useMetadata] fetched certification via TMDB id (extract path)', { type, fetchedTmdbId, certification });
|
||||
setMetadata(prev => prev ? {
|
||||
...prev,
|
||||
tmdbId: fetchedTmdbId,
|
||||
certification
|
||||
} : null);
|
||||
} else {
|
||||
if (__DEV__) console.warn('[useMetadata] certification not returned from TMDB (extract path)', { type, fetchedTmdbId });
|
||||
if (__DEV__) logger.warn('[useMetadata] certification not returned from TMDB (extract path)', { type, fetchedTmdbId });
|
||||
}
|
||||
} else {
|
||||
// Just set the TMDB ID without certification
|
||||
setMetadata(prev => prev ? { ...prev, tmdbId: fetchedTmdbId } : null);
|
||||
}
|
||||
} else {
|
||||
if (__DEV__) console.warn('[useMetadata] Could not determine TMDB ID for recommendations / certification', { id });
|
||||
if (__DEV__) logger.warn('[useMetadata] Could not determine TMDB ID for recommendations / certification', { id });
|
||||
}
|
||||
} catch (error) {
|
||||
if (__DEV__) console.error('[useMetadata] Error fetching TMDB ID (extract path):', error);
|
||||
if (__DEV__) logger.error('[useMetadata] Error fetching TMDB ID (extract path):', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -2318,7 +2241,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
if (tmdbId) {
|
||||
// Check both master switch AND granular recommendations setting
|
||||
if (settings.enrichMetadataWithTMDB && settings.tmdbEnrichRecommendations) {
|
||||
if (__DEV__) console.log('[useMetadata] tmdbId available; loading recommendations', { tmdbId });
|
||||
if (__DEV__) logger.log('[useMetadata] tmdbId available; loading recommendations', { tmdbId });
|
||||
loadRecommendations();
|
||||
}
|
||||
// Reset recommendations when tmdbId changes
|
||||
|
|
@ -2343,32 +2266,32 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const maybeAttachCertification = async () => {
|
||||
// Check both master switch AND granular certification setting
|
||||
if (!settings.enrichMetadataWithTMDB || !settings.tmdbEnrichCertification) {
|
||||
if (__DEV__) console.log('[useMetadata] certification enrichment disabled; skip (attach path)');
|
||||
if (__DEV__) logger.log('[useMetadata] certification enrichment disabled; skip (attach path)');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (!metadata) {
|
||||
if (__DEV__) console.warn('[useMetadata] skip certification attach: metadata not ready');
|
||||
if (__DEV__) logger.warn('[useMetadata] skip certification attach: metadata not ready');
|
||||
return;
|
||||
}
|
||||
if (!tmdbId) {
|
||||
if (__DEV__) console.warn('[useMetadata] skip certification attach: tmdbId not available yet');
|
||||
if (__DEV__) logger.warn('[useMetadata] skip certification attach: tmdbId not available yet');
|
||||
return;
|
||||
}
|
||||
if ((metadata as any).certification) {
|
||||
if (__DEV__) console.log('[useMetadata] certification already present on metadata; skipping fetch');
|
||||
if (__DEV__) logger.log('[useMetadata] certification already present on metadata; skipping fetch');
|
||||
return;
|
||||
}
|
||||
const tmdbSvc = TMDBService.getInstance();
|
||||
const cert = await tmdbSvc.getCertification(normalizedType, tmdbId);
|
||||
if (cert) {
|
||||
if (__DEV__) console.log('[useMetadata] fetched certification (attach path)', { type, tmdbId, cert });
|
||||
if (__DEV__) logger.log('[useMetadata] fetched certification (attach path)', { type, tmdbId, cert });
|
||||
setMetadata(prev => prev ? { ...prev, tmdbId, certification: cert } : prev);
|
||||
} else {
|
||||
if (__DEV__) console.warn('[useMetadata] TMDB returned no certification (attach path)', { type, tmdbId });
|
||||
if (__DEV__) logger.warn('[useMetadata] TMDB returned no certification (attach path)', { type, tmdbId });
|
||||
}
|
||||
} catch (err) {
|
||||
if (__DEV__) console.error('[useMetadata] error attaching certification', err);
|
||||
if (__DEV__) logger.error('[useMetadata] error attaching certification', err);
|
||||
}
|
||||
};
|
||||
maybeAttachCertification();
|
||||
|
|
@ -2405,7 +2328,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const tmdbService = TMDBService.getInstance();
|
||||
let productionInfo: any[] = [];
|
||||
|
||||
if (__DEV__) console.log('[useMetadata] fetchProductionInfo starting', {
|
||||
if (__DEV__) logger.log('[useMetadata] fetchProductionInfo starting', {
|
||||
contentKey,
|
||||
type,
|
||||
tmdbId,
|
||||
|
|
@ -2423,7 +2346,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const lang = settings.useTmdbLocalizedMetadata ? (settings.tmdbLanguagePreference || 'en') : 'en';
|
||||
const showDetails = await tmdbService.getTVShowDetails(tmdbId, lang);
|
||||
if (showDetails) {
|
||||
if (__DEV__) console.log('[useMetadata] fetchProductionInfo got showDetails', {
|
||||
if (__DEV__) logger.log('[useMetadata] fetchProductionInfo got showDetails', {
|
||||
hasNetworks: !!showDetails.networks,
|
||||
networksCount: showDetails.networks?.length || 0
|
||||
});
|
||||
|
|
@ -2472,7 +2395,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
const lang = settings.useTmdbLocalizedMetadata ? (settings.tmdbLanguagePreference || 'en') : 'en';
|
||||
const movieDetails = await tmdbService.getMovieDetails(String(tmdbId), lang);
|
||||
if (movieDetails) {
|
||||
if (__DEV__) console.log('[useMetadata] fetchProductionInfo got movieDetails', {
|
||||
if (__DEV__) logger.log('[useMetadata] fetchProductionInfo got movieDetails', {
|
||||
hasProductionCompanies: !!movieDetails.production_companies,
|
||||
productionCompaniesCount: movieDetails.production_companies?.length || 0
|
||||
});
|
||||
|
|
@ -2557,7 +2480,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (__DEV__) console.warn('[useMetadata] Failed to fetch movie images for:', part.id, error);
|
||||
if (__DEV__) logger.warn('[useMetadata] Failed to fetch movie images for:', part.id, error);
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
@ -2592,7 +2515,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
if (__DEV__) console.error('[useMetadata] Error fetching collection:', error);
|
||||
if (__DEV__) logger.error('[useMetadata] Error fetching collection:', error);
|
||||
} finally {
|
||||
setLoadingCollection(false);
|
||||
}
|
||||
|
|
@ -2604,7 +2527,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
setMetadata((prev: any) => ({ ...prev, networks: productionInfo }));
|
||||
}
|
||||
} catch (error) {
|
||||
if (__DEV__) console.error('[useMetadata] Failed to fetch production info:', error);
|
||||
if (__DEV__) logger.error('[useMetadata] Failed to fetch production info:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2641,7 +2564,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
|||
// Reset production info fetch tracking
|
||||
productionInfoFetchedRef.current = null;
|
||||
|
||||
if (__DEV__) console.log('[useMetadata] Component unmounted, memory cleaned up');
|
||||
if (__DEV__) logger.log('[useMetadata] Component unmounted, memory cleaned up');
|
||||
};
|
||||
}, [cleanupStreams]);
|
||||
|
||||
|
|
|
|||
|
|
@ -1941,10 +1941,8 @@ const ConditionalPostHogProvider: React.FC<{ children: React.ReactNode }> = ({ c
|
|||
if (posthogRef.current) {
|
||||
if (settings.analyticsEnabled) {
|
||||
posthogRef.current.optIn();
|
||||
console.log('[Telemetry] PostHog opted in');
|
||||
} else {
|
||||
posthogRef.current.optOut();
|
||||
console.log('[Telemetry] PostHog opted out');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1996,10 +1994,8 @@ const PostHogOptController: React.FC<{
|
|||
onPostHogReady(posthog);
|
||||
if (enabled) {
|
||||
posthog.optIn();
|
||||
console.log('[Telemetry] PostHog opted in');
|
||||
} else {
|
||||
posthog.optOut();
|
||||
console.log('[Telemetry] PostHog opted out');
|
||||
}
|
||||
}
|
||||
}, [enabled, posthog, onPostHogReady]);
|
||||
|
|
|
|||
|
|
@ -26,39 +26,19 @@ import { useTheme } from '../contexts/ThemeContext';
|
|||
import { logger } from '../utils/logger';
|
||||
import { RATING_PROVIDERS } from '../components/metadata/RatingsSection';
|
||||
import CustomAlert from '../components/CustomAlert'; // Moved CustomAlert import here
|
||||
import {
|
||||
MDBLIST_API_KEY_STORAGE_KEY,
|
||||
MDBLIST_ENABLED_STORAGE_KEY,
|
||||
RATING_PROVIDERS_STORAGE_KEY,
|
||||
isMDBListEnabled,
|
||||
getMDBListAPIKey,
|
||||
} from '../services/mdblistConstants';
|
||||
|
||||
// Re-export for backwards compatibility
|
||||
export { MDBLIST_API_KEY_STORAGE_KEY, RATING_PROVIDERS_STORAGE_KEY, MDBLIST_ENABLED_STORAGE_KEY, isMDBListEnabled, getMDBListAPIKey };
|
||||
|
||||
export const MDBLIST_API_KEY_STORAGE_KEY = 'mdblist_api_key';
|
||||
export const RATING_PROVIDERS_STORAGE_KEY = 'rating_providers_config';
|
||||
export const MDBLIST_ENABLED_STORAGE_KEY = 'mdblist_enabled';
|
||||
const ANDROID_STATUSBAR_HEIGHT = StatusBar.currentHeight || 0;
|
||||
|
||||
// Function to check if MDBList is enabled
|
||||
export const isMDBListEnabled = async (): Promise<boolean> => {
|
||||
try {
|
||||
const enabledSetting = await mmkvStorage.getItem(MDBLIST_ENABLED_STORAGE_KEY);
|
||||
return enabledSetting === 'true';
|
||||
} catch (error) {
|
||||
logger.error('[MDBList] Error checking if MDBList is enabled:', error);
|
||||
return false; // Default to disabled if there's an error
|
||||
}
|
||||
};
|
||||
|
||||
// Function to get MDBList API key if enabled
|
||||
export const getMDBListAPIKey = async (): Promise<string | null> => {
|
||||
try {
|
||||
const isEnabled = await isMDBListEnabled();
|
||||
if (!isEnabled) {
|
||||
logger.log('[MDBList] MDBList is disabled, not retrieving API key');
|
||||
return null;
|
||||
}
|
||||
|
||||
return await mmkvStorage.getItem(MDBLIST_API_KEY_STORAGE_KEY);
|
||||
} catch (error) {
|
||||
logger.error('[MDBList] Error retrieving API key:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Create a styles creator function that accepts the theme colors
|
||||
const createStyles = (colors: any) => StyleSheet.create({
|
||||
container: {
|
||||
|
|
|
|||
|
|
@ -84,11 +84,19 @@ const BREAKPOINTS = {
|
|||
const MemoizedRatingsSection = memo(RatingsSection);
|
||||
const MemoizedCommentsSection = memo(CommentsSection);
|
||||
const MemoizedCastDetailsModal = memo(CastDetailsModal);
|
||||
const noop = (..._args: unknown[]) => {};
|
||||
const logger = {
|
||||
log: noop,
|
||||
error: noop,
|
||||
warn: noop,
|
||||
info: noop,
|
||||
debug: noop,
|
||||
};
|
||||
|
||||
// ... other imports
|
||||
|
||||
const MetadataScreen: React.FC = () => {
|
||||
useEffect(() => { console.log('✅ MetadataScreen MOUNTED'); }, []);
|
||||
useEffect(() => { logger.log('✅ MetadataScreen MOUNTED'); }, []);
|
||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const route = useRoute<RouteProp<RootStackParamList, 'Metadata'>>();
|
||||
const { id, type, episodeId, addonId } = route.params;
|
||||
|
|
@ -184,16 +192,16 @@ const MetadataScreen: React.FC = () => {
|
|||
|
||||
// Debug state changes
|
||||
React.useEffect(() => {
|
||||
console.log('MetadataScreen: commentBottomSheetVisible changed to:', commentBottomSheetVisible);
|
||||
logger.log('MetadataScreen: commentBottomSheetVisible changed to:', commentBottomSheetVisible);
|
||||
}, [commentBottomSheetVisible]);
|
||||
|
||||
React.useEffect(() => {
|
||||
console.log('MetadataScreen: selectedComment changed to:', selectedComment?.id);
|
||||
logger.log('MetadataScreen: selectedComment changed to:', selectedComment?.id);
|
||||
}, [selectedComment]);
|
||||
|
||||
// Log useMetadata hook state changes for debugging
|
||||
React.useEffect(() => {
|
||||
console.log('🔍 [MetadataScreen] useMetadata state:', {
|
||||
logger.log('🔍 [MetadataScreen] useMetadata state:', {
|
||||
loading,
|
||||
hasMetadata: !!metadata,
|
||||
metadataId: metadata?.id,
|
||||
|
|
@ -357,7 +365,7 @@ const MetadataScreen: React.FC = () => {
|
|||
// Debug logging for color extraction timing
|
||||
useEffect(() => {
|
||||
if (__DEV__ && heroImageUri && dominantColor) {
|
||||
if (__DEV__) console.log('[MetadataScreen] Dynamic background color:', {
|
||||
if (__DEV__) logger.log('[MetadataScreen] Dynamic background color:', {
|
||||
dominantColor,
|
||||
fallback: currentTheme.colors.darkBackground,
|
||||
finalColor: dynamicBackgroundColor,
|
||||
|
|
@ -422,7 +430,7 @@ const MetadataScreen: React.FC = () => {
|
|||
const isAuthenticated = await traktService.isAuthenticated();
|
||||
|
||||
if (!isAuthenticated) {
|
||||
if (__DEV__) console.log(`[MetadataScreen] Not authenticated with Trakt`);
|
||||
if (__DEV__) logger.log(`[MetadataScreen] Not authenticated with Trakt`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -449,7 +457,7 @@ const MetadataScreen: React.FC = () => {
|
|||
if (relevantProgress.length === 0) return;
|
||||
|
||||
// Log only essential progress information for performance
|
||||
if (__DEV__) console.log(`[MetadataScreen] Found ${relevantProgress.length} Trakt progress items for ${type}`);
|
||||
if (__DEV__) logger.log(`[MetadataScreen] Found ${relevantProgress.length} Trakt progress items for ${type}`);
|
||||
|
||||
// Find most recent progress if multiple episodes
|
||||
if (Object.keys(groupedEpisodes).length > 0 && relevantProgress.length > 1) {
|
||||
|
|
@ -458,12 +466,12 @@ const MetadataScreen: React.FC = () => {
|
|||
)[0];
|
||||
|
||||
if (mostRecent.episode && mostRecent.show) {
|
||||
if (__DEV__) console.log(`[MetadataScreen] Most recent: S${mostRecent.episode.season}E${mostRecent.episode.number} - ${mostRecent.progress.toFixed(1)}%`);
|
||||
if (__DEV__) logger.log(`[MetadataScreen] Most recent: S${mostRecent.episode.season}E${mostRecent.episode.number} - ${mostRecent.progress.toFixed(1)}%`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
if (__DEV__) console.error(`[MetadataScreen] Failed to fetch Trakt progress:`, error);
|
||||
if (__DEV__) logger.error(`[MetadataScreen] Failed to fetch Trakt progress:`, error);
|
||||
}
|
||||
}, [shouldLoadSecondaryData, metadata, id, type]);
|
||||
|
||||
|
|
@ -495,7 +503,7 @@ const MetadataScreen: React.FC = () => {
|
|||
const timer = setTimeout(() => {
|
||||
const renderTime = Date.now() - startTime;
|
||||
if (renderTime > 100) {
|
||||
if (__DEV__) console.warn(`[MetadataScreen] Slow render detected: ${renderTime}ms for ${metadata.name}`);
|
||||
if (__DEV__) logger.warn(`[MetadataScreen] Slow render detected: ${renderTime}ms for ${metadata.name}`);
|
||||
}
|
||||
}, 0);
|
||||
return () => clearTimeout(timer);
|
||||
|
|
@ -513,11 +521,11 @@ const MetadataScreen: React.FC = () => {
|
|||
const totalMB = Math.round(memory.totalJSHeapSize / 1048576);
|
||||
const limitMB = Math.round(memory.jsHeapSizeLimit / 1048576);
|
||||
|
||||
if (__DEV__) console.log(`[MetadataScreen] Memory usage: ${usedMB}MB / ${totalMB}MB (limit: ${limitMB}MB)`);
|
||||
if (__DEV__) logger.log(`[MetadataScreen] Memory usage: ${usedMB}MB / ${totalMB}MB (limit: ${limitMB}MB)`);
|
||||
|
||||
// Trigger cleanup if memory usage is high
|
||||
if (usedMB > limitMB * 0.8) {
|
||||
if (__DEV__) console.warn(`[MetadataScreen] High memory usage detected (${usedMB}MB), triggering cleanup`);
|
||||
if (__DEV__) logger.warn(`[MetadataScreen] High memory usage detected (${usedMB}MB), triggering cleanup`);
|
||||
// Force garbage collection if available
|
||||
if (global.gc) {
|
||||
global.gc();
|
||||
|
|
@ -536,16 +544,7 @@ const MetadataScreen: React.FC = () => {
|
|||
// Memoized derived values for performance
|
||||
const isReady = useMemo(() => !loading && metadata && !metadataError, [loading, metadata, metadataError]);
|
||||
|
||||
// Log readiness state for debugging
|
||||
React.useEffect(() => {
|
||||
console.log('🔍 [MetadataScreen] Readiness state:', {
|
||||
isReady,
|
||||
loading,
|
||||
hasMetadata: !!metadata,
|
||||
hasError: !!metadataError,
|
||||
errorMessage: metadataError
|
||||
});
|
||||
}, [isReady, loading, metadata, metadataError]);
|
||||
|
||||
|
||||
// Optimized content ready state management
|
||||
useEffect(() => {
|
||||
|
|
@ -627,13 +626,13 @@ const MetadataScreen: React.FC = () => {
|
|||
const nextEpisodeId = isImdb
|
||||
? `${id}:${currentSeason || episodes[0]?.season_number || 1}:${currentEpisode + 1}`
|
||||
: `${id}:${currentEpisode + 1}`;
|
||||
if (__DEV__) console.log(`[MetadataScreen] Created next episode ID: ${nextEpisodeId}`);
|
||||
if (__DEV__) logger.log(`[MetadataScreen] Created next episode ID: ${nextEpisodeId}`);
|
||||
|
||||
const nextEpisodeExists = episodes.some(ep => ep.episode_number === (currentEpisode + 1));
|
||||
if (nextEpisodeExists) {
|
||||
if (__DEV__) console.log(`[MetadataScreen] Verified next episode exists`);
|
||||
if (__DEV__) logger.log(`[MetadataScreen] Verified next episode exists`);
|
||||
} else {
|
||||
if (__DEV__) console.log(`[MetadataScreen] Warning: Next episode not found`);
|
||||
if (__DEV__) logger.log(`[MetadataScreen] Warning: Next episode not found`);
|
||||
}
|
||||
|
||||
targetEpisodeId = nextEpisodeId;
|
||||
|
|
@ -643,7 +642,7 @@ const MetadataScreen: React.FC = () => {
|
|||
// Fallback logic: if not finished or nextEp not found
|
||||
if (!targetEpisodeId) {
|
||||
targetEpisodeId = watchProgress?.episodeId || episodeId || (episodes.length > 0 ? buildEpisodeId(episodes[0]) : undefined);
|
||||
if (__DEV__) console.log(`[MetadataScreen] Using fallback episode ID: ${targetEpisodeId}`);
|
||||
if (__DEV__) logger.log(`[MetadataScreen] Using fallback episode ID: ${targetEpisodeId}`);
|
||||
}
|
||||
|
||||
if (targetEpisodeId) {
|
||||
|
|
@ -657,7 +656,7 @@ const MetadataScreen: React.FC = () => {
|
|||
else if (epParts.length === 2 && isImdb) {
|
||||
normalizedEpisodeId = `${id}:${epParts[0]}:${epParts[1]}`;
|
||||
}
|
||||
if (__DEV__) console.log(`[MetadataScreen] Navigating to streams with episodeId: ${normalizedEpisodeId}`);
|
||||
if (__DEV__) logger.log(`[MetadataScreen] Navigating to streams with episodeId: ${normalizedEpisodeId}`);
|
||||
navigation.navigate('Streams', { id, type, episodeId: normalizedEpisodeId });
|
||||
return;
|
||||
}
|
||||
|
|
@ -671,14 +670,14 @@ const MetadataScreen: React.FC = () => {
|
|||
fallbackEpisodeId = isImdb ? `${id}:${p[0]}:${p[1]}` : `${id}:${p[1]}`;
|
||||
}
|
||||
}
|
||||
if (__DEV__) console.log(`[MetadataScreen] Navigating with fallback episodeId: ${fallbackEpisodeId}`);
|
||||
if (__DEV__) logger.log(`[MetadataScreen] Navigating with fallback episodeId: ${fallbackEpisodeId}`);
|
||||
navigation.navigate('Streams', { id, type, episodeId: fallbackEpisodeId });
|
||||
}, [navigation, id, type, episodes, episodeId, watchProgressData.watchProgress]);
|
||||
|
||||
const handleEpisodeSelect = useCallback((episode: Episode) => {
|
||||
if (!isScreenFocused) return;
|
||||
|
||||
if (__DEV__) console.log('[MetadataScreen] Selected Episode:', episode.episode_number, episode.season_number);
|
||||
if (__DEV__) logger.log('[MetadataScreen] Selected Episode:', episode.episode_number, episode.season_number);
|
||||
|
||||
let episodeId: string;
|
||||
if (episode.stremioId) {
|
||||
|
|
@ -716,15 +715,11 @@ const MetadataScreen: React.FC = () => {
|
|||
}, [isScreenFocused]);
|
||||
|
||||
const handleCommentPress = useCallback((comment: any) => {
|
||||
console.log('MetadataScreen: handleCommentPress called with comment:', comment?.id);
|
||||
if (!isScreenFocused) {
|
||||
console.log('MetadataScreen: Screen not focused, ignoring');
|
||||
return;
|
||||
}
|
||||
console.log('MetadataScreen: Setting selected comment and opening bottomsheet');
|
||||
setSelectedComment(comment);
|
||||
setCommentBottomSheetVisible(true);
|
||||
console.log('MetadataScreen: State should be updated now');
|
||||
}, [isScreenFocused]);
|
||||
|
||||
const handleCommentBottomSheetClose = useCallback(() => {
|
||||
|
|
@ -774,7 +769,6 @@ const MetadataScreen: React.FC = () => {
|
|||
|
||||
// Parse error to extract code and user-friendly message
|
||||
const parseError = (error: string) => {
|
||||
console.log('🔍 Parsing error in MetadataScreen:', error);
|
||||
|
||||
// Check for HTTP status codes - handle multiple formats
|
||||
// Match patterns like: "status code 500", "status": 500, "Request failed with status code 500"
|
||||
|
|
@ -785,7 +779,6 @@ const MetadataScreen: React.FC = () => {
|
|||
|
||||
if (statusCodeMatch) {
|
||||
const code = parseInt(statusCodeMatch[1]);
|
||||
console.log('✅ Found status code:', code);
|
||||
switch (code) {
|
||||
case 404:
|
||||
return { code: '404', message: t('metadata.content_not_found'), userMessage: t('metadata.content_not_found_desc') };
|
||||
|
|
@ -893,13 +886,11 @@ const MetadataScreen: React.FC = () => {
|
|||
|
||||
// Show error if exists
|
||||
if (metadataError || (!loading && !metadata)) {
|
||||
console.log('❌ MetadataScreen ERROR state:', { metadataError, loading, hasMetadata: !!metadata });
|
||||
return ErrorComponent;
|
||||
}
|
||||
|
||||
// Show loading screen if metadata is not yet available or exit animation hasn't completed
|
||||
if (loading || !isContentReady || !loadingScreenExited) {
|
||||
console.log('⏳ MetadataScreen LOADING state:', { loading, isContentReady, loadingScreenExited, hasMetadata: !!metadata });
|
||||
return (
|
||||
<MetadataLoadingScreen
|
||||
ref={loadingScreenRef}
|
||||
|
|
@ -1637,4 +1628,4 @@ const styles = StyleSheet.create({
|
|||
|
||||
|
||||
|
||||
export default MetadataScreen;
|
||||
export default MetadataScreen;
|
||||
|
|
|
|||
|
|
@ -59,16 +59,12 @@ class CampaignService {
|
|||
try {
|
||||
const now = Date.now();
|
||||
|
||||
console.log('[CampaignService] getActiveCampaign called, API URL:', CAMPAIGN_API_URL);
|
||||
|
||||
if (this.campaignQueue.length > 0 && (now - this.lastFetch) < this.CACHE_TTL) {
|
||||
console.log('[CampaignService] Using cached campaigns');
|
||||
return this.getNextValidCampaign();
|
||||
}
|
||||
|
||||
const platform = Platform.OS;
|
||||
const url = `${CAMPAIGN_API_URL}/api/campaigns/queue?platform=${platform}`;
|
||||
console.log('[CampaignService] Fetching from:', url);
|
||||
const response = await fetch(
|
||||
`${CAMPAIGN_API_URL}/api/campaigns/queue?platform=${platform}`,
|
||||
{
|
||||
|
|
@ -100,14 +96,11 @@ class CampaignService {
|
|||
}
|
||||
});
|
||||
|
||||
console.log('[CampaignService] Fetched campaigns:', campaigns.length, 'CAMPAIGN_API_URL:', CAMPAIGN_API_URL);
|
||||
|
||||
this.campaignQueue = campaigns;
|
||||
this.currentIndex = 0;
|
||||
this.lastFetch = now;
|
||||
|
||||
const result = this.getNextValidCampaign();
|
||||
console.log('[CampaignService] Next valid campaign:', result?.id, result?.type);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.warn('[CampaignService] Error fetching campaigns:', error);
|
||||
|
|
|
|||
|
|
@ -31,32 +31,19 @@ export async function getContentDetails(
|
|||
id: string,
|
||||
preferredAddonId?: string
|
||||
): Promise<StreamingContent | null> {
|
||||
console.log('🔍 [CatalogService] getContentDetails called:', { type, id, preferredAddonId });
|
||||
|
||||
try {
|
||||
let meta = null;
|
||||
let lastError = null;
|
||||
|
||||
for (let attempt = 0; attempt < 2; attempt += 1) {
|
||||
try {
|
||||
console.log(`🔍 [CatalogService] Attempt ${attempt + 1}/2 for getContentDetails:`, { type, id, preferredAddonId });
|
||||
|
||||
const isValidId = await stremioService.isValidContentId(type, id);
|
||||
console.log('🔍 [CatalogService] Content ID validation:', { type, id, isValidId });
|
||||
|
||||
if (!isValidId) {
|
||||
console.log('🔍 [CatalogService] Invalid content ID, breaking retry loop');
|
||||
break;
|
||||
}
|
||||
|
||||
console.log('🔍 [CatalogService] Calling stremioService.getMetaDetails:', { type, id, preferredAddonId });
|
||||
meta = await stremioService.getMetaDetails(type, id, preferredAddonId);
|
||||
console.log('🔍 [CatalogService] stremioService.getMetaDetails result:', {
|
||||
hasMeta: !!meta,
|
||||
metaId: meta?.id,
|
||||
metaName: meta?.name,
|
||||
metaType: meta?.type,
|
||||
});
|
||||
|
||||
if (meta) {
|
||||
break;
|
||||
|
|
@ -65,61 +52,24 @@ export async function getContentDetails(
|
|||
await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt)));
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
console.log(`🔍 [CatalogService] Attempt ${attempt + 1} failed:`, {
|
||||
errorMessage: error instanceof Error ? error.message : String(error),
|
||||
isAxiosError: (error as any)?.isAxiosError,
|
||||
responseStatus: (error as any)?.response?.status,
|
||||
responseData: (error as any)?.response?.data,
|
||||
});
|
||||
logger.error(`Attempt ${attempt + 1} failed to get content details for ${type}:${id}:`, error);
|
||||
await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt)));
|
||||
}
|
||||
}
|
||||
|
||||
if (meta) {
|
||||
console.log('🔍 [CatalogService] Meta found, converting to StreamingContent:', {
|
||||
metaId: meta.id,
|
||||
metaName: meta.name,
|
||||
metaType: meta.type,
|
||||
});
|
||||
|
||||
const content = convertMetaToStreamingContentEnhanced(meta, state.library);
|
||||
addToRecentContent(state, content);
|
||||
content.inLibrary = state.library[createLibraryKey(type, id)] !== undefined;
|
||||
|
||||
console.log('🔍 [CatalogService] Successfully converted meta to StreamingContent:', {
|
||||
contentId: content.id,
|
||||
contentName: content.name,
|
||||
contentType: content.type,
|
||||
inLibrary: content.inLibrary,
|
||||
});
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
console.log('🔍 [CatalogService] No meta found, checking lastError:', {
|
||||
hasLastError: !!lastError,
|
||||
lastErrorMessage: lastError instanceof Error ? lastError.message : String(lastError),
|
||||
});
|
||||
|
||||
if (lastError) {
|
||||
console.log('🔍 [CatalogService] Throwing lastError:', {
|
||||
errorMessage: lastError instanceof Error ? lastError.message : String(lastError),
|
||||
isAxiosError: (lastError as any)?.isAxiosError,
|
||||
responseStatus: (lastError as any)?.response?.status,
|
||||
});
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
console.log('🔍 [CatalogService] No meta and no error, returning null');
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.log('🔍 [CatalogService] getContentDetails caught error:', {
|
||||
errorMessage: error instanceof Error ? error.message : String(error),
|
||||
isAxiosError: (error as any)?.isAxiosError,
|
||||
responseStatus: (error as any)?.response?.status,
|
||||
responseData: (error as any)?.response?.data,
|
||||
});
|
||||
logger.error(`Failed to get content details for ${type}:${id}:`, error);
|
||||
return null;
|
||||
}
|
||||
|
|
@ -131,25 +81,11 @@ export async function getEnhancedContentDetails(
|
|||
id: string,
|
||||
preferredAddonId?: string
|
||||
): Promise<StreamingContent | null> {
|
||||
console.log('🔍 [CatalogService] getEnhancedContentDetails called:', { type, id, preferredAddonId });
|
||||
logger.log(`🔍 [MetadataScreen] Fetching enhanced metadata for ${type}:${id} ${preferredAddonId ? `from addon ${preferredAddonId}` : ''}`);
|
||||
|
||||
try {
|
||||
const result = await getContentDetails(state, type, id, preferredAddonId);
|
||||
console.log('🔍 [CatalogService] getEnhancedContentDetails result:', {
|
||||
hasResult: !!result,
|
||||
resultId: result?.id,
|
||||
resultName: result?.name,
|
||||
resultType: result?.type,
|
||||
});
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.log('🔍 [CatalogService] getEnhancedContentDetails error:', {
|
||||
errorMessage: error instanceof Error ? error.message : String(error),
|
||||
isAxiosError: (error as any)?.isAxiosError,
|
||||
responseStatus: (error as any)?.response?.status,
|
||||
responseData: (error as any)?.response?.data,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -201,81 +137,29 @@ export async function getBasicContentDetails(
|
|||
}
|
||||
|
||||
export async function getStremioId(type: string, tmdbId: string): Promise<string | null> {
|
||||
if (__DEV__) {
|
||||
console.log('=== CatalogService.getStremioId ===');
|
||||
console.log('Input type:', type);
|
||||
console.log('Input tmdbId:', tmdbId);
|
||||
}
|
||||
|
||||
try {
|
||||
if (type === 'movie') {
|
||||
if (__DEV__) {
|
||||
console.log('Processing movie - fetching TMDB details...');
|
||||
}
|
||||
|
||||
const movieDetails = await TMDBService.getInstance().getMovieDetails(tmdbId);
|
||||
|
||||
if (__DEV__) {
|
||||
console.log('Movie details result:', {
|
||||
id: movieDetails?.id,
|
||||
title: movieDetails?.title,
|
||||
imdb_id: movieDetails?.imdb_id,
|
||||
hasImdbId: !!movieDetails?.imdb_id,
|
||||
});
|
||||
}
|
||||
|
||||
if (movieDetails?.imdb_id) {
|
||||
if (__DEV__) {
|
||||
console.log('Successfully found IMDb ID:', movieDetails.imdb_id);
|
||||
}
|
||||
return movieDetails.imdb_id;
|
||||
}
|
||||
|
||||
console.warn('No IMDb ID found for movie:', tmdbId);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type === 'tv' || type === 'series') {
|
||||
if (__DEV__) {
|
||||
console.log('Processing TV show - fetching TMDB details for IMDb ID...');
|
||||
}
|
||||
|
||||
const externalIds = await TMDBService.getInstance().getShowExternalIds(parseInt(tmdbId, 10));
|
||||
|
||||
if (__DEV__) {
|
||||
console.log('TV show external IDs result:', {
|
||||
tmdbId,
|
||||
imdb_id: externalIds?.imdb_id,
|
||||
hasImdbId: !!externalIds?.imdb_id,
|
||||
});
|
||||
}
|
||||
|
||||
if (externalIds?.imdb_id) {
|
||||
if (__DEV__) {
|
||||
console.log('Successfully found IMDb ID for TV show:', externalIds.imdb_id);
|
||||
}
|
||||
return externalIds.imdb_id;
|
||||
}
|
||||
|
||||
console.warn('No IMDb ID found for TV show, falling back to kitsu format:', tmdbId);
|
||||
const fallbackId = `kitsu:${tmdbId}`;
|
||||
if (__DEV__) {
|
||||
console.log('Generated fallback Stremio ID for TV:', fallbackId);
|
||||
}
|
||||
return fallbackId;
|
||||
}
|
||||
|
||||
console.warn('Unknown type provided:', type);
|
||||
return null;
|
||||
} catch (error: any) {
|
||||
if (__DEV__) {
|
||||
console.error('=== Error in getStremioId ===');
|
||||
console.error('Type:', type);
|
||||
console.error('TMDB ID:', tmdbId);
|
||||
console.error('Error details:', error);
|
||||
console.error('Error message:', error.message);
|
||||
}
|
||||
|
||||
logger.error('Error getting Stremio ID:', error);
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
import { notificationService } from '../notificationService';
|
||||
import { mmkvStorage } from '../mmkvStorage';
|
||||
import { logger } from '../../utils/logger';
|
||||
|
||||
import type { StreamingContent } from './types';
|
||||
|
||||
// Lazy import to break require cycle:
|
||||
// catalogService -> content-details -> content-mappers -> library -> notificationService -> catalogService
|
||||
const getNotificationService = () =>
|
||||
require('../notificationService').notificationService;
|
||||
|
||||
export interface CatalogLibraryState {
|
||||
LEGACY_LIBRARY_KEY: string;
|
||||
RECENT_CONTENT_KEY: string;
|
||||
|
|
@ -259,10 +263,9 @@ export async function addToLibrary(state: CatalogLibraryState, content: Streamin
|
|||
|
||||
if (content.type === 'series') {
|
||||
try {
|
||||
await notificationService.updateNotificationsForSeries(content.id);
|
||||
console.log(`[CatalogService] Auto-setup notifications for series: ${content.name}`);
|
||||
await getNotificationService().updateNotificationsForSeries(content.id);
|
||||
} catch (error) {
|
||||
console.error(`[CatalogService] Failed to setup notifications for ${content.name}:`, error);
|
||||
logger.error(`[CatalogService] Failed to setup notifications for ${content.name}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -299,16 +302,14 @@ export async function removeFromLibrary(
|
|||
|
||||
if (type === 'series') {
|
||||
try {
|
||||
const scheduledNotifications = notificationService.getScheduledNotifications();
|
||||
const seriesToCancel = scheduledNotifications.filter(notification => notification.seriesId === id);
|
||||
const scheduledNotifications = getNotificationService().getScheduledNotifications();
|
||||
const seriesToCancel = scheduledNotifications.filter((notification: any) => notification.seriesId === id);
|
||||
|
||||
for (const notification of seriesToCancel) {
|
||||
await notificationService.cancelNotification(notification.id);
|
||||
await getNotificationService().cancelNotification(notification.id);
|
||||
}
|
||||
|
||||
console.log(`[CatalogService] Cancelled ${seriesToCancel.length} notifications for removed series: ${id}`);
|
||||
} catch (error) {
|
||||
console.error(`[CatalogService] Failed to cancel notifications for removed series ${id}:`, error);
|
||||
logger.error(`[CatalogService] Failed to cancel notifications for removed series ${id}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
31
src/services/mdblistConstants.ts
Normal file
31
src/services/mdblistConstants.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import { mmkvStorage } from './mmkvStorage';
|
||||
import { logger } from '../utils/logger';
|
||||
|
||||
export const MDBLIST_API_KEY_STORAGE_KEY = 'mdblist_api_key';
|
||||
export const MDBLIST_ENABLED_STORAGE_KEY = 'mdblist_enabled';
|
||||
export const RATING_PROVIDERS_STORAGE_KEY = 'rating_providers_config';
|
||||
|
||||
// Function to check if MDBList is enabled
|
||||
export const isMDBListEnabled = async (): Promise<boolean> => {
|
||||
try {
|
||||
const enabledSetting = await mmkvStorage.getItem(MDBLIST_ENABLED_STORAGE_KEY);
|
||||
return enabledSetting === 'true';
|
||||
} catch (error) {
|
||||
logger.error('[MDBList] Error checking if MDBList is enabled:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Function to get MDBList API key if enabled
|
||||
export const getMDBListAPIKey = async (): Promise<string | null> => {
|
||||
try {
|
||||
const isEnabled = await isMDBListEnabled();
|
||||
if (!isEnabled) {
|
||||
return null;
|
||||
}
|
||||
return await mmkvStorage.getItem(MDBLIST_API_KEY_STORAGE_KEY);
|
||||
} catch (error) {
|
||||
logger.error('[MDBList] Error getting API key:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
|
@ -3,8 +3,7 @@ import { logger } from '../utils/logger';
|
|||
import {
|
||||
MDBLIST_API_KEY_STORAGE_KEY,
|
||||
MDBLIST_ENABLED_STORAGE_KEY,
|
||||
isMDBListEnabled
|
||||
} from '../screens/MDBListSettingsScreen';
|
||||
} from './mdblistConstants';
|
||||
|
||||
export interface MDBListRatings {
|
||||
trakt?: number;
|
||||
|
|
|
|||
|
|
@ -148,7 +148,6 @@ class TelemetryService {
|
|||
}
|
||||
|
||||
this.initialized = true;
|
||||
console.log('[TelemetryService] Initialized with settings:', this.settings);
|
||||
} catch (error) {
|
||||
console.error('[TelemetryService] Error initializing:', error);
|
||||
// Use defaults on error
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ class Logger {
|
|||
|
||||
constructor() {
|
||||
// __DEV__ is a global variable in React Native
|
||||
this.isEnabled = __DEV__;
|
||||
this.isEnabled = false;
|
||||
}
|
||||
|
||||
log(...args: any[]) {
|
||||
|
|
@ -37,4 +37,4 @@ class Logger {
|
|||
}
|
||||
}
|
||||
|
||||
export const logger = new Logger();
|
||||
export const logger = new Logger();
|
||||
|
|
|
|||
Loading…
Reference in a new issue