Persist mute state across video scrolling

This commit is contained in:
Khoa.vo 2025-12-19 19:16:54 +07:00
parent 2d622c259f
commit 929df62342
2 changed files with 30 additions and 8 deletions

View file

@ -73,6 +73,9 @@ export const Feed: React.FC = () => {
const [searchResults, setSearchResults] = useState<Video[]>([]);
const [isSearching, setIsSearching] = useState(false);
// Global mute state - persists across video scrolling
const [isMuted, setIsMuted] = useState(true);
// ========== SWIPE LOGIC ==========
const touchStart = useRef<number | null>(null);
const touchEnd = useRef<number | null>(null);
@ -655,8 +658,8 @@ export const Feed: React.FC = () => {
onClick={handleJsonLogin}
disabled={!jsonInput.trim()}
className={`w-full py-4 text-white font-semibold rounded-2xl transition-all transform active:scale-[0.98] shadow-lg text-base ${jsonInput.trim()
? 'bg-gradient-to-r from-cyan-500 to-pink-500 hover:from-cyan-400 hover:to-pink-400 shadow-pink-500/20'
: 'bg-gray-700 cursor-not-allowed'
? 'bg-gradient-to-r from-cyan-500 to-pink-500 hover:from-cyan-400 hover:to-pink-400 shadow-pink-500/20'
: 'bg-gray-700 cursor-not-allowed'
}`}
>
Connect to TikTok
@ -826,6 +829,8 @@ export const Feed: React.FC = () => {
isFollowing={following.includes(video.author)}
onFollow={handleFollow}
onAuthorClick={(author) => searchByUsername(author)}
isMuted={isMuted}
onMuteToggle={() => setIsMuted(prev => !prev)}
/>
) : (
/* Lightweight Placeholder */

View file

@ -15,6 +15,8 @@ interface VideoPlayerProps {
isFollowing?: boolean;
onFollow?: (author: string) => void;
onAuthorClick?: (author: string) => void; // In-app navigation to creator
isMuted?: boolean; // Global mute state from parent
onMuteToggle?: () => void; // Callback to toggle parent mute state
}
export const VideoPlayer: React.FC<VideoPlayerProps> = ({
@ -22,7 +24,9 @@ export const VideoPlayer: React.FC<VideoPlayerProps> = ({
isActive,
isFollowing = false,
onFollow,
onAuthorClick
onAuthorClick,
isMuted: externalMuted,
onMuteToggle
}) => {
const videoRef = useRef<HTMLVideoElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
@ -34,7 +38,9 @@ export const VideoPlayer: React.FC<VideoPlayerProps> = ({
const [duration, setDuration] = useState(0);
const [isSeeking, setIsSeeking] = useState(false);
const [useFallback, setUseFallback] = useState(false); // Fallback to full proxy
const [isMuted, setIsMuted] = useState(true); // Start muted for autoplay policy
// Use external mute state if provided, otherwise use local state for backward compatibility
const [localMuted, setLocalMuted] = useState(true);
const isMuted = externalMuted !== undefined ? externalMuted : localMuted;
const [hearts, setHearts] = useState<HeartParticle[]>([]);
const lastTapRef = useRef<number>(0);
@ -52,7 +58,7 @@ export const VideoPlayer: React.FC<VideoPlayerProps> = ({
// Auto-play when becoming active
if (videoRef.current.paused) {
videoRef.current.currentTime = 0;
videoRef.current.muted = true; // Always start muted for autoplay policy
videoRef.current.muted = isMuted; // Use current mute state
videoRef.current.play().catch((err) => {
// If autoplay fails even muted, show paused state
console.log('Autoplay blocked:', err.message);
@ -65,6 +71,13 @@ export const VideoPlayer: React.FC<VideoPlayerProps> = ({
}
}, [isActive]); // Only trigger on isActive change
// Sync video muted property when isMuted state changes
useEffect(() => {
if (videoRef.current) {
videoRef.current.muted = isMuted;
}
}, [isMuted]);
// Spacebar to pause/play when this video is active
useEffect(() => {
if (!isActive) return;
@ -148,9 +161,13 @@ export const VideoPlayer: React.FC<VideoPlayerProps> = ({
const toggleMute = (e: React.MouseEvent | React.TouchEvent) => {
e.stopPropagation(); // Prevent video tap
if (!videoRef.current) return;
const newMuted = !videoRef.current.muted;
videoRef.current.muted = newMuted;
setIsMuted(newMuted);
// Use external toggle if provided, otherwise use local state
if (onMuteToggle) {
onMuteToggle();
} else {
setLocalMuted(prev => !prev);
}
};
// Handle tap - double tap shows heart, single tap toggles play