From 8c596f8326e1683986d76dd5784498b0c9062fc9 Mon Sep 17 00:00:00 2001 From: sebastjanartic <45803536-sebastjanartic@users.noreply.replit.com> Date: Tue, 2 Sep 2025 15:44:25 +0000 Subject: [PATCH] Improve video preview audio muting consistency across the platform Refactor video card component to synchronize mute state across all video previews using localStorage and custom events, ensuring consistent audio behavior. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 2cd2c0bc-434c-4bc9-ad3f-b99d3897a0d1 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/2cd2c0bc-434c-4bc9-ad3f-b99d3897a0d1/4DOsXkx --- client/src/components/video-card.tsx | 39 ++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/client/src/components/video-card.tsx b/client/src/components/video-card.tsx index a28f437..418b7e1 100644 --- a/client/src/components/video-card.tsx +++ b/client/src/components/video-card.tsx @@ -46,16 +46,40 @@ function formatDate(date: Date | string): string { export default function VideoCard({ video, onClick, className = "", hideOverlay = false }: VideoCardProps) { const [isHovered, setIsHovered] = useState(false); const [showPreview, setShowPreview] = useState(false); - const [isMuted, setIsMuted] = useState(() => { - // Check localStorage for user's audio preference, default to muted - const savedMuteState = localStorage.getItem('videoPreviewMuted'); - return savedMuteState === null ? true : savedMuteState === 'true'; - }); + const [isMuted, setIsMuted] = useState(true); const hoverTimeoutRef = useRef(); const videoRef = useRef(null); const hlsRef = useRef(null); const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(0); + + // Load mute preference on component mount + useEffect(() => { + const savedMuteState = localStorage.getItem('videoPreviewMuted'); + const shouldBeMuted = savedMuteState === null ? true : savedMuteState === 'true'; + setIsMuted(shouldBeMuted); + }, []); + + // Listen for changes in localStorage from other components + useEffect(() => { + const handleStorageChange = (e: StorageEvent) => { + if (e.key === 'videoPreviewMuted' && e.newValue !== null) { + setIsMuted(e.newValue === 'true'); + } + }; + + const handleMuteChange = (e: CustomEvent) => { + setIsMuted(e.detail.isMuted); + }; + + window.addEventListener('storage', handleStorageChange); + window.addEventListener('videoMuteChanged', handleMuteChange as EventListener); + + return () => { + window.removeEventListener('storage', handleStorageChange); + window.removeEventListener('videoMuteChanged', handleMuteChange as EventListener); + }; + }, []); // Enable video preview on hover for desktop devices useEffect(() => { @@ -208,6 +232,11 @@ export default function VideoCard({ video, onClick, className = "", hideOverlay // Save preference to localStorage for all future previews localStorage.setItem('videoPreviewMuted', newMutedState.toString()); + // Dispatch custom event to notify other components + window.dispatchEvent(new CustomEvent('videoMuteChanged', { + detail: { isMuted: newMutedState } + })); + if (videoRef.current) { videoRef.current.muted = newMutedState; }