mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-10 20:10:54 +00:00
catalog parallel fetching and subtitle backgound fix
This commit is contained in:
parent
8e34fbb124
commit
2ba7c3c057
4 changed files with 30 additions and 30 deletions
|
|
@ -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,
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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(() => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue