From 17f8ec63190db8aaa4fb5208968c6669b67738d8 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Fri, 31 Jan 2025 10:44:15 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=B8(frontend)=20refactor=20participant?= =?UTF-8?q?=20tile=20while=20being=20hovered?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspired by GMeet. Make central actions available on a participant tile when a user hover it. This new interactive zone will be extended with more actions and controls. --- .../livekit/components/ParticipantTile.tsx | 12 ++- .../components/ParticipantTileFocus.tsx | 97 +++++++++++++++++++ src/frontend/src/locales/de/rooms.json | 6 ++ src/frontend/src/locales/en/rooms.json | 6 ++ src/frontend/src/locales/fr/rooms.json | 6 ++ 5 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 src/frontend/src/features/rooms/livekit/components/ParticipantTileFocus.tsx diff --git a/src/frontend/src/features/rooms/livekit/components/ParticipantTile.tsx b/src/frontend/src/features/rooms/livekit/components/ParticipantTile.tsx index 076ea42f..c745c00d 100644 --- a/src/frontend/src/features/rooms/livekit/components/ParticipantTile.tsx +++ b/src/frontend/src/features/rooms/livekit/components/ParticipantTile.tsx @@ -1,7 +1,6 @@ import { AudioTrack, ConnectionQualityIndicator, - FocusToggle, LockLockedIcon, ParticipantName, ParticipantTileProps, @@ -23,11 +22,12 @@ import { TrackReferenceOrPlaceholder, } from '@livekit/components-core' import { Track } from 'livekit-client' -import { ParticipantPlaceholder } from '@/features/rooms/livekit/components/ParticipantPlaceholder' import { RiHand } from '@remixicon/react' -import { useRaisedHand } from '@/features/rooms/livekit/hooks/useRaisedHand' +import { useRaisedHand } from '../hooks/useRaisedHand' import { HStack } from '@/styled-system/jsx' -import { MutedMicIndicator } from '@/features/rooms/livekit/components/MutedMicIndicator' +import { MutedMicIndicator } from './MutedMicIndicator' +import { ParticipantPlaceholder } from './ParticipantPlaceholder' +import { ParticipantTileFocus } from './ParticipantTileFocus' export function TrackRefContextIfNeeded( props: React.PropsWithChildren<{ @@ -173,7 +173,9 @@ export const ParticipantTile: ( )} )} - {!disableMetadata && } + {!disableMetadata && ( + + )} diff --git a/src/frontend/src/features/rooms/livekit/components/ParticipantTileFocus.tsx b/src/frontend/src/features/rooms/livekit/components/ParticipantTileFocus.tsx new file mode 100644 index 00000000..babec88a --- /dev/null +++ b/src/frontend/src/features/rooms/livekit/components/ParticipantTileFocus.tsx @@ -0,0 +1,97 @@ +import { css } from '@/styled-system/css' +import { HStack } from '@/styled-system/jsx' +import { Button } from '@/primitives' +import { RiPushpin2Line, RiUnpinLine } from '@remixicon/react' +import { useFocusToggle } from '@livekit/components-react' +import { useTranslation } from 'react-i18next' +import { TrackReferenceOrPlaceholder } from '@livekit/components-core' +import { useEffect, useState } from 'react' + +const FocusButton = ({ + trackRef, +}: { + trackRef: TrackReferenceOrPlaceholder +}) => { + const { t } = useTranslation('rooms', { keyPrefix: 'participantTileFocus' }) + const { mergedProps, inFocus } = useFocusToggle({ + trackRef, + props: {}, + }) + return ( + + ) +} + +export const ParticipantTileFocus = ({ + trackRef, +}: { + trackRef: TrackReferenceOrPlaceholder +}) => { + const [hovered, setHovered] = useState(false) + const [opacity, setOpacity] = useState(0) + + useEffect(() => { + if (hovered) { + // Wait for next frame to ensure element is mounted + requestAnimationFrame(() => { + setOpacity(0.6) + }) + } else { + setOpacity(0) + } + }, [hovered]) + + return ( +
setHovered(true)} + onMouseLeave={() => setHovered(false)} + > + {hovered && ( +
+ + + +
+ )} +
+ ) +} diff --git a/src/frontend/src/locales/de/rooms.json b/src/frontend/src/locales/de/rooms.json index 5812c476..3193aed6 100644 --- a/src/frontend/src/locales/de/rooms.json +++ b/src/frontend/src/locales/de/rooms.json @@ -189,5 +189,11 @@ }, "recording": { "label": "" + }, + "participantTileFocus": { + "pin": { + "enable": "", + "disable": "" + } } } diff --git a/src/frontend/src/locales/en/rooms.json b/src/frontend/src/locales/en/rooms.json index 3e7e19ce..6aaf96b4 100644 --- a/src/frontend/src/locales/en/rooms.json +++ b/src/frontend/src/locales/en/rooms.json @@ -188,5 +188,11 @@ }, "recording": { "label": "Recording" + }, + "participantTileFocus": { + "pin": { + "enable": "Pin", + "disable": "Unpin" + } } } diff --git a/src/frontend/src/locales/fr/rooms.json b/src/frontend/src/locales/fr/rooms.json index 4583a618..4e80b75e 100644 --- a/src/frontend/src/locales/fr/rooms.json +++ b/src/frontend/src/locales/fr/rooms.json @@ -188,5 +188,11 @@ }, "recording": { "label": "Enregistrement" + }, + "participantTileFocus": { + "pin": { + "enable": "Épingler", + "disable": "Annuler l'épinglage" + } } }