mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-30 20:29:07 +00:00
♻️(frontend) simplify videoconference layout and clarify component roles
Remove unnecessary wrapper divs to reduce layout complexity. Explicitly name components to better reflect their responsibilities, including RoomContentArea which handles the video track viewport.
This commit is contained in:
@@ -1,24 +0,0 @@
|
|||||||
import { styled } from '@/styled-system/jsx'
|
|
||||||
import { cva } from '@/styled-system/css'
|
|
||||||
|
|
||||||
export const LayoutWrapper = styled(
|
|
||||||
'div',
|
|
||||||
cva({
|
|
||||||
base: {
|
|
||||||
position: 'relative',
|
|
||||||
display: 'flex',
|
|
||||||
width: '100%',
|
|
||||||
transition: 'height .5s cubic-bezier(0.4,0,0.2,1) 5ms',
|
|
||||||
},
|
|
||||||
variants: {
|
|
||||||
areSubtitlesOpen: {
|
|
||||||
true: {
|
|
||||||
height: 'calc(100% - 12rem)',
|
|
||||||
},
|
|
||||||
false: {
|
|
||||||
height: '100%',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
)
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// RoomContentArea.tsx
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import { styled } from '@/styled-system/jsx'
|
||||||
|
import { cva } from '@/styled-system/css'
|
||||||
|
import { useSubtitles } from '@/features/subtitle/hooks/useSubtitles'
|
||||||
|
import { useSidePanel } from '@/features/rooms/livekit/hooks/useSidePanel'
|
||||||
|
import {Subtitles} from "@/features/subtitle/component/Subtitles";
|
||||||
|
import {MainNotificationToast} from "@/features/notifications/MainNotificationToast";
|
||||||
|
|
||||||
|
|
||||||
|
const RoomViewport = styled(
|
||||||
|
'div',
|
||||||
|
cva({
|
||||||
|
base: {
|
||||||
|
position: 'absolute',
|
||||||
|
maxHeight: '100%',
|
||||||
|
transition: 'inset .5s cubic-bezier(0.4,0,0.2,1) 5ms',
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
isSidePanelOpen: {
|
||||||
|
true: {
|
||||||
|
inset: `var(--lk-grid-gap) calc(358px + 3rem) calc(80px + var(--lk-grid-gap)) 16px`,
|
||||||
|
},
|
||||||
|
false: {
|
||||||
|
inset: `var(--lk-grid-gap) var(--lk-grid-gap) calc(80px + var(--lk-grid-gap))`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const TrackAreaContainer = styled(
|
||||||
|
'div',
|
||||||
|
cva({
|
||||||
|
base: {
|
||||||
|
position: 'relative',
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
transition: 'height .5s cubic-bezier(0.4,0,0.2,1) 5ms',
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
areSubtitlesOpen: {
|
||||||
|
true: {
|
||||||
|
height: 'calc(100% - 12rem)',
|
||||||
|
},
|
||||||
|
false: {
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
interface RoomContentAreaProps {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RoomContentArea({ children }: RoomContentAreaProps) {
|
||||||
|
const { isSidePanelOpen } = useSidePanel()
|
||||||
|
const { areSubtitlesOpen } = useSubtitles()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RoomViewport isSidePanelOpen={isSidePanelOpen}>
|
||||||
|
<TrackAreaContainer areSubtitlesOpen={areSubtitlesOpen}>
|
||||||
|
{children}
|
||||||
|
</TrackAreaContainer>
|
||||||
|
<Subtitles />
|
||||||
|
<MainNotificationToast />
|
||||||
|
</RoomViewport>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -20,11 +20,9 @@ import {
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { ControlBar } from './ControlBar/ControlBar'
|
import { ControlBar } from './ControlBar/ControlBar'
|
||||||
import { MainNotificationToast } from '@/features/notifications/MainNotificationToast'
|
|
||||||
import { FocusLayout } from '../components/FocusLayout'
|
import { FocusLayout } from '../components/FocusLayout'
|
||||||
import { ParticipantTile } from '../components/ParticipantTile'
|
import { ParticipantTile } from '../components/ParticipantTile'
|
||||||
import { SidePanel } from '../components/SidePanel'
|
import { SidePanel } from '../components/SidePanel'
|
||||||
import { useSidePanel } from '../hooks/useSidePanel'
|
|
||||||
import { RecordingProvider } from '@/features/recording'
|
import { RecordingProvider } from '@/features/recording'
|
||||||
import { ScreenShareErrorModal } from '../components/ScreenShareErrorModal'
|
import { ScreenShareErrorModal } from '../components/ScreenShareErrorModal'
|
||||||
import { useConnectionObserver } from '../hooks/useConnectionObserver'
|
import { useConnectionObserver } from '../hooks/useConnectionObserver'
|
||||||
@@ -35,15 +33,15 @@ import { useSettingsDialog } from '@/features/settings'
|
|||||||
import { SettingsDialogExtendedKey } from '@/features/settings/type'
|
import { SettingsDialogExtendedKey } from '@/features/settings/type'
|
||||||
import { useVideoResolutionSubscription } from '../hooks/useVideoResolutionSubscription'
|
import { useVideoResolutionSubscription } from '../hooks/useVideoResolutionSubscription'
|
||||||
import { SettingsDialogProvider } from '@/features/settings/components/SettingsDialogProvider'
|
import { SettingsDialogProvider } from '@/features/settings/components/SettingsDialogProvider'
|
||||||
import { useSubtitles } from '@/features/subtitle/hooks/useSubtitles'
|
|
||||||
import { Subtitles } from '@/features/subtitle/component/Subtitles'
|
|
||||||
import { IsIdleDisconnectModal } from '../components/IsIdleDisconnectModal'
|
import { IsIdleDisconnectModal } from '../components/IsIdleDisconnectModal'
|
||||||
import { getParticipantName } from '@/features/rooms/utils/getParticipantName'
|
import { getParticipantName } from '@/features/rooms/utils/getParticipantName'
|
||||||
import { useScreenReaderAnnounce } from '@/hooks/useScreenReaderAnnounce'
|
import { useScreenReaderAnnounce } from '@/hooks/useScreenReaderAnnounce'
|
||||||
import { ReactionPortals } from '@/features/reactions/components/ReactionPortals'
|
import { ReactionPortals } from '@/features/reactions/components/ReactionPortals'
|
||||||
import { CarouselLayout } from '@/features/layout/components/CarouselLayout'
|
import { CarouselLayout } from '@/features/layout/components/CarouselLayout'
|
||||||
import { GridLayout } from '@/features/layout/components/GridLayout'
|
import { GridLayout } from '@/features/layout/components/GridLayout'
|
||||||
import { LayoutWrapper } from '@/features/layout/components/LayoutWrapper'
|
import {
|
||||||
|
RoomContentArea,
|
||||||
|
} from '@/features/layout/components/RoomContentArea'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
@@ -231,9 +229,6 @@ export function VideoConference({ ...props }: VideoConferenceProps) {
|
|||||||
])
|
])
|
||||||
/* eslint-enable react-hooks/exhaustive-deps */
|
/* eslint-enable react-hooks/exhaustive-deps */
|
||||||
|
|
||||||
const { isSidePanelOpen } = useSidePanel()
|
|
||||||
const { areSubtitlesOpen } = useSubtitles()
|
|
||||||
|
|
||||||
const [isShareErrorVisible, setIsShareErrorVisible] = useState(false)
|
const [isShareErrorVisible, setIsShareErrorVisible] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -254,57 +249,36 @@ export function VideoConference({ ...props }: VideoConferenceProps) {
|
|||||||
onClose={() => setIsShareErrorVisible(false)}
|
onClose={() => setIsShareErrorVisible(false)}
|
||||||
/>
|
/>
|
||||||
<IsIdleDisconnectModal />
|
<IsIdleDisconnectModal />
|
||||||
<div
|
<RoomContentArea
|
||||||
// todo - extract these magic values into constant
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
inset: isSidePanelOpen
|
|
||||||
? `var(--lk-grid-gap) calc(358px + 3rem) calc(80px + var(--lk-grid-gap)) 16px`
|
|
||||||
: `var(--lk-grid-gap) var(--lk-grid-gap) calc(80px + var(--lk-grid-gap))`,
|
|
||||||
transition: 'inset .5s cubic-bezier(0.4,0,0.2,1) 5ms',
|
|
||||||
maxHeight: '100%',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<LayoutWrapper areSubtitlesOpen={areSubtitlesOpen}>
|
{!focusTrack ? (
|
||||||
<div
|
<div
|
||||||
style={{
|
className="lk-grid-layout-wrapper"
|
||||||
display: 'flex',
|
style={{ height: 'auto' }}
|
||||||
position: 'relative',
|
>
|
||||||
width: '100%',
|
<GridLayout tracks={tracks} style={{ padding: 0 }}>
|
||||||
}}
|
<ParticipantTile />
|
||||||
>
|
</GridLayout>
|
||||||
{!focusTrack ? (
|
</div>
|
||||||
<div
|
) : (
|
||||||
className="lk-grid-layout-wrapper"
|
<div
|
||||||
style={{ height: 'auto' }}
|
className="lk-focus-layout-wrapper"
|
||||||
>
|
style={{ height: 'auto' }}
|
||||||
<GridLayout tracks={tracks} style={{ padding: 0 }}>
|
>
|
||||||
|
<FocusLayoutContainer style={{ padding: 0 }}>
|
||||||
|
<CarouselLayout
|
||||||
|
tracks={carouselTracks}
|
||||||
|
style={{
|
||||||
|
minWidth: '200px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ParticipantTile />
|
<ParticipantTile />
|
||||||
</GridLayout>
|
</CarouselLayout>
|
||||||
</div>
|
{focusTrack && <FocusLayout trackRef={focusTrack} />}
|
||||||
) : (
|
</FocusLayoutContainer>
|
||||||
<div
|
</div>
|
||||||
className="lk-focus-layout-wrapper"
|
)}
|
||||||
style={{ height: 'auto' }}
|
</RoomContentArea>
|
||||||
>
|
|
||||||
<FocusLayoutContainer style={{ padding: 0 }}>
|
|
||||||
<CarouselLayout
|
|
||||||
tracks={carouselTracks}
|
|
||||||
style={{
|
|
||||||
minWidth: '200px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ParticipantTile />
|
|
||||||
</CarouselLayout>
|
|
||||||
{focusTrack && <FocusLayout trackRef={focusTrack} />}
|
|
||||||
</FocusLayoutContainer>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</LayoutWrapper>
|
|
||||||
<Subtitles />
|
|
||||||
<MainNotificationToast />
|
|
||||||
</div>
|
|
||||||
<ControlBar
|
<ControlBar
|
||||||
onDeviceError={(e) => {
|
onDeviceError={(e) => {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
|
|||||||
Reference in New Issue
Block a user