From c92dfb149cae415394a583d0d8fc8449821a3848 Mon Sep 17 00:00:00 2001 From: tapframe Date: Tue, 9 Sep 2025 00:33:30 +0530 Subject: [PATCH] many major fixes --- src/components/UpdatePopup.tsx | 18 +++--- src/components/common/OptimizedImage.tsx | 6 +- src/components/metadata/HeroSection.tsx | 26 ++++---- src/hooks/useFeaturedContent.ts | 4 +- src/screens/AddonsScreen.tsx | 82 ++++++++++++++++++++++++ src/screens/UpdateScreen.tsx | 7 +- src/services/SyncService.ts | 2 +- src/services/catalogService.ts | 4 +- src/services/imageCacheService.ts | 8 +-- src/services/localScraperService.ts | 4 +- src/services/notificationService.ts | 8 +-- src/services/robustCalendarCache.ts | 2 +- src/services/seriesGraphService.ts | 0 src/services/traktService.ts | 10 ++- 14 files changed, 130 insertions(+), 51 deletions(-) create mode 100644 src/services/seriesGraphService.ts diff --git a/src/components/UpdatePopup.tsx b/src/components/UpdatePopup.tsx index 223596e0..31b23133 100644 --- a/src/components/UpdatePopup.tsx +++ b/src/components/UpdatePopup.tsx @@ -129,14 +129,16 @@ const UpdatePopup: React.FC = ({ ]}> Version: - - {updateInfo.manifest?.id ? - `${updateInfo.manifest.id.substring(0, 8)}...` : - 'Latest' - } + + {updateInfo.manifest?.id || 'Latest'} diff --git a/src/components/common/OptimizedImage.tsx b/src/components/common/OptimizedImage.tsx index 545808b7..804b22c4 100644 --- a/src/components/common/OptimizedImage.tsx +++ b/src/components/common/OptimizedImage.tsx @@ -102,7 +102,7 @@ const OptimizedImage: React.FC = ({ if (mountedRef.current) { setIsVisible(true); } - }, priority === 'high' ? 100 : priority === 'normal' ? 300 : 500); + }, priority === 'high' ? 200 : priority === 'normal' ? 500 : 1000); return () => clearTimeout(timer); } @@ -124,8 +124,8 @@ const OptimizedImage: React.FC = ({ } }, 10000); // 10 second timeout - // Prefetch the image - await ExpoImage.prefetch(cachedUrl); + // Skip prefetch to reduce memory pressure and heating + // await ExpoImage.prefetch(cachedUrl); if (mountedRef.current) { setIsLoaded(true); diff --git a/src/components/metadata/HeroSection.tsx b/src/components/metadata/HeroSection.tsx index 33e7d9c2..3d0ddc1f 100644 --- a/src/components/metadata/HeroSection.tsx +++ b/src/components/metadata/HeroSection.tsx @@ -1080,19 +1080,19 @@ const HeroSection: React.FC = memo(({ }; }, [imageOpacity, imageLoadOpacity, shimmerOpacity, trailerOpacity, thumbnailOpacity, actionButtonsOpacity, titleCardTranslateY, genreOpacity, watchProgressOpacity, buttonsOpacity, buttonsTranslateY, logoOpacity, heroOpacity, heroHeight]); - // Development-only performance monitoring - useEffect(() => { - if (__DEV__) { - const startTime = Date.now(); - const timer = setTimeout(() => { - const renderTime = Date.now() - startTime; - if (renderTime > 100) { - console.warn(`[HeroSection] Slow render detected: ${renderTime}ms`); - } - }, 0); - return () => clearTimeout(timer); - } - }); + // Disabled performance monitoring to reduce CPU overhead in production + // useEffect(() => { + // if (__DEV__) { + // const startTime = Date.now(); + // const timer = setTimeout(() => { + // const renderTime = Date.now() - startTime; + // if (renderTime > 100) { + // console.warn(`[HeroSection] Slow render detected: ${renderTime}ms`); + // } + // }, 0); + // return () => clearTimeout(timer); + // } + // }); diff --git a/src/hooks/useFeaturedContent.ts b/src/hooks/useFeaturedContent.ts index 52113c37..fefaab5f 100644 --- a/src/hooks/useFeaturedContent.ts +++ b/src/hooks/useFeaturedContent.ts @@ -557,8 +557,8 @@ export function useFeaturedContent() { } }; - // Increased rotation interval from 15s to 45s to reduce heating - const intervalId = setInterval(rotateContent, 45000); + // Further increased rotation interval to 90s to reduce CPU cycles + const intervalId = setInterval(rotateContent, 90000); return () => clearInterval(intervalId); }, [allFeaturedContent]); diff --git a/src/screens/AddonsScreen.tsx b/src/screens/AddonsScreen.tsx index b0253b28..2d6d1928 100644 --- a/src/screens/AddonsScreen.tsx +++ b/src/screens/AddonsScreen.tsx @@ -608,6 +608,28 @@ const AddonsScreen = () => { const [communityLoading, setCommunityLoading] = useState(true); const [communityError, setCommunityError] = useState(null); + // Promotional addon: Nuvio Streams + const PROMO_ADDON_URL = 'https://nuviostreams.hayd.uk/manifest.json'; + const promoAddon: ExtendedManifest = { + id: 'org.nuvio.streams', + name: 'Nuvio Streams | Elfhosted', + version: '0.5.0', + description: 'Stremio addon for high-quality streaming links.', + // @ts-ignore - logo not in base manifest type + logo: 'https://raw.githubusercontent.com/tapframe/NuvioStreaming/refs/heads/appstore/assets/titlelogo.png', + types: ['movie', 'series'], + catalogs: [], + behaviorHints: { configurable: true }, + // help handleConfigureAddon derive configure URL from the transport + transport: PROMO_ADDON_URL, + } as ExtendedManifest; + const isPromoInstalled = addons.some(a => + a.id === 'org.nuvio.streams' || + (typeof a.id === 'string' && a.id.includes('nuviostreams.hayd.uk')) || + (typeof a.transport === 'string' && a.transport.includes('nuviostreams.hayd.uk')) || + (typeof (a as any).url === 'string' && (a as any).url.includes('nuviostreams.hayd.uk')) + ); + useEffect(() => { loadAddons(); loadCommunityAddons(); @@ -1129,6 +1151,7 @@ const AddonsScreen = () => { showsVerticalScrollIndicator={false} contentInsetAdjustmentBehavior="automatic" > + {/* Overview Section */} OVERVIEW @@ -1195,6 +1218,65 @@ const AddonsScreen = () => { {/* Separator */} + {/* Promotional Addon Section (hidden if installed) */} + {!isPromoInstalled && ( + + OFFICIAL ADDON + + + + {promoAddon.logo ? ( + + ) : ( + + + + )} + + {promoAddon.name} + + v{promoAddon.version} + + {promoAddon.types?.map(t => t.charAt(0).toUpperCase() + t.slice(1)).join(' • ')} + + + + {promoAddon.behaviorHints?.configurable && ( + handleConfigureAddon(promoAddon, PROMO_ADDON_URL)} + > + + + )} + handleAddAddon(PROMO_ADDON_URL)} + disabled={installing} + > + {installing ? ( + + ) : ( + + )} + + + + + {promoAddon.description} + + + Configure and install for full functionality. + + + + + )} + {/* Community Addons Section */} COMMUNITY ADDONS diff --git a/src/screens/UpdateScreen.tsx b/src/screens/UpdateScreen.tsx index a31f50fd..53408b2d 100644 --- a/src/screens/UpdateScreen.tsx +++ b/src/screens/UpdateScreen.tsx @@ -93,7 +93,7 @@ const UpdateScreen: React.FC = () => { if (info.isAvailable) { setUpdateStatus('available'); - setLastOperation(`Update available: ${info.manifest?.id?.substring(0, 8) || 'unknown'}...`); + setLastOperation(`Update available: ${info.manifest?.id || 'unknown'}`); } else { setUpdateStatus('idle'); setLastOperation('No updates available'); @@ -484,8 +484,9 @@ const UpdateScreen: React.FC = () => { Current version: - - {currentInfo?.manifest?.id ? `${currentInfo.manifest.id.substring(0, 8)}...` : (currentInfo?.isEmbeddedLaunch === false ? 'Unknown' : 'Embedded')} + + {currentInfo?.manifest?.id || (currentInfo?.isEmbeddedLaunch === false ? 'Unknown' : 'Embedded')} diff --git a/src/services/SyncService.ts b/src/services/SyncService.ts index b36de869..f4e569d3 100644 --- a/src/services/SyncService.ts +++ b/src/services/SyncService.ts @@ -213,7 +213,7 @@ class SyncService { } catch (e) { // silent } - }, 14400000); + }, 21600000); // Increased from 4 hours to 6 hours to reduce background CPU }; unsubscribeRealtime = (): void => { diff --git a/src/services/catalogService.ts b/src/services/catalogService.ts index b0b1994a..a1129fb5 100644 --- a/src/services/catalogService.ts +++ b/src/services/catalogService.ts @@ -482,11 +482,11 @@ class CatalogService { async getContentDetails(type: string, id: string, preferredAddonId?: string): Promise { try { - // Try up to 3 times with increasing delays + // Try up to 2 times with increasing delays to reduce CPU load let meta = null; let lastError = null; - for (let i = 0; i < 3; i++) { + for (let i = 0; i < 2; i++) { try { meta = await stremioService.getMetaDetails(type, id, preferredAddonId); if (meta) break; diff --git a/src/services/imageCacheService.ts b/src/services/imageCacheService.ts index ecd1d3ac..72b582a0 100644 --- a/src/services/imageCacheService.ts +++ b/src/services/imageCacheService.ts @@ -189,9 +189,7 @@ class ImageCacheService { removedCount++; } - if (removedCount > 0) { - logger.log(`[ImageCache] Evicted ${removedCount} entries to free memory. Current usage: ${(this.currentMemoryUsage / 1024 / 1024).toFixed(1)}MB`); - } + // Skip verbose memory eviction logging to reduce CPU load } /** @@ -236,9 +234,7 @@ class ImageCacheService { const finalSize = this.cache.size; const finalMemory = this.currentMemoryUsage; - if (initialSize !== finalSize || Math.abs(initialMemory - finalMemory) > 1024 * 1024) { - logger.log(`[ImageCache] Cleanup completed: ${initialSize}→${finalSize} entries, ${(initialMemory / 1024 / 1024).toFixed(1)}→${(finalMemory / 1024 / 1024).toFixed(1)}MB`); - } + // Skip verbose cleanup logging to reduce CPU load } /** diff --git a/src/services/localScraperService.ts b/src/services/localScraperService.ts index 98113123..827f73d5 100644 --- a/src/services/localScraperService.ts +++ b/src/services/localScraperService.ts @@ -977,7 +977,7 @@ class LocalScraperService { throw new Error(`No code found for scraper ${scraper.id}`); } - logger.log('[LocalScraperService] Executing scraper:', scraper.name); + // Skip verbose logging to reduce CPU load // Load per-scraper settings const scraperSettings = await this.getScraperSettings(scraper.id); @@ -999,7 +999,7 @@ class LocalScraperService { callback(streams, scraper.id, scraper.name, null); } - logger.log('[LocalScraperService] Scraper', scraper.name, 'returned', streams.length, 'streams'); + // Skip verbose logging to reduce CPU load } catch (error) { logger.error('[LocalScraperService] Scraper', scraper.name, 'failed:', error); diff --git a/src/services/notificationService.ts b/src/services/notificationService.ts index 352d5109..85a90e31 100644 --- a/src/services/notificationService.ts +++ b/src/services/notificationService.ts @@ -285,14 +285,14 @@ class NotificationService { // Setup background sync for notifications private setupBackgroundSync(): void { - // Sync notifications every 6 hours + // Sync notifications every 12 hours to reduce background CPU usage this.backgroundSyncInterval = setInterval(async () => { if (this.settings.enabled) { // Reduced logging verbosity // logger.log('[NotificationService] Running background notification sync'); await this.performBackgroundSync(); } - }, 6 * 60 * 60 * 1000); // 6 hours + }, 12 * 60 * 60 * 1000); // 12 hours } // Setup app state handling for foreground sync @@ -326,8 +326,8 @@ class NotificationService { for (const series of seriesItems) { await this.updateNotificationsForSeries(series.id); - // Small delay to prevent overwhelming the API - await new Promise(resolve => setTimeout(resolve, 100)); + // Longer delay to prevent overwhelming the API and reduce heating + await new Promise(resolve => setTimeout(resolve, 500)); } // Reduced logging verbosity diff --git a/src/services/robustCalendarCache.ts b/src/services/robustCalendarCache.ts index b50ebe56..ad36e9c8 100644 --- a/src/services/robustCalendarCache.ts +++ b/src/services/robustCalendarCache.ts @@ -17,7 +17,7 @@ interface TraktCollections { const THIS_WEEK_CACHE_KEY = 'this_week_episodes_cache'; const CALENDAR_CACHE_KEY = 'calendar_data_cache'; -const CACHE_DURATION_MS = 15 * 60 * 1000; // 15 minutes +const CACHE_DURATION_MS = 30 * 60 * 1000; // 30 minutes (increased to reduce API calls) const ERROR_CACHE_DURATION_MS = 5 * 60 * 1000; // 5 minutes for error recovery class RobustCalendarCache { diff --git a/src/services/seriesGraphService.ts b/src/services/seriesGraphService.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/services/traktService.ts b/src/services/traktService.ts index 3bce8074..9b806921 100644 --- a/src/services/traktService.ts +++ b/src/services/traktService.ts @@ -260,7 +260,7 @@ export class TraktService { // Rate limiting private lastApiCall: number = 0; - private readonly MIN_API_INTERVAL = 1000; // Minimum 1 second between API calls + private readonly MIN_API_INTERVAL = 2000; // Minimum 2 seconds between API calls (reduce heating) private requestQueue: Array<() => Promise> = []; private isProcessingQueue: boolean = false; @@ -272,11 +272,11 @@ export class TraktService { // Track currently watching sessions to avoid duplicate starts// Sync debouncing private currentlyWatching: Set = new Set(); private lastSyncTimes: Map = new Map(); - private readonly SYNC_DEBOUNCE_MS = 1000; // 1 second for immediate sync + private readonly SYNC_DEBOUNCE_MS = 15000; // 15 seconds to align with player save interval // Debounce for stop calls private lastStopCalls: Map = new Map(); - private readonly STOP_DEBOUNCE_MS = 1000; // 1 second debounce for immediate stop calls + private readonly STOP_DEBOUNCE_MS = 3000; // 3 seconds to avoid duplicate stop calls // Default completion threshold (overridden by user settings) private readonly DEFAULT_COMPLETION_THRESHOLD = 80; // 80% @@ -356,9 +356,7 @@ export class TraktService { } } - if (cleanupCount > 0) { - logger.log(`[TraktService] Cleaned up ${cleanupCount} old tracking entries`); - } + // Skip verbose cleanup logging to reduce CPU load } public static getInstance(): TraktService {