mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-21 00:32:04 +00:00
small bug fixes
This commit is contained in:
parent
9b1368e7c6
commit
46cdf95cd4
5 changed files with 75 additions and 6 deletions
5
App.tsx
5
App.tsx
|
|
@ -25,6 +25,7 @@ import { CatalogProvider } from './src/contexts/CatalogContext';
|
||||||
import { GenreProvider } from './src/contexts/GenreContext';
|
import { GenreProvider } from './src/contexts/GenreContext';
|
||||||
import { TraktProvider } from './src/contexts/TraktContext';
|
import { TraktProvider } from './src/contexts/TraktContext';
|
||||||
import { ThemeProvider, useTheme } from './src/contexts/ThemeContext';
|
import { ThemeProvider, useTheme } from './src/contexts/ThemeContext';
|
||||||
|
import { TrailerProvider } from './src/contexts/TrailerContext';
|
||||||
import SplashScreen from './src/components/SplashScreen';
|
import SplashScreen from './src/components/SplashScreen';
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
import * as Sentry from '@sentry/react-native';
|
import * as Sentry from '@sentry/react-native';
|
||||||
|
|
@ -129,7 +130,9 @@ function App(): React.JSX.Element {
|
||||||
<CatalogProvider>
|
<CatalogProvider>
|
||||||
<TraktProvider>
|
<TraktProvider>
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<ThemedApp />
|
<TrailerProvider>
|
||||||
|
<ThemedApp />
|
||||||
|
</TrailerProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</TraktProvider>
|
</TraktProvider>
|
||||||
</CatalogProvider>
|
</CatalogProvider>
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import Animated, {
|
||||||
import { useTheme } from '../../contexts/ThemeContext';
|
import { useTheme } from '../../contexts/ThemeContext';
|
||||||
import { useTraktContext } from '../../contexts/TraktContext';
|
import { useTraktContext } from '../../contexts/TraktContext';
|
||||||
import { useSettings } from '../../hooks/useSettings';
|
import { useSettings } from '../../hooks/useSettings';
|
||||||
|
import { useTrailer } from '../../contexts/TrailerContext';
|
||||||
import { logger } from '../../utils/logger';
|
import { logger } from '../../utils/logger';
|
||||||
import { TMDBService } from '../../services/tmdbService';
|
import { TMDBService } from '../../services/tmdbService';
|
||||||
import TrailerService from '../../services/trailerService';
|
import TrailerService from '../../services/trailerService';
|
||||||
|
|
@ -697,6 +698,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
||||||
const { currentTheme } = useTheme();
|
const { currentTheme } = useTheme();
|
||||||
const { isAuthenticated: isTraktAuthenticated } = useTraktContext();
|
const { isAuthenticated: isTraktAuthenticated } = useTraktContext();
|
||||||
const { settings, updateSetting } = useSettings();
|
const { settings, updateSetting } = useSettings();
|
||||||
|
const { isTrailerPlaying: globalTrailerPlaying, setTrailerPlaying } = useTrailer();
|
||||||
|
|
||||||
// Performance optimization: Refs for avoiding re-renders
|
// Performance optimization: Refs for avoiding re-renders
|
||||||
const interactionComplete = useRef(false);
|
const interactionComplete = useRef(false);
|
||||||
|
|
@ -710,7 +712,6 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
||||||
const [trailerError, setTrailerError] = useState(false);
|
const [trailerError, setTrailerError] = useState(false);
|
||||||
// Use persistent setting instead of local state
|
// Use persistent setting instead of local state
|
||||||
const trailerMuted = settings.trailerMuted;
|
const trailerMuted = settings.trailerMuted;
|
||||||
const [isTrailerPlaying, setIsTrailerPlaying] = useState(false);
|
|
||||||
const [trailerReady, setTrailerReady] = useState(false);
|
const [trailerReady, setTrailerReady] = useState(false);
|
||||||
const [trailerPreloaded, setTrailerPreloaded] = useState(false);
|
const [trailerPreloaded, setTrailerPreloaded] = useState(false);
|
||||||
const trailerVideoRef = useRef<any>(null);
|
const trailerVideoRef = useRef<any>(null);
|
||||||
|
|
@ -745,7 +746,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
||||||
setTrailerPreloaded(true);
|
setTrailerPreloaded(true);
|
||||||
}
|
}
|
||||||
setTrailerReady(true);
|
setTrailerReady(true);
|
||||||
setIsTrailerPlaying(true);
|
setTrailerPlaying(true);
|
||||||
|
|
||||||
// Smooth transition: fade out thumbnail, fade in trailer
|
// Smooth transition: fade out thumbnail, fade in trailer
|
||||||
thumbnailOpacity.value = withTiming(0, { duration: 500 });
|
thumbnailOpacity.value = withTiming(0, { duration: 500 });
|
||||||
|
|
@ -768,7 +769,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
||||||
const handleTrailerError = useCallback(() => {
|
const handleTrailerError = useCallback(() => {
|
||||||
setTrailerError(true);
|
setTrailerError(true);
|
||||||
setTrailerReady(false);
|
setTrailerReady(false);
|
||||||
setIsTrailerPlaying(false);
|
setTrailerPlaying(false);
|
||||||
|
|
||||||
// Fade back to thumbnail
|
// Fade back to thumbnail
|
||||||
trailerOpacity.value = withTiming(0, { duration: 300 });
|
trailerOpacity.value = withTiming(0, { duration: 300 });
|
||||||
|
|
@ -1068,7 +1069,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
||||||
<TrailerPlayer
|
<TrailerPlayer
|
||||||
ref={trailerVideoRef}
|
ref={trailerVideoRef}
|
||||||
trailerUrl={trailerUrl}
|
trailerUrl={trailerUrl}
|
||||||
autoPlay={true}
|
autoPlay={globalTrailerPlaying}
|
||||||
muted={trailerMuted}
|
muted={trailerMuted}
|
||||||
style={styles.absoluteFill}
|
style={styles.absoluteFill}
|
||||||
hideLoadingSpinner={true}
|
hideLoadingSpinner={true}
|
||||||
|
|
@ -1215,7 +1216,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
|
||||||
getEpisodeDetails={getEpisodeDetails}
|
getEpisodeDetails={getEpisodeDetails}
|
||||||
animatedStyle={watchProgressAnimatedStyle}
|
animatedStyle={watchProgressAnimatedStyle}
|
||||||
isWatched={isWatched}
|
isWatched={isWatched}
|
||||||
isTrailerPlaying={isTrailerPlaying}
|
isTrailerPlaying={globalTrailerPlaying}
|
||||||
trailerMuted={trailerMuted}
|
trailerMuted={trailerMuted}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,11 @@ const TrailerPlayer = React.forwardRef<any, TrailerPlayerProps>(({
|
||||||
setIsMuted(muted);
|
setIsMuted(muted);
|
||||||
}, [muted]);
|
}, [muted]);
|
||||||
|
|
||||||
|
// Sync internal playing state with autoPlay prop
|
||||||
|
useEffect(() => {
|
||||||
|
setIsPlaying(autoPlay);
|
||||||
|
}, [autoPlay]);
|
||||||
|
|
||||||
// Cleanup timeout on unmount
|
// Cleanup timeout on unmount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
|
|
|
||||||
47
src/contexts/TrailerContext.tsx
Normal file
47
src/contexts/TrailerContext.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import React, { createContext, useContext, useState, useCallback, useMemo, ReactNode } from 'react';
|
||||||
|
|
||||||
|
interface TrailerContextValue {
|
||||||
|
isTrailerPlaying: boolean;
|
||||||
|
pauseTrailer: () => void;
|
||||||
|
resumeTrailer: () => void;
|
||||||
|
setTrailerPlaying: (playing: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TrailerContext = createContext<TrailerContextValue | undefined>(undefined);
|
||||||
|
|
||||||
|
export const TrailerProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
|
||||||
|
const [isTrailerPlaying, setIsTrailerPlaying] = useState(true);
|
||||||
|
|
||||||
|
const pauseTrailer = useCallback(() => {
|
||||||
|
setIsTrailerPlaying(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const resumeTrailer = useCallback(() => {
|
||||||
|
setIsTrailerPlaying(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const setTrailerPlaying = useCallback((playing: boolean) => {
|
||||||
|
setIsTrailerPlaying(playing);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const value: TrailerContextValue = useMemo(() => ({
|
||||||
|
isTrailerPlaying,
|
||||||
|
pauseTrailer,
|
||||||
|
resumeTrailer,
|
||||||
|
setTrailerPlaying,
|
||||||
|
}), [isTrailerPlaying, pauseTrailer, resumeTrailer, setTrailerPlaying]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TrailerContext.Provider value={value}>
|
||||||
|
{children}
|
||||||
|
</TrailerContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useTrailer = (): TrailerContextValue => {
|
||||||
|
const context = useContext(TrailerContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useTrailer must be used within a TrailerProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
@ -30,6 +30,7 @@ import { RootStackParamList, RootStackNavigationProp } from '../navigation/AppNa
|
||||||
import { useMetadata } from '../hooks/useMetadata';
|
import { useMetadata } from '../hooks/useMetadata';
|
||||||
import { useMetadataAssets } from '../hooks/useMetadataAssets';
|
import { useMetadataAssets } from '../hooks/useMetadataAssets';
|
||||||
import { useTheme } from '../contexts/ThemeContext';
|
import { useTheme } from '../contexts/ThemeContext';
|
||||||
|
import { useTrailer } from '../contexts/TrailerContext';
|
||||||
import { Stream } from '../types/metadata';
|
import { Stream } from '../types/metadata';
|
||||||
import { tmdbService } from '../services/tmdbService';
|
import { tmdbService } from '../services/tmdbService';
|
||||||
import { stremioService } from '../services/stremioService';
|
import { stremioService } from '../services/stremioService';
|
||||||
|
|
@ -360,6 +361,7 @@ export const StreamsScreen = () => {
|
||||||
const { settings } = useSettings();
|
const { settings } = useSettings();
|
||||||
const { currentTheme } = useTheme();
|
const { currentTheme } = useTheme();
|
||||||
const { colors } = currentTheme;
|
const { colors } = currentTheme;
|
||||||
|
const { pauseTrailer, resumeTrailer } = useTrailer();
|
||||||
|
|
||||||
// Add ref to prevent excessive updates
|
// Add ref to prevent excessive updates
|
||||||
const isMounted = useRef(true);
|
const isMounted = useRef(true);
|
||||||
|
|
@ -383,6 +385,17 @@ export const StreamsScreen = () => {
|
||||||
console.log('[StreamsScreen] Received thumbnail from params:', episodeThumbnail);
|
console.log('[StreamsScreen] Received thumbnail from params:', episodeThumbnail);
|
||||||
}, [episodeThumbnail]);
|
}, [episodeThumbnail]);
|
||||||
|
|
||||||
|
// Pause trailer when StreamsScreen is opened
|
||||||
|
useEffect(() => {
|
||||||
|
// Pause trailer when component mounts
|
||||||
|
pauseTrailer();
|
||||||
|
|
||||||
|
// Resume trailer when component unmounts
|
||||||
|
return () => {
|
||||||
|
resumeTrailer();
|
||||||
|
};
|
||||||
|
}, [pauseTrailer, resumeTrailer]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
metadata,
|
metadata,
|
||||||
episodes,
|
episodes,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue