From a5fb3b910fe75356f3adbd98b4db27f9e2a555d7 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Thu, 17 Apr 2025 22:00:56 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20add=20meeting=20info=20si?= =?UTF-8?q?de=20panel=20with=20copy=20functionality?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement new side panel that provides easy access to meeting information with copy/paste capabilities. Introduces xs text size to accommodate longer URLs. Panel includes space for future documentation links about meeting functionality. Addresses direct user requests for simpler sharing of meeting details. --- src/frontend/panda.config.ts | 6 ++ .../rooms/livekit/components/Info.tsx | 75 +++++++++++++++++++ .../rooms/livekit/components/SidePanel.tsx | 5 ++ .../components/controls/InfoToggle.tsx | 41 ++++++++++ .../rooms/livekit/hooks/useSidePanel.ts | 9 +++ .../prefabs/ControlBar/MoreOptions.tsx | 2 + src/frontend/src/locales/de/rooms.json | 20 ++++- src/frontend/src/locales/en/rooms.json | 20 ++++- src/frontend/src/locales/fr/rooms.json | 20 ++++- src/frontend/src/locales/nl/rooms.json | 20 ++++- src/frontend/src/primitives/Text.tsx | 4 + 11 files changed, 214 insertions(+), 8 deletions(-) create mode 100644 src/frontend/src/features/rooms/livekit/components/Info.tsx create mode 100644 src/frontend/src/features/rooms/livekit/components/controls/InfoToggle.tsx diff --git a/src/frontend/panda.config.ts b/src/frontend/panda.config.ts index ed740179..921691c0 100644 --- a/src/frontend/panda.config.ts +++ b/src/frontend/panda.config.ts @@ -397,6 +397,12 @@ const config: Config = { lineHeight: '1.25rem', }, }, + xs: { + value: { + fontSize: '0.825rem', + lineHeight: '1.15rem', + }, + }, badge: { value: { fontSize: '0.75rem', diff --git a/src/frontend/src/features/rooms/livekit/components/Info.tsx b/src/frontend/src/features/rooms/livekit/components/Info.tsx new file mode 100644 index 00000000..a0aadaae --- /dev/null +++ b/src/frontend/src/features/rooms/livekit/components/Info.tsx @@ -0,0 +1,75 @@ +import { useTranslation } from 'react-i18next' +import { useEffect, useState } from 'react' +import { VStack } from '@/styled-system/jsx' +import { css } from '@/styled-system/css' +import { RiCheckLine, RiFileCopyLine } from '@remixicon/react' +import { Button, Div, Text } from '@/primitives' +import { getRouteUrl } from '@/navigation/getRouteUrl' +import { useRoomData } from '../hooks/useRoomData' + +export const Info = () => { + const { t } = useTranslation('rooms', { keyPrefix: 'info' }) + + const [isCopied, setIsCopied] = useState(false) + + useEffect(() => { + if (isCopied) { + const timeout = setTimeout(() => setIsCopied(false), 3000) + return () => clearTimeout(timeout) + } + }, [isCopied]) + + const data = useRoomData() + const roomUrl = getRouteUrl('room', data?.slug) + + return ( +
+ + + {t('roomInformation.title')} + + + {roomUrl} + + + +
+ ) +} diff --git a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx index c437123b..57db8dda 100644 --- a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx +++ b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx @@ -12,6 +12,7 @@ import { Chat } from '../prefabs/Chat' import { Effects } from './effects/Effects' import { Admin } from './Admin' import { Tools } from './Tools' +import { Info } from './Info' type StyledSidePanelProps = { title: string @@ -133,6 +134,7 @@ export const SidePanel = () => { isSidePanelOpen, isToolsOpen, isAdminOpen, + isInfoOpen, isSubPanelOpen, activeSubPanelId, } = useSidePanel() @@ -167,6 +169,9 @@ export const SidePanel = () => { + + + ) } diff --git a/src/frontend/src/features/rooms/livekit/components/controls/InfoToggle.tsx b/src/frontend/src/features/rooms/livekit/components/controls/InfoToggle.tsx new file mode 100644 index 00000000..2f61921b --- /dev/null +++ b/src/frontend/src/features/rooms/livekit/components/controls/InfoToggle.tsx @@ -0,0 +1,41 @@ +import { useTranslation } from 'react-i18next' +import { RiInformationLine } from '@remixicon/react' +import { css } from '@/styled-system/css' +import { ToggleButton } from '@/primitives' +import { useSidePanel } from '../../hooks/useSidePanel' +import { ToggleButtonProps } from '@/primitives/ToggleButton' + +export const InfoToggle = ({ + onPress, + ...props +}: Partial) => { + const { t } = useTranslation('rooms', { keyPrefix: 'controls.info' }) + + const { isInfoOpen, toggleInfo } = useSidePanel() + const tooltipLabel = isInfoOpen ? 'open' : 'closed' + + return ( +
+ { + toggleInfo() + onPress?.(e) + }} + data-attr={`controls-info-${tooltipLabel}`} + {...props} + > + + +
+ ) +} diff --git a/src/frontend/src/features/rooms/livekit/hooks/useSidePanel.ts b/src/frontend/src/features/rooms/livekit/hooks/useSidePanel.ts index ed23512e..96b125e9 100644 --- a/src/frontend/src/features/rooms/livekit/hooks/useSidePanel.ts +++ b/src/frontend/src/features/rooms/livekit/hooks/useSidePanel.ts @@ -7,6 +7,7 @@ export enum PanelId { CHAT = 'chat', TOOLS = 'tools', ADMIN = 'admin', + INFO = 'info', } export enum SubPanelId { @@ -24,6 +25,7 @@ export const useSidePanel = () => { const isChatOpen = activePanelId == PanelId.CHAT const isToolsOpen = activePanelId == PanelId.TOOLS const isAdminOpen = activePanelId == PanelId.ADMIN + const isInfoOpen = activePanelId == PanelId.INFO const isTranscriptOpen = activeSubPanelId == SubPanelId.TRANSCRIPT const isScreenRecordingOpen = activeSubPanelId == SubPanelId.SCREEN_RECORDING const isSidePanelOpen = !!activePanelId @@ -54,6 +56,11 @@ export const useSidePanel = () => { if (layoutSnap.activeSubPanelId) layoutStore.activeSubPanelId = null } + const toggleInfo = () => { + layoutStore.activePanelId = isInfoOpen ? null : PanelId.INFO + if (layoutSnap.activeSubPanelId) layoutStore.activeSubPanelId = null + } + const openTranscript = () => { layoutStore.activeSubPanelId = SubPanelId.TRANSCRIPT layoutStore.activePanelId = PanelId.TOOLS @@ -72,6 +79,7 @@ export const useSidePanel = () => { toggleEffects, toggleTools, toggleAdmin, + toggleInfo, openTranscript, openScreenRecording, isSubPanelOpen, @@ -81,6 +89,7 @@ export const useSidePanel = () => { isSidePanelOpen, isToolsOpen, isAdminOpen, + isInfoOpen, isTranscriptOpen, isScreenRecordingOpen, } diff --git a/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/MoreOptions.tsx b/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/MoreOptions.tsx index 8715b95b..811b3a80 100644 --- a/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/MoreOptions.tsx +++ b/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/MoreOptions.tsx @@ -2,6 +2,7 @@ import { css } from '@/styled-system/css' import { ChatToggle } from '../../components/controls/ChatToggle' import { ParticipantsToggle } from '../../components/controls/Participants/ParticipantsToggle' import { ToolsToggle } from '../../components/controls/ToolsToggle' +import { InfoToggle } from '../../components/controls/InfoToggle' import { AdminToggle } from '../../components/AdminToggle' import { useSize } from '../../hooks/useResizeObserver' import { useState, RefObject } from 'react' @@ -18,6 +19,7 @@ const NavigationControls = ({ tooltipType = 'instant', }: Partial) => ( <> + diff --git a/src/frontend/src/locales/de/rooms.json b/src/frontend/src/locales/de/rooms.json index 17c44a96..3cff09c6 100644 --- a/src/frontend/src/locales/de/rooms.json +++ b/src/frontend/src/locales/de/rooms.json @@ -91,6 +91,10 @@ } } }, + "info": { + "open": "", + "closed": "" + }, "hand": { "raise": "", "lower": "" @@ -171,7 +175,8 @@ "transcript": "", "screenRecording": "", "admin": "", - "tools": "" + "tools": "", + "info": "" }, "content": { "participants": "", @@ -180,7 +185,8 @@ "transcript": "", "screenRecording": "", "admin": "", - "tools": "" + "tools": "", + "info": "" }, "closeButton": "" }, @@ -201,6 +207,16 @@ } } }, + "info": { + "roomInformation": { + "title": "", + "button": { + "ariaLabel": "", + "copy": "", + "copied": "" + } + } + }, "transcript": { "start": { "heading": "", diff --git a/src/frontend/src/locales/en/rooms.json b/src/frontend/src/locales/en/rooms.json index 739cfa40..0e35f5af 100644 --- a/src/frontend/src/locales/en/rooms.json +++ b/src/frontend/src/locales/en/rooms.json @@ -90,6 +90,10 @@ } } }, + "info": { + "open": "Hide information", + "closed": "Show information" + }, "hand": { "raise": "Raise hand", "lower": "Lower hand" @@ -170,7 +174,8 @@ "transcript": "Transcription", "screenRecording": "Recording", "admin": "Admin settings", - "tools": "More tools" + "tools": "More tools", + "info": "Meeting information" }, "content": { "participants": "participants", @@ -179,7 +184,8 @@ "transcript": "transcription", "screenRecording": "recording", "admin": "admin settings", - "tools": "more tools" + "tools": "more tools", + "info": "meeting information" }, "closeButton": "Hide {{content}}" }, @@ -200,6 +206,16 @@ } } }, + "info": { + "roomInformation": { + "title": "Connection Information", + "button": { + "ariaLabel": "Copy your meeting address", + "copy": "Copy address", + "copied": "Address copied" + } + } + }, "transcript": { "start": { "heading": "Transcribe this call", diff --git a/src/frontend/src/locales/fr/rooms.json b/src/frontend/src/locales/fr/rooms.json index 5f23e211..645f3d4b 100644 --- a/src/frontend/src/locales/fr/rooms.json +++ b/src/frontend/src/locales/fr/rooms.json @@ -90,6 +90,10 @@ } } }, + "info": { + "open": "Masquer les informations", + "closed": "Afficher les informations" + }, "hand": { "raise": "Lever la main", "lower": "Baisser la main" @@ -170,7 +174,8 @@ "transcript": "Transcription", "screenRecording": "Enregistrement", "admin": "Commandes de l'organisateur", - "tools": "Plus d'outils" + "tools": "Plus d'outils", + "info": "Informations sur la réunion" }, "content": { "participants": "les participants", @@ -179,7 +184,8 @@ "transcript": "transcription", "screenRecording": "enregistrement", "admin": "commandes de l'organisateur", - "tools": "plus d'outils" + "tools": "plus d'outils", + "info": "informations sur la réunion" }, "closeButton": "Masquer {{content}}" }, @@ -200,6 +206,16 @@ } } }, + "info": { + "roomInformation": { + "title": "Informations de connexions", + "button": { + "ariaLabel": "Copier l'adresse de votre réunion", + "copy": "Copier l'adresse", + "copied": "Adresse copiée" + } + } + }, "transcript": { "start": { "heading": "Transcrire cet appel", diff --git a/src/frontend/src/locales/nl/rooms.json b/src/frontend/src/locales/nl/rooms.json index da3d8d87..9ee85b85 100644 --- a/src/frontend/src/locales/nl/rooms.json +++ b/src/frontend/src/locales/nl/rooms.json @@ -90,6 +90,10 @@ } } }, + "info": { + "open": "Informatie verbergen", + "closed": "Informatie tonen" + }, "hand": { "raise": "Hand opsteken", "lower": "Hand laten zakken" @@ -170,7 +174,8 @@ "transcript": "Transcriptie", "screenRecording": "Schermopname", "admin": "Beheerdersbediening", - "tools": "Meer tools" + "tools": "Meer tools", + "info": "Vergaderinformatie" }, "content": { "participants": "deelnemers", @@ -179,7 +184,8 @@ "screenRecording": "transcriptie", "transcript": "schermopname", "admin": "beheerdersbediening", - "tools": "meer tools" + "tools": "meer tools", + "info": "vergaderinformatie" }, "closeButton": "Verberg {{content}}" }, @@ -200,6 +206,16 @@ } } }, + "info": { + "roomInformation": { + "title": "Verbindingsinformatie", + "button": { + "ariaLabel": "Kopieer je vergaderadres", + "copy": "Adres kopiëren", + "copied": "Adres gekopieerd" + } + } + }, "transcript": { "start": { "heading": "Transcribeer dit gesprek", diff --git a/src/frontend/src/primitives/Text.tsx b/src/frontend/src/primitives/Text.tsx index a7de86ef..bd430025 100644 --- a/src/frontend/src/primitives/Text.tsx +++ b/src/frontend/src/primitives/Text.tsx @@ -57,6 +57,10 @@ export const text = cva({ color: 'default.subtle-text', textStyle: 'sm', }, + xsNote: { + color: 'default.subtle-text', + textStyle: 'xs', + }, inherits: {}, }, centered: {