heating optimization

This commit is contained in:
tapframe 2025-09-08 22:38:03 +05:30
parent 02bfd85b5a
commit 6bb4d927ed
8 changed files with 34 additions and 47 deletions

View file

@ -164,10 +164,11 @@ const ContentItem = ({ item, onPress }: ContentItemProps) => {
style={[styles.poster, { backgroundColor: currentTheme.colors.elevation1, borderRadius: posterRadius }]}
contentFit="cover"
cachePolicy="memory-disk" // Use both memory and disk cache
transition={200} // Add smooth transition
transition={0} // Disable transition to reduce GPU work
placeholder={{ blurhash: PLACEHOLDER_BLURHASH } as any}
placeholderContentFit="cover"
allowDownscaling
priority="low" // Deprioritize decode for long lists
onLoad={() => {
setImageLoaded(true);
setImageError(false);
@ -183,7 +184,6 @@ const ContentItem = ({ item, onPress }: ContentItemProps) => {
setImageError(true);
setImageLoaded(false);
}}
priority="normal" // Increase priority for better loading
recyclingKey={item.id} // Add recycling key for better performance
/>
) : (
@ -239,11 +239,11 @@ const styles = StyleSheet.create({
borderRadius: 12,
overflow: 'hidden',
position: 'relative',
elevation: Platform.OS === 'android' ? 2 : 0,
elevation: Platform.OS === 'android' ? 1 : 0,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
shadowOpacity: 0.05,
shadowRadius: 1,
borderWidth: 0.5,
borderColor: 'rgba(255,255,255,0.12)',
marginBottom: 8,

View file

@ -157,10 +157,10 @@ const HeroCarousel: React.FC<HeroCarouselProps> = ({ items, loading = false }) =
source={{ uri: item.banner || item.poster }}
style={styles.backgroundImage as ImageStyle}
contentFit="cover"
blurRadius={Platform.OS === 'android' ? 12 : 20}
blurRadius={Platform.OS === 'android' ? 8 : 12}
cachePolicy="memory-disk"
transition={200}
priority="high"
transition={0}
priority="low"
/>
<LinearGradient
colors={["rgba(0,0,0,0.45)", "rgba(0,0,0,0.75)"]}
@ -270,7 +270,7 @@ const CarouselCard: React.FC<CarouselCardProps> = memo(({ item, colors, logoFail
source={{ uri: item.banner || item.poster }}
style={styles.banner as ImageStyle}
contentFit="cover"
transition={300}
transition={0}
cachePolicy="memory-disk"
/>
<LinearGradient
@ -285,7 +285,7 @@ const CarouselCard: React.FC<CarouselCardProps> = memo(({ item, colors, logoFail
source={{ uri: item.logo }}
style={styles.logo as ImageStyle}
contentFit="contain"
transition={250}
transition={0}
cachePolicy="memory-disk"
onError={onLogoError}
/>
@ -360,11 +360,11 @@ const styles = StyleSheet.create({
height: CARD_HEIGHT,
borderRadius: 16,
overflow: 'hidden',
elevation: 6,
elevation: 2,
shadowColor: '#000',
shadowOffset: { width: 0, height: 6 },
shadowOpacity: 0.3,
shadowRadius: 12,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.15,
shadowRadius: 4,
},
skeletonCard: {
width: CARD_WIDTH,

View file

@ -515,8 +515,8 @@ const AndroidVideoPlayer: React.FC = () => {
clearInterval(progressSaveInterval);
}
// IMMEDIATE SYNC: Reduce sync interval to 5 seconds for near real-time sync
const syncInterval = 5000; // 5 seconds for immediate sync
// HEATING FIX: Increase sync interval to 15 seconds to reduce CPU load
const syncInterval = 15000; // 15 seconds to prevent heating
const interval = setInterval(() => {
saveWatchProgress();
@ -2032,7 +2032,7 @@ const AndroidVideoPlayer: React.FC = () => {
playWhenInactive={false}
ignoreSilentSwitch="ignore"
mixWithOthers="inherit"
progressUpdateInterval={250}
progressUpdateInterval={1000}
bufferConfig={{
minBufferMs: 15000,
maxBufferMs: 50000,

View file

@ -547,8 +547,8 @@ const VideoPlayer: React.FC = () => {
clearInterval(progressSaveInterval);
}
// IMMEDIATE SYNC: Reduce sync interval to 5 seconds for near real-time sync
const syncInterval = 5000; // 5 seconds for immediate sync
// HEATING FIX: Increase sync interval to 15 seconds to reduce CPU load
const syncInterval = 15000; // 15 seconds to prevent heating
const interval = setInterval(() => {
saveWatchProgress();

View file

@ -870,8 +870,8 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
});
};
// Check completion periodically
const completionInterval = setInterval(checkScrapersCompletion, 1000);
// Check completion less frequently to reduce CPU load
const completionInterval = setInterval(checkScrapersCompletion, 2000);
// Fallback timeout after 30 seconds
const fallbackTimeout = setTimeout(() => {
@ -1039,8 +1039,8 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
});
};
// Check completion periodically
const episodeCompletionInterval = setInterval(checkEpisodeScrapersCompletion, 1000);
// Check completion less frequently to reduce CPU load
const episodeCompletionInterval = setInterval(checkEpisodeScrapersCompletion, 2000);
// Fallback timeout after 30 seconds
const episodeFallbackTimeout = setTimeout(() => {

View file

@ -161,7 +161,7 @@ export const useMetadataAnimations = (safeAreaTop: number, watchProgress: any) =
// Use single progress value for all header animations
if (headerProgress.value !== progress) {
headerProgress.value = withTiming(progress, {
duration: progress ? 200 : 150,
duration: progress ? 150 : 100,
easing: easings.ultraFast
});
}

View file

@ -158,7 +158,7 @@ const HomeScreen = () => {
let catalogIndex = 0;
// Limit concurrent catalog loading to prevent overwhelming the system
const MAX_CONCURRENT_CATALOGS = 3; // Lower concurrency to reduce CPU/network spikes
const MAX_CONCURRENT_CATALOGS = 2; // Very low concurrency to reduce heating
let activeCatalogLoads = 0;
const catalogQueue: (() => Promise<void>)[] = [];
@ -169,8 +169,8 @@ const HomeScreen = () => {
activeCatalogLoads++;
catalogLoader().finally(async () => {
activeCatalogLoads--;
// Yield to event loop to avoid JS thread starvation
await new Promise(resolve => setTimeout(resolve, 10));
// Yield to event loop to avoid JS thread starvation and reduce heating
await new Promise(resolve => setTimeout(resolve, 50));
processCatalogQueue(); // Process next in queue
});
}
@ -605,14 +605,7 @@ const HomeScreen = () => {
// Add memory cleanup on scroll end
const handleScrollEnd = useCallback(() => {
// Clear memory cache after scroll settles to free up RAM
setTimeout(() => {
try {
ExpoImage.clearMemoryCache();
} catch (error) {
// Ignore errors
}
}, 1000);
// No-op; avoid clearing image memory cache here to prevent decode thrash/heating
}, []);
// Memoize individual section components to prevent re-renders
@ -765,7 +758,6 @@ const HomeScreen = () => {
showsVerticalScrollIndicator={false}
ListHeaderComponent={memoizedHeader}
ListFooterComponent={ListFooterComponent}
onMomentumScrollEnd={handleScrollEnd}
onEndReached={handleLoadMoreCatalogs}
onEndReachedThreshold={0.6}
scrollEventThrottle={32}

View file

@ -20,10 +20,10 @@ class ImageCacheService {
private cleanupInterval: NodeJS.Timeout | null = null;
constructor() {
// Start cleanup interval every 10 minutes
// Start cleanup interval every 30 minutes (less churn)
this.cleanupInterval = setInterval(() => {
this.performCleanup();
}, 10 * 60 * 1000);
}, 30 * 60 * 1000);
}
/**
@ -40,13 +40,13 @@ class ImageCacheService {
// Update access tracking
cached.accessCount++;
cached.lastAccessed = Date.now();
logger.log(`[ImageCache] Retrieved from cache: ${originalUrl.substring(0, 50)}...`);
// Skip verbose logging to reduce CPU load
return cached.localPath;
}
// Check memory pressure before adding new entries (more lenient)
if (this.cache.size >= this.MAX_CACHE_SIZE * 0.95) {
logger.log(`[ImageCache] Skipping cache due to size limit`);
// Skip verbose logging to reduce CPU load
return originalUrl;
}
@ -68,7 +68,7 @@ class ImageCacheService {
this.currentMemoryUsage += estimatedSize;
this.enforceMemoryLimits();
logger.log(`[ImageCache] ✅ NEW CACHE ENTRY: ${originalUrl.substring(0, 50)}... (Cache: ${this.cache.size}/${this.MAX_CACHE_SIZE}, Memory: ${(this.currentMemoryUsage / 1024 / 1024).toFixed(1)}MB)`);
// Skip verbose logging to reduce CPU load
return cachedImage.localPath;
} catch (error) {
logger.error('[ImageCache] Failed to cache image:', error);
@ -231,12 +231,7 @@ class ImageCacheService {
this.enforceMemoryLimits();
this.enforceMaxCacheSize();
// Clear Expo image memory cache periodically
try {
ExpoImage.clearMemoryCache();
} catch (error) {
// Ignore errors from clearing memory cache
}
// Avoid clearing Expo's global memory cache to prevent re-decode churn
const finalSize = this.cache.size;
const finalMemory = this.currentMemoryUsage;