From aa2783ae2ed67ea5be9140fb9a30b5e391a1e916 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Fri, 14 Feb 2025 17:21:31 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=B8(frontend)=20auto-hide=20participan?= =?UTF-8?q?t=20controls=20after=203s=20of=20inactivity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Auto-hides participant tile controls after 3 seconds of cursor inactivity to reduce visual clutter. Controls reappear on cursor movement. --- .../components/ParticipantTileFocus.tsx | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/features/rooms/livekit/components/ParticipantTileFocus.tsx b/src/frontend/src/features/rooms/livekit/components/ParticipantTileFocus.tsx index 9132e5a9..f38f6df5 100644 --- a/src/frontend/src/features/rooms/livekit/components/ParticipantTileFocus.tsx +++ b/src/frontend/src/features/rooms/livekit/components/ParticipantTileFocus.tsx @@ -15,7 +15,7 @@ import { } from '@livekit/components-react' import { useTranslation } from 'react-i18next' import { TrackReferenceOrPlaceholder } from '@livekit/components-core' -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { useSidePanel } from '../hooks/useSidePanel' import { useFullScreen } from '../hooks/useFullScreen' import { Participant, Track } from 'livekit-client' @@ -126,6 +126,8 @@ const MuteButton = ({ participant }: { participant: Participant }) => { ) } +const MOUSE_IDLE_TIME = 3000 + export const ParticipantTileFocus = ({ trackRef, }: { @@ -134,8 +136,11 @@ export const ParticipantTileFocus = ({ const [hovered, setHovered] = useState(false) const [opacity, setOpacity] = useState(0) + const idleTimerRef = useRef(null) + const [isIdleRef, setIsIdleRef] = useState(false) + useEffect(() => { - if (hovered) { + if (hovered && !isIdleRef) { // Wait for next frame to ensure element is mounted requestAnimationFrame(() => { setOpacity(0.6) @@ -143,7 +148,17 @@ export const ParticipantTileFocus = ({ } else { setOpacity(0) } - }, [hovered]) + }, [hovered, isIdleRef]) + + const handleMouseMove = () => { + if (idleTimerRef.current) { + window.clearTimeout(idleTimerRef.current) + } + idleTimerRef.current = window.setTimeout(() => { + setIsIdleRef(true) + }, MOUSE_IDLE_TIME) + setIsIdleRef(false) + } const participant = trackRef.participant @@ -164,6 +179,7 @@ export const ParticipantTileFocus = ({ })} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)} + onMouseMove={handleMouseMove} > {hovered && (