catalog parallel fetching and subtitle backgound fix

This commit is contained in:
tapframe 2025-11-03 22:33:33 +05:30
parent 8e34fbb124
commit 2ba7c3c057
4 changed files with 30 additions and 30 deletions

View file

@ -41,19 +41,19 @@ export const MetadataLoadingScreen = forwardRef<MetadataLoadingScreenRef, Metada
const exitAnimation = Animated.parallel([ const exitAnimation = Animated.parallel([
Animated.timing(sceneOpacity, { Animated.timing(sceneOpacity, {
toValue: 0, toValue: 0,
duration: 200, duration: 100,
easing: Easing.bezier(0.25, 0.1, 0.25, 1.0), easing: Easing.bezier(0.25, 0.1, 0.25, 1.0),
useNativeDriver: true, useNativeDriver: true,
}), }),
Animated.timing(sceneScale, { Animated.timing(sceneScale, {
toValue: 0.95, toValue: 0.95,
duration: 200, duration: 100,
easing: Easing.bezier(0.25, 0.1, 0.25, 1.0), easing: Easing.bezier(0.25, 0.1, 0.25, 1.0),
useNativeDriver: true, useNativeDriver: true,
}), }),
Animated.timing(sceneTranslateY, { Animated.timing(sceneTranslateY, {
toValue: 8, toValue: 8,
duration: 200, duration: 100,
easing: Easing.bezier(0.25, 0.1, 0.25, 1.0), easing: Easing.bezier(0.25, 0.1, 0.25, 1.0),
useNativeDriver: true, useNativeDriver: true,
}), }),
@ -74,19 +74,19 @@ export const MetadataLoadingScreen = forwardRef<MetadataLoadingScreenRef, Metada
const sceneAnimation = Animated.parallel([ const sceneAnimation = Animated.parallel([
Animated.timing(sceneOpacity, { Animated.timing(sceneOpacity, {
toValue: 1, toValue: 1,
duration: 200, duration: 100,
easing: Easing.bezier(0.25, 0.1, 0.25, 1.0), easing: Easing.bezier(0.25, 0.1, 0.25, 1.0),
useNativeDriver: true, useNativeDriver: true,
}), }),
Animated.timing(sceneScale, { Animated.timing(sceneScale, {
toValue: 1, toValue: 1,
duration: 200, duration: 100,
easing: Easing.bezier(0.25, 0.1, 0.25, 1.0), easing: Easing.bezier(0.25, 0.1, 0.25, 1.0),
useNativeDriver: true, useNativeDriver: true,
}), }),
Animated.timing(sceneTranslateY, { Animated.timing(sceneTranslateY, {
toValue: 0, toValue: 0,
duration: 200, duration: 100,
easing: Easing.bezier(0.25, 0.1, 0.25, 1.0), easing: Easing.bezier(0.25, 0.1, 0.25, 1.0),
useNativeDriver: true, useNativeDriver: true,
}), }),

View file

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { View, Text } from 'react-native'; import { View, Text, Dimensions } from 'react-native';
import Svg, { Text as SvgText, TSpan } from 'react-native-svg'; import Svg, { Text as SvgText, TSpan } from 'react-native-svg';
import { styles } from '../utils/playerStyles'; import { styles } from '../utils/playerStyles';
import { SubtitleSegment } from '../utils/playerTypes'; import { SubtitleSegment } from '../utils/playerTypes';
@ -85,6 +85,13 @@ export const CustomSubtitles: React.FC<CustomSubtitlesProps> = ({
const displayFontSize = subtitleSize * inverseScale; const displayFontSize = subtitleSize * inverseScale;
const displayLineHeight = subtitleSize * lineHeightMultiplier * inverseScale; const displayLineHeight = subtitleSize * lineHeightMultiplier * inverseScale;
const svgHeight = lines.length * displayLineHeight; const svgHeight = lines.length * displayLineHeight;
// Estimate text width to keep background from spanning full screen when using SVG
const windowWidth = Math.min(Dimensions.get('window').width, Dimensions.get('window').height);
const longestLineChars = Math.max(1, ...lines.map(l => l.length));
const estimatedContentWidth = Math.min(
Math.max(100, Math.ceil(longestLineChars * displayFontSize * 0.6)),
Math.max(140, windowWidth - 40)
);
// Helper to render formatted segments // Helper to render formatted segments
const renderFormattedText = (segments: SubtitleSegment[], lineIndex: number, keyPrefix: string, isRTL?: boolean, customLetterSpacing?: number) => { const renderFormattedText = (segments: SubtitleSegment[], lineIndex: number, keyPrefix: string, isRTL?: boolean, customLetterSpacing?: number) => {
@ -140,14 +147,16 @@ export const CustomSubtitles: React.FC<CustomSubtitlesProps> = ({
backgroundColor: bgColor, backgroundColor: bgColor,
position: 'relative', position: 'relative',
alignItems: 'center', alignItems: 'center',
alignSelf: 'center',
maxWidth: windowWidth - 40,
} }
]}> ]}>
{useCrispSvgOutline ? ( {useCrispSvgOutline ? (
// Crisp outline using react-native-svg (stroke under, fill on top) // Crisp outline using react-native-svg (stroke under, fill on top)
<Svg <Svg
width={800} width={estimatedContentWidth}
height={svgHeight} height={svgHeight}
viewBox={`0 0 1000 ${svgHeight}`} viewBox={`0 0 ${estimatedContentWidth} ${svgHeight}`}
preserveAspectRatio="xMidYMax meet" preserveAspectRatio="xMidYMax meet"
> >
{(() => { {(() => {
@ -159,10 +168,10 @@ export const CustomSubtitles: React.FC<CustomSubtitlesProps> = ({
if (isRTL) { if (isRTL) {
// For RTL, always use 'end' anchor to position from right edge // For RTL, always use 'end' anchor to position from right edge
anchor = 'end'; anchor = 'end';
x = 1000; x = estimatedContentWidth;
} else { } else {
anchor = align === 'center' ? 'middle' : align === 'left' ? 'start' : 'end'; anchor = align === 'center' ? 'middle' : align === 'left' ? 'start' : 'end';
x = align === 'center' ? 500 : (align === 'left' ? 0 : 1000); x = align === 'center' ? (estimatedContentWidth / 2) : (align === 'left' ? 0 : estimatedContentWidth);
} }
const baseFontSize = displayFontSize; const baseFontSize = displayFontSize;

View file

@ -65,26 +65,26 @@ export const useMetadataAnimations = (safeAreaTop: number, watchProgress: any) =
try { try {
// Start with slightly reduced values and animate to full visibility // Start with slightly reduced values and animate to full visibility
screenOpacity.value = withTiming(1, { screenOpacity.value = withTiming(1, {
duration: 250, duration: 100,
easing: easings.fast easing: easings.fast
}); });
heroOpacity.value = withTiming(1, { heroOpacity.value = withTiming(1, {
duration: 300, duration: 100,
easing: easings.fast easing: easings.fast
}); });
heroScale.value = withSpring(1, ultraFastSpring); heroScale.value = withSpring(1, ultraFastSpring);
uiElementsOpacity.value = withTiming(1, { uiElementsOpacity.value = withTiming(1, {
duration: 400, duration: 100,
easing: easings.natural easing: easings.natural
}); });
uiElementsTranslateY.value = withSpring(0, fastSpring); uiElementsTranslateY.value = withSpring(0, fastSpring);
contentOpacity.value = withTiming(1, { contentOpacity.value = withTiming(1, {
duration: 350, duration: 100,
easing: easings.fast easing: easings.fast
}); });
} catch (error) { } catch (error) {

View file

@ -188,21 +188,12 @@ const HomeScreen = () => {
let catalogIndex = 0; let catalogIndex = 0;
const catalogQueue: (() => Promise<void>)[] = []; const catalogQueue: (() => Promise<void>)[] = [];
// Limit concurrent catalog loading to prevent overwhelming the system // Launch all catalog loaders in parallel
const MAX_CONCURRENT_CATALOGS = 1; // Single catalog at a time to minimize heating/memory const launchAllCatalogs = () => {
let activeCatalogLoads = 0; while (catalogQueue.length > 0) {
const processCatalogQueue = async () => {
while (catalogQueue.length > 0 && activeCatalogLoads < MAX_CONCURRENT_CATALOGS) {
const catalogLoader = catalogQueue.shift(); const catalogLoader = catalogQueue.shift();
if (catalogLoader) { if (catalogLoader) {
activeCatalogLoads++; catalogLoader();
catalogLoader().finally(async () => {
activeCatalogLoads--;
// Yield to event loop to avoid JS thread starvation and reduce heating
await new Promise(resolve => setTimeout(resolve, 100));
processCatalogQueue(); // Process next in queue
});
} }
} }
}; };
@ -318,8 +309,8 @@ const HomeScreen = () => {
setCatalogs(new Array(catalogIndex).fill(null)); setCatalogs(new Array(catalogIndex).fill(null));
}); });
// Start processing the catalog queue // Start all catalog requests in parallel
processCatalogQueue(); launchAllCatalogs();
} catch (error) { } catch (error) {
if (__DEV__) console.error('[HomeScreen] Error in progressive catalog loading:', error); if (__DEV__) console.error('[HomeScreen] Error in progressive catalog loading:', error);
InteractionManager.runAfterInteractions(() => { InteractionManager.runAfterInteractions(() => {