mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-02-10 22:32:22 +00:00
Fix: Improves Chromecast casting experience
Fixes several issues and improves the overall Chromecast casting experience: - Implements an AbortController for fetching item data to prevent race conditions. - Syncs live progress in the mini player more accurately using elapsed real time. - Prevents event propagation in the mini player's play/pause button. - Ensures the disconnect callback in the connection menu is always called. - Retries scrolling in the episode list on failure. - Handles unmute failures gracefully in volume controls. - Clamps seek positions to prevent exceeding duration. - Fixes reporting playback start multiple times - Improves segment calculation in `useChromecastSegments` - Prevents race condition with `isPlaying` state in `Controls` component Also includes minor UI and timing adjustments for a smoother user experience.
This commit is contained in:
@@ -63,27 +63,41 @@ export const CastingMiniPlayer: React.FC = () => {
|
||||
mediaStatus?.streamPosition || 0,
|
||||
);
|
||||
|
||||
// Track baseline for elapsed-time computation
|
||||
const baselinePositionRef = useRef(mediaStatus?.streamPosition || 0);
|
||||
const baselineTimestampRef = useRef(Date.now());
|
||||
|
||||
// Sync live progress with mediaStatus and poll every second when playing
|
||||
useEffect(() => {
|
||||
if (mediaStatus?.streamPosition) {
|
||||
// Resync baseline whenever mediaStatus reports a new position
|
||||
if (mediaStatus?.streamPosition !== undefined) {
|
||||
baselinePositionRef.current = mediaStatus.streamPosition;
|
||||
baselineTimestampRef.current = Date.now();
|
||||
setLiveProgress(mediaStatus.streamPosition);
|
||||
}
|
||||
|
||||
// Update every second when playing
|
||||
// Update based on elapsed real time when playing
|
||||
const interval = setInterval(() => {
|
||||
if (
|
||||
mediaStatus?.playerState === MediaPlayerState.PLAYING &&
|
||||
mediaStatus?.streamPosition !== undefined
|
||||
) {
|
||||
setLiveProgress((prev) => prev + 1);
|
||||
if (mediaStatus?.playerState === MediaPlayerState.PLAYING) {
|
||||
const elapsed =
|
||||
((Date.now() - baselineTimestampRef.current) *
|
||||
(mediaStatus.playbackRate || 1)) /
|
||||
1000;
|
||||
setLiveProgress(baselinePositionRef.current + elapsed);
|
||||
} else if (mediaStatus?.streamPosition !== undefined) {
|
||||
// Sync with actual position when paused/buffering
|
||||
baselinePositionRef.current = mediaStatus.streamPosition;
|
||||
baselineTimestampRef.current = Date.now();
|
||||
setLiveProgress(mediaStatus.streamPosition);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [mediaStatus?.playerState, mediaStatus?.streamPosition]);
|
||||
}, [
|
||||
mediaStatus?.playerState,
|
||||
mediaStatus?.streamPosition,
|
||||
mediaStatus?.playbackRate,
|
||||
]);
|
||||
|
||||
const progress = liveProgress * 1000; // Convert to ms
|
||||
const duration = (mediaStatus?.mediaInfo?.streamDuration || 0) * 1000;
|
||||
@@ -425,7 +439,13 @@ export const CastingMiniPlayer: React.FC = () => {
|
||||
</View>
|
||||
|
||||
{/* Play/Pause button */}
|
||||
<Pressable onPress={handleTogglePlayPause} style={{ padding: 8 }}>
|
||||
<Pressable
|
||||
onPress={(e) => {
|
||||
e.stopPropagation();
|
||||
handleTogglePlayPause();
|
||||
}}
|
||||
style={{ padding: 8 }}
|
||||
>
|
||||
<Ionicons
|
||||
name={isPlaying ? "pause" : "play"}
|
||||
size={28}
|
||||
|
||||
Reference in New Issue
Block a user