mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-21 08:41:57 +00:00
ui changes
This commit is contained in:
parent
91a42e6e29
commit
1756c28ed9
9 changed files with 23 additions and 27 deletions
|
|
@ -726,7 +726,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||||
|
|
||||||
DefaultRenderersFactory renderersFactory =
|
DefaultRenderersFactory renderersFactory =
|
||||||
new DefaultRenderersFactory(getContext())
|
new DefaultRenderersFactory(getContext())
|
||||||
.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF)
|
.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER)
|
||||||
.setEnableDecoderFallback(true)
|
.setEnableDecoderFallback(true)
|
||||||
.forceEnableMediaCodecAsynchronousQueueing();
|
.forceEnableMediaCodecAsynchronousQueueing();
|
||||||
|
|
||||||
|
|
|
||||||
2
package-lock.json
generated
2
package-lock.json
generated
|
|
@ -80,7 +80,7 @@
|
||||||
"react-native-reanimated-carousel": "^4.0.3",
|
"react-native-reanimated-carousel": "^4.0.3",
|
||||||
"react-native-safe-area-context": "~5.6.0",
|
"react-native-safe-area-context": "~5.6.0",
|
||||||
"react-native-screens": "~4.16.0",
|
"react-native-screens": "~4.16.0",
|
||||||
"react-native-svg": "15.12.1",
|
"react-native-svg": "^15.12.1",
|
||||||
"react-native-url-polyfill": "^2.0.0",
|
"react-native-url-polyfill": "^2.0.0",
|
||||||
"react-native-vector-icons": "^10.3.0",
|
"react-native-vector-icons": "^10.3.0",
|
||||||
"react-native-video": "^6.17.0",
|
"react-native-video": "^6.17.0",
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@
|
||||||
"react-native-reanimated-carousel": "^4.0.3",
|
"react-native-reanimated-carousel": "^4.0.3",
|
||||||
"react-native-safe-area-context": "~5.6.0",
|
"react-native-safe-area-context": "~5.6.0",
|
||||||
"react-native-screens": "~4.16.0",
|
"react-native-screens": "~4.16.0",
|
||||||
"react-native-svg": "15.12.1",
|
"react-native-svg": "^15.12.1",
|
||||||
"react-native-url-polyfill": "^2.0.0",
|
"react-native-url-polyfill": "^2.0.0",
|
||||||
"react-native-vector-icons": "^10.3.0",
|
"react-native-vector-icons": "^10.3.0",
|
||||||
"react-native-video": "^6.17.0",
|
"react-native-video": "^6.17.0",
|
||||||
|
|
|
||||||
|
|
@ -388,8 +388,8 @@ const styles = StyleSheet.create({
|
||||||
shadowOffset: { width: 0, height: 1 },
|
shadowOffset: { width: 0, height: 1 },
|
||||||
shadowOpacity: 0.05,
|
shadowOpacity: 0.05,
|
||||||
shadowRadius: 1,
|
shadowRadius: 1,
|
||||||
borderWidth: 0.5,
|
borderWidth: 1.5,
|
||||||
borderColor: 'rgba(255,255,255,0.12)',
|
borderColor: 'rgba(255,255,255,0.15)',
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
},
|
},
|
||||||
contentItemContainer: {
|
contentItemContainer: {
|
||||||
|
|
|
||||||
|
|
@ -710,6 +710,7 @@ const CarouselCard: React.FC<CarouselCardProps> = memo(({ item, colors, logoFail
|
||||||
</Text>
|
</Text>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
|
<TouchableOpacity activeOpacity={0.9} onPress={onPressInfo} style={StyleSheet.absoluteFillObject as any} />
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,8 @@ const styles = StyleSheet.create({
|
||||||
poster: {
|
poster: {
|
||||||
borderRadius: 8, // overridden responsively
|
borderRadius: 8, // overridden responsively
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: 'rgba(255,255,255,0.15)',
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
fontSize: 13, // overridden responsively
|
fontSize: 13, // overridden responsively
|
||||||
|
|
|
||||||
|
|
@ -85,11 +85,6 @@ 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;
|
||||||
// Roughly estimate text width to size SVG snugly (avoids overly wide background)
|
|
||||||
const charWidthFactor = 0.48; // even tighter average width per character
|
|
||||||
const estimatedLineWidths = lines.map(line => Math.max(1, line.length * displayFontSize * charWidthFactor));
|
|
||||||
const maxEstimatedLineWidth = estimatedLineWidths.length > 0 ? Math.max(...estimatedLineWidths) : displayFontSize * 2;
|
|
||||||
const svgWidth = Math.max(displayFontSize * 2, Math.ceil(maxEstimatedLineWidth + displayFontSize * 0.25));
|
|
||||||
|
|
||||||
// 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) => {
|
||||||
|
|
@ -145,19 +140,14 @@ export const CustomSubtitles: React.FC<CustomSubtitlesProps> = ({
|
||||||
backgroundColor: bgColor,
|
backgroundColor: bgColor,
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
alignSelf: 'center',
|
|
||||||
maxWidth: '90%',
|
|
||||||
paddingHorizontal: 4,
|
|
||||||
paddingVertical: 4,
|
|
||||||
transform: [{ scale: inverseScale }],
|
|
||||||
}
|
}
|
||||||
]}>
|
]}>
|
||||||
{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={svgWidth}
|
width={800}
|
||||||
height={svgHeight}
|
height={svgHeight}
|
||||||
viewBox={`0 0 ${svgWidth} ${svgHeight}`}
|
viewBox={`0 0 1000 ${svgHeight}`}
|
||||||
preserveAspectRatio="xMidYMax meet"
|
preserveAspectRatio="xMidYMax meet"
|
||||||
>
|
>
|
||||||
{(() => {
|
{(() => {
|
||||||
|
|
@ -169,10 +159,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 = svgWidth;
|
x = 1000;
|
||||||
} else {
|
} else {
|
||||||
anchor = align === 'center' ? 'middle' : align === 'left' ? 'start' : 'end';
|
anchor = align === 'center' ? 'middle' : align === 'left' ? 'start' : 'end';
|
||||||
x = align === 'center' ? svgWidth / 2 : (align === 'left' ? 0 : svgWidth);
|
x = align === 'center' ? 500 : (align === 'left' ? 0 : 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseFontSize = displayFontSize;
|
const baseFontSize = displayFontSize;
|
||||||
|
|
@ -258,6 +248,7 @@ export const CustomSubtitles: React.FC<CustomSubtitlesProps> = ({
|
||||||
letterSpacing: effectiveLetterSpacing,
|
letterSpacing: effectiveLetterSpacing,
|
||||||
fontSize: subtitleSize * inverseScale,
|
fontSize: subtitleSize * inverseScale,
|
||||||
lineHeight: subtitleSize * lineHeightMultiplier * inverseScale,
|
lineHeight: subtitleSize * lineHeightMultiplier * inverseScale,
|
||||||
|
transform: [{ scale: inverseScale }],
|
||||||
},
|
},
|
||||||
shadowStyle,
|
shadowStyle,
|
||||||
]}>
|
]}>
|
||||||
|
|
|
||||||
|
|
@ -1136,6 +1136,8 @@ const styles = StyleSheet.create({
|
||||||
shadowOffset: { width: 0, height: 4 },
|
shadowOffset: { width: 0, height: 4 },
|
||||||
shadowOpacity: 0.2,
|
shadowOpacity: 0.2,
|
||||||
shadowRadius: 8,
|
shadowRadius: 8,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: 'rgba(255,255,255,0.15)',
|
||||||
},
|
},
|
||||||
poster: {
|
poster: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|
|
||||||
|
|
@ -1260,14 +1260,6 @@ const MetadataScreen: React.FC = () => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Recommendations Section with skeleton when loading - Lazy loaded */}
|
|
||||||
{type === 'movie' && shouldLoadSecondaryData && (
|
|
||||||
<MemoizedMoreLikeThisSection
|
|
||||||
recommendations={recommendations}
|
|
||||||
loadingRecommendations={loadingRecommendations}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Series/Movie Content with episode skeleton when loading */}
|
{/* Series/Movie Content with episode skeleton when loading */}
|
||||||
{Object.keys(groupedEpisodes).length > 0 ? (
|
{Object.keys(groupedEpisodes).length > 0 ? (
|
||||||
<MemoizedSeriesContent
|
<MemoizedSeriesContent
|
||||||
|
|
@ -1394,6 +1386,14 @@ const MetadataScreen: React.FC = () => {
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Recommendations Section with skeleton when loading - Shown at bottom for shows */}
|
||||||
|
{shouldLoadSecondaryData && (
|
||||||
|
<MemoizedMoreLikeThisSection
|
||||||
|
recommendations={recommendations}
|
||||||
|
loadingRecommendations={loadingRecommendations}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</Animated.ScrollView>
|
</Animated.ScrollView>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue