mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-03 16:59:08 +00:00
Changed to TraktService.getInstance().isAuthenticated()
This commit is contained in:
parent
d2987ce0cc
commit
9375fab06c
3 changed files with 61 additions and 40 deletions
|
|
@ -340,7 +340,10 @@ const KSPlayerCore: React.FC = () => {
|
||||||
const resumeTarget = routeInitialPosition || watchProgress.initialPosition || watchProgress.initialSeekTargetRef?.current;
|
const resumeTarget = routeInitialPosition || watchProgress.initialPosition || watchProgress.initialSeekTargetRef?.current;
|
||||||
if (resumeTarget && resumeTarget > 0 && !watchProgress.showResumeOverlay && data.duration > 0) {
|
if (resumeTarget && resumeTarget > 0 && !watchProgress.showResumeOverlay && data.duration > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
controls.seekToTime(resumeTarget);
|
if (ksPlayerRef.current) {
|
||||||
|
logger.debug(`[KSPlayerCore] Auto-resuming to ${resumeTarget}`);
|
||||||
|
ksPlayerRef.current.seek(resumeTarget);
|
||||||
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -373,15 +376,17 @@ const KSPlayerCore: React.FC = () => {
|
||||||
modals.setShowErrorModal(true);
|
modals.setShowErrorModal(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClose = async () => {
|
const handleClose = useCallback(() => {
|
||||||
if (isSyncingBeforeClose.current) return;
|
if (isSyncingBeforeClose.current) return;
|
||||||
isSyncingBeforeClose.current = true;
|
isSyncingBeforeClose.current = true;
|
||||||
|
|
||||||
await traktAutosync.handleProgressUpdate(currentTime, duration, true);
|
// Fire and forget - don't block navigation on async operations
|
||||||
await traktAutosync.handlePlaybackEnd(currentTime, duration, 'user_close');
|
// The useWatchProgress and useTraktAutosync hooks handle cleanup on unmount
|
||||||
|
traktAutosync.handleProgressUpdate(currentTime, duration, true);
|
||||||
|
traktAutosync.handlePlaybackEnd(currentTime, duration, 'user_close');
|
||||||
|
|
||||||
navigation.goBack();
|
navigation.goBack();
|
||||||
};
|
}, [navigation, currentTime, duration, traktAutosync]);
|
||||||
|
|
||||||
// Stream selection handler
|
// Stream selection handler
|
||||||
const handleSelectStream = async (newStream: any) => {
|
const handleSelectStream = async (newStream: any) => {
|
||||||
|
|
|
||||||
|
|
@ -102,13 +102,17 @@ export const useWatchProgress = (
|
||||||
}
|
}
|
||||||
}, [id, type, paused, currentTime, duration]);
|
}, [id, type, paused, currentTime, duration]);
|
||||||
|
|
||||||
// Unmount Save
|
// Unmount Save - deferred to allow navigation to complete first
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
if (id && type && durationRef.current > 0) {
|
// Use setTimeout(0) to defer save operations to next event loop tick
|
||||||
saveWatchProgress();
|
// This allows navigation animations to complete smoothly
|
||||||
traktAutosync.handlePlaybackEnd(currentTimeRef.current, durationRef.current, 'unmount');
|
setTimeout(() => {
|
||||||
}
|
if (id && type && durationRef.current > 0) {
|
||||||
|
saveWatchProgress();
|
||||||
|
traktAutosync.handlePlaybackEnd(currentTimeRef.current, durationRef.current, 'unmount');
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
};
|
};
|
||||||
}, [id, type]);
|
}, [id, type]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,12 +55,24 @@ export const EpisodesModal: React.FC<EpisodesModalProps> = ({
|
||||||
if (showEpisodesModal && metadata?.id) {
|
if (showEpisodesModal && metadata?.id) {
|
||||||
setIsLoadingProgress(true);
|
setIsLoadingProgress(true);
|
||||||
try {
|
try {
|
||||||
const progress = await storageService.getShowProgress(metadata.id);
|
// Get all watch progress and filter for this show's episodes
|
||||||
setEpisodeProgress(progress || {});
|
const allProgress = await storageService.getAllWatchProgress();
|
||||||
|
const showPrefix = `series:${metadata.id}:`;
|
||||||
|
const progress: { [key: string]: any } = {};
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(allProgress)) {
|
||||||
|
if (key.startsWith(showPrefix)) {
|
||||||
|
// Extract episode id from key (format: series:showId:episodeId)
|
||||||
|
const episodeId = key.replace(showPrefix, '');
|
||||||
|
progress[episodeId] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setEpisodeProgress(progress);
|
||||||
|
|
||||||
// Trakt sync logic preserved
|
// Trakt sync logic preserved
|
||||||
if (await TraktService.isAuthenticated()) {
|
if (await TraktService.getInstance().isAuthenticated()) {
|
||||||
// Optional: background sync logic
|
// Optional: background sync logic
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Failed to fetch episode progress', err);
|
logger.error('Failed to fetch episode progress', err);
|
||||||
|
|
@ -84,7 +96,7 @@ export const EpisodesModal: React.FC<EpisodesModalProps> = ({
|
||||||
const currentSeasonEpisodes = groupedEpisodes[selectedSeason] || [];
|
const currentSeasonEpisodes = groupedEpisodes[selectedSeason] || [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={StyleSheet.absoluteFill} zIndex={9999}>
|
<View style={[StyleSheet.absoluteFill, { zIndex: 9999 }]}>
|
||||||
<TouchableOpacity style={StyleSheet.absoluteFill} activeOpacity={1} onPress={() => setShowEpisodesModal(false)}>
|
<TouchableOpacity style={StyleSheet.absoluteFill} activeOpacity={1} onPress={() => setShowEpisodesModal(false)}>
|
||||||
<Animated.View entering={FadeIn.duration(200)} exiting={FadeOut.duration(150)} style={{ flex: 1, backgroundColor: 'rgba(0,0,0,0.5)' }} />
|
<Animated.View entering={FadeIn.duration(200)} exiting={FadeOut.duration(150)} style={{ flex: 1, backgroundColor: 'rgba(0,0,0,0.5)' }} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
@ -110,31 +122,31 @@ export const EpisodesModal: React.FC<EpisodesModalProps> = ({
|
||||||
|
|
||||||
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ paddingBottom: 15, gap: 8 }}>
|
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ paddingBottom: 15, gap: 8 }}>
|
||||||
{[...seasons]
|
{[...seasons]
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
if (a === 0) return 1;
|
if (a === 0) return 1;
|
||||||
if (b === 0) return -1;
|
if (b === 0) return -1;
|
||||||
return a - b;
|
return a - b;
|
||||||
}).map((season) => (
|
}).map((season) => (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
key={season}
|
key={season}
|
||||||
onPress={() => setSelectedSeason(season)}
|
onPress={() => setSelectedSeason(season)}
|
||||||
style={{
|
style={{
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
paddingVertical: 8,
|
paddingVertical: 8,
|
||||||
borderRadius: 20,
|
borderRadius: 20,
|
||||||
backgroundColor: selectedSeason === season ? 'white' : 'rgba(255,255,255,0.06)',
|
backgroundColor: selectedSeason === season ? 'white' : 'rgba(255,255,255,0.06)',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderColor: selectedSeason === season ? 'white' : 'rgba(255,255,255,0.1)',
|
borderColor: selectedSeason === season ? 'white' : 'rgba(255,255,255,0.1)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text style={{
|
<Text style={{
|
||||||
color: selectedSeason === season ? 'black' : 'white',
|
color: selectedSeason === season ? 'black' : 'white',
|
||||||
fontWeight: selectedSeason === season ? '700' : '500'
|
fontWeight: selectedSeason === season ? '700' : '500'
|
||||||
}}>
|
}}>
|
||||||
{season === 0 ? 'Specials' : `Season ${season}`}
|
{season === 0 ? 'Specials' : `Season ${season}`}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
))}
|
))}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue