mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-11 20:40:42 +00:00
floating header logo fetch fix
This commit is contained in:
parent
1535ef9aac
commit
fd5861026d
3 changed files with 23 additions and 12 deletions
|
|
@ -6,6 +6,7 @@ import {
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
Platform,
|
Platform,
|
||||||
Dimensions,
|
Dimensions,
|
||||||
|
Image,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { BlurView as ExpoBlurView } from 'expo-blur';
|
import { BlurView as ExpoBlurView } from 'expo-blur';
|
||||||
import { MaterialIcons, Feather } from '@expo/vector-icons';
|
import { MaterialIcons, Feather } from '@expo/vector-icons';
|
||||||
|
|
@ -24,7 +25,6 @@ if (Platform.OS === 'ios') {
|
||||||
liquidGlassAvailable = false;
|
liquidGlassAvailable = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
import FastImage from '@d11/react-native-fast-image';
|
|
||||||
import Animated, {
|
import Animated, {
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
interpolate,
|
interpolate,
|
||||||
|
|
@ -49,6 +49,7 @@ interface FloatingHeaderProps {
|
||||||
headerElementsOpacity: SharedValue<number>;
|
headerElementsOpacity: SharedValue<number>;
|
||||||
safeAreaTop: number;
|
safeAreaTop: number;
|
||||||
setLogoLoadError: (error: boolean) => void;
|
setLogoLoadError: (error: boolean) => void;
|
||||||
|
stableLogoUri?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FloatingHeader: React.FC<FloatingHeaderProps> = ({
|
const FloatingHeader: React.FC<FloatingHeaderProps> = ({
|
||||||
|
|
@ -62,6 +63,7 @@ const FloatingHeader: React.FC<FloatingHeaderProps> = ({
|
||||||
headerElementsOpacity,
|
headerElementsOpacity,
|
||||||
safeAreaTop,
|
safeAreaTop,
|
||||||
setLogoLoadError,
|
setLogoLoadError,
|
||||||
|
stableLogoUri,
|
||||||
}) => {
|
}) => {
|
||||||
const { currentTheme } = useTheme();
|
const { currentTheme } = useTheme();
|
||||||
const [isHeaderInteractive, setIsHeaderInteractive] = React.useState(false);
|
const [isHeaderInteractive, setIsHeaderInteractive] = React.useState(false);
|
||||||
|
|
@ -111,13 +113,13 @@ const FloatingHeader: React.FC<FloatingHeaderProps> = ({
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<View style={styles.headerTitleContainer}>
|
<View style={styles.headerTitleContainer}>
|
||||||
{metadata.logo && !logoLoadError ? (
|
{(stableLogoUri || metadata.logo) && !logoLoadError ? (
|
||||||
<FastImage
|
<Image
|
||||||
source={{ uri: metadata.logo }}
|
source={{ uri: stableLogoUri || metadata.logo }}
|
||||||
style={styles.floatingHeaderLogo}
|
style={styles.floatingHeaderLogo}
|
||||||
resizeMode={FastImage.resizeMode.contain}
|
resizeMode="contain"
|
||||||
onError={() => {
|
onError={() => {
|
||||||
logger.warn(`[FloatingHeader] Logo failed to load: ${metadata.logo}`);
|
logger.warn(`[FloatingHeader] Logo failed to load: ${stableLogoUri || metadata.logo}`);
|
||||||
setLogoLoadError(true);
|
setLogoLoadError(true);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -155,13 +157,13 @@ const FloatingHeader: React.FC<FloatingHeaderProps> = ({
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<View style={styles.headerTitleContainer}>
|
<View style={styles.headerTitleContainer}>
|
||||||
{metadata.logo && !logoLoadError ? (
|
{(stableLogoUri || metadata.logo) && !logoLoadError ? (
|
||||||
<FastImage
|
<Image
|
||||||
source={{ uri: metadata.logo }}
|
source={{ uri: stableLogoUri || metadata.logo }}
|
||||||
style={styles.floatingHeaderLogo}
|
style={styles.floatingHeaderLogo}
|
||||||
resizeMode={FastImage.resizeMode.contain}
|
resizeMode="contain"
|
||||||
onError={() => {
|
onError={() => {
|
||||||
logger.warn(`[FloatingHeader] Logo failed to load: ${metadata.logo}`);
|
logger.warn(`[FloatingHeader] Logo failed to load: ${stableLogoUri || metadata.logo}`);
|
||||||
setLogoLoadError(true);
|
setLogoLoadError(true);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ interface HeroSectionProps {
|
||||||
traktSynced?: boolean;
|
traktSynced?: boolean;
|
||||||
traktProgress?: number;
|
traktProgress?: number;
|
||||||
} | null;
|
} | null;
|
||||||
|
onStableLogoUriChange?: (logoUri: string | null) => void;
|
||||||
type: 'movie' | 'series';
|
type: 'movie' | 'series';
|
||||||
getEpisodeDetails: (episodeId: string) => { seasonNumber: string; episodeNumber: string; episodeName: string } | null;
|
getEpisodeDetails: (episodeId: string) => { seasonNumber: string; episodeNumber: string; episodeName: string } | null;
|
||||||
handleShowStreams: () => void;
|
handleShowStreams: () => void;
|
||||||
|
|
@ -777,6 +778,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
||||||
buttonsTranslateY,
|
buttonsTranslateY,
|
||||||
watchProgressOpacity,
|
watchProgressOpacity,
|
||||||
watchProgress,
|
watchProgress,
|
||||||
|
onStableLogoUriChange,
|
||||||
type,
|
type,
|
||||||
getEpisodeDetails,
|
getEpisodeDetails,
|
||||||
handleShowStreams,
|
handleShowStreams,
|
||||||
|
|
@ -966,12 +968,14 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
||||||
|
|
||||||
if (metadata?.logo && metadata.logo !== stableLogoUri) {
|
if (metadata?.logo && metadata.logo !== stableLogoUri) {
|
||||||
setStableLogoUri(metadata.logo);
|
setStableLogoUri(metadata.logo);
|
||||||
|
onStableLogoUriChange?.(metadata.logo);
|
||||||
setLogoHasLoadedSuccessfully(false); // Reset for new logo
|
setLogoHasLoadedSuccessfully(false); // Reset for new logo
|
||||||
logoLoadOpacity.value = 0; // reset fade for new logo
|
logoLoadOpacity.value = 0; // reset fade for new logo
|
||||||
setShouldShowTextFallback(false);
|
setShouldShowTextFallback(false);
|
||||||
} else if (!metadata?.logo && stableLogoUri) {
|
} else if (!metadata?.logo && stableLogoUri) {
|
||||||
// Clear logo if metadata no longer has one
|
// Clear logo if metadata no longer has one
|
||||||
setStableLogoUri(null);
|
setStableLogoUri(null);
|
||||||
|
onStableLogoUriChange?.(null);
|
||||||
setLogoHasLoadedSuccessfully(false);
|
setLogoHasLoadedSuccessfully(false);
|
||||||
// Start a short grace period before showing text fallback
|
// Start a short grace period before showing text fallback
|
||||||
setShouldShowTextFallback(false);
|
setShouldShowTextFallback(false);
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,9 @@ const MetadataScreen: React.FC = () => {
|
||||||
const watchProgressData = useWatchProgress(id, Object.keys(groupedEpisodes).length > 0 ? 'series' : type as 'movie' | 'series', episodeId, episodes);
|
const watchProgressData = useWatchProgress(id, Object.keys(groupedEpisodes).length > 0 ? 'series' : type as 'movie' | 'series', episodeId, episodes);
|
||||||
const assetData = useMetadataAssets(metadata, id, type, imdbId, settings, setMetadata);
|
const assetData = useMetadataAssets(metadata, id, type, imdbId, settings, setMetadata);
|
||||||
const animations = useMetadataAnimations(safeAreaTop, watchProgressData.watchProgress);
|
const animations = useMetadataAnimations(safeAreaTop, watchProgressData.watchProgress);
|
||||||
|
|
||||||
|
// Stable logo URI from HeroSection
|
||||||
|
const [stableLogoUri, setStableLogoUri] = React.useState<string | null>(null);
|
||||||
|
|
||||||
// Extract dominant color from hero image for dynamic background
|
// Extract dominant color from hero image for dynamic background
|
||||||
const heroImageUri = useMemo(() => {
|
const heroImageUri = useMemo(() => {
|
||||||
|
|
@ -870,7 +873,7 @@ const MetadataScreen: React.FC = () => {
|
||||||
{metadata && (
|
{metadata && (
|
||||||
<>
|
<>
|
||||||
{/* Floating Header - Optimized */}
|
{/* Floating Header - Optimized */}
|
||||||
<FloatingHeader
|
<FloatingHeader
|
||||||
metadata={metadata}
|
metadata={metadata}
|
||||||
logoLoadError={assetData.logoLoadError}
|
logoLoadError={assetData.logoLoadError}
|
||||||
handleBack={handleBack}
|
handleBack={handleBack}
|
||||||
|
|
@ -881,6 +884,7 @@ const MetadataScreen: React.FC = () => {
|
||||||
headerElementsOpacity={animations.headerElementsOpacity}
|
headerElementsOpacity={animations.headerElementsOpacity}
|
||||||
safeAreaTop={safeAreaTop}
|
safeAreaTop={safeAreaTop}
|
||||||
setLogoLoadError={assetData.setLogoLoadError}
|
setLogoLoadError={assetData.setLogoLoadError}
|
||||||
|
stableLogoUri={stableLogoUri}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Animated.ScrollView
|
<Animated.ScrollView
|
||||||
|
|
@ -908,6 +912,7 @@ const MetadataScreen: React.FC = () => {
|
||||||
watchProgressOpacity={animations.watchProgressOpacity}
|
watchProgressOpacity={animations.watchProgressOpacity}
|
||||||
watchProgressWidth={animations.watchProgressWidth}
|
watchProgressWidth={animations.watchProgressWidth}
|
||||||
watchProgress={watchProgressData.watchProgress}
|
watchProgress={watchProgressData.watchProgress}
|
||||||
|
onStableLogoUriChange={setStableLogoUri}
|
||||||
type={Object.keys(groupedEpisodes).length > 0 ? 'series' : type as 'movie' | 'series'}
|
type={Object.keys(groupedEpisodes).length > 0 ? 'series' : type as 'movie' | 'series'}
|
||||||
getEpisodeDetails={watchProgressData.getEpisodeDetails}
|
getEpisodeDetails={watchProgressData.getEpisodeDetails}
|
||||||
handleShowStreams={handleShowStreams}
|
handleShowStreams={handleShowStreams}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue