mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-16 17:23:43 +08:00
feat: Improve video playback state syncing for AirPlay and add unoptimized and referrerPolicy to image components.
This commit is contained in:
@@ -45,6 +45,8 @@ export const MovieCard = memo(function MovieCard({ movie, onMovieClick }: MovieC
|
||||
className="object-cover transition-transform duration-300 group-hover:scale-105 rounded-[var(--radius-2xl)]"
|
||||
sizes="(max-width: 640px) 50vw, (max-width: 768px) 33vw, (max-width: 1024px) 25vw, 20vw"
|
||||
loading="lazy"
|
||||
unoptimized
|
||||
referrerPolicy="no-referrer"
|
||||
onError={(e) => {
|
||||
const target = e.currentTarget as HTMLImageElement;
|
||||
target.style.display = 'none';
|
||||
|
||||
@@ -73,6 +73,7 @@ export function DesktopVideoPlayer({
|
||||
className="w-full h-full object-contain"
|
||||
src={src}
|
||||
poster={poster}
|
||||
x-webkit-airplay="allow"
|
||||
onPlay={handlePlay}
|
||||
onPause={handlePause}
|
||||
onTimeUpdate={handleTimeUpdateEvent}
|
||||
|
||||
@@ -123,7 +123,8 @@ export function usePlaybackControls({
|
||||
videoRef,
|
||||
isDraggingProgressRef,
|
||||
setCurrentTime,
|
||||
setDuration
|
||||
setDuration,
|
||||
setIsPlaying
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -135,7 +135,8 @@ export function useMobilePlaybackControls({
|
||||
videoRef,
|
||||
isDraggingProgressRef,
|
||||
setCurrentTime,
|
||||
setDuration
|
||||
setDuration,
|
||||
setIsPlaying
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -6,6 +6,7 @@ interface UsePlaybackPollingProps {
|
||||
isDraggingProgressRef: React.MutableRefObject<boolean>;
|
||||
setCurrentTime: (time: number) => void;
|
||||
setDuration: (duration: number) => void;
|
||||
setIsPlaying: (playing: boolean) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -17,24 +18,34 @@ export function usePlaybackPolling({
|
||||
videoRef,
|
||||
isDraggingProgressRef,
|
||||
setCurrentTime,
|
||||
setDuration
|
||||
setDuration,
|
||||
setIsPlaying
|
||||
}: UsePlaybackPollingProps) {
|
||||
useEffect(() => {
|
||||
if (!isPlaying || !videoRef.current) return;
|
||||
if (!videoRef.current) return;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
if (videoRef.current && !isDraggingProgressRef.current) {
|
||||
const current = videoRef.current.currentTime;
|
||||
const total = videoRef.current.duration;
|
||||
if (videoRef.current) {
|
||||
// Sync play/pause state (crucial for AirPlay where events might be missed)
|
||||
const isVideoPaused = videoRef.current.paused;
|
||||
if (isVideoPaused === isPlaying && !isDraggingProgressRef.current) {
|
||||
// State mismatch detected (e.g. AirPlay paused but app thinks playing)
|
||||
setIsPlaying(!isVideoPaused);
|
||||
}
|
||||
|
||||
// Only update if significantly different to avoid jitter
|
||||
setCurrentTime(current);
|
||||
if (!isNaN(total) && total > 0) {
|
||||
setDuration(total);
|
||||
if (!isDraggingProgressRef.current && !isVideoPaused) {
|
||||
const current = videoRef.current.currentTime;
|
||||
const total = videoRef.current.duration;
|
||||
|
||||
// Only update if significantly different to avoid jitter
|
||||
setCurrentTime(current);
|
||||
if (!isNaN(total) && total > 0) {
|
||||
setDuration(total);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 500); // Poll every 500ms
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [isPlaying, videoRef, isDraggingProgressRef, setCurrentTime, setDuration]);
|
||||
}, [isPlaying, videoRef, isDraggingProgressRef, setCurrentTime, setDuration, setIsPlaying]);
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ export const VideoCard = memo<VideoCardProps>(({
|
||||
className="object-cover rounded-[var(--radius-2xl)]"
|
||||
sizes="(max-width: 640px) 33vw, (max-width: 1024px) 20vw, 16vw"
|
||||
loading="lazy"
|
||||
unoptimized
|
||||
referrerPolicy="no-referrer"
|
||||
onError={(e) => {
|
||||
const target = e.currentTarget as HTMLImageElement;
|
||||
target.style.opacity = '0';
|
||||
|
||||
Reference in New Issue
Block a user