mirror of
https://github.com/suitenumerique/meet.git
synced 2026-07-26 11:58:53 +00:00
♻️(refactor) inject side panel store via context for PiP
Keep pipLayoutStore separate from layoutStore; shared components use context.
This commit is contained in:
@@ -3,7 +3,10 @@ import { supportsScreenSharing } from '@livekit/components-core'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { styled } from '@/styled-system/jsx'
|
||||
import { SidePanel } from '@/features/rooms/livekit/components/SidePanel'
|
||||
import { useSidePanel } from '@/features/rooms/livekit/hooks/useSidePanel'
|
||||
import {
|
||||
SidePanelStoreProvider,
|
||||
useSidePanel,
|
||||
} from '@/features/rooms/livekit/hooks/useSidePanel'
|
||||
import { pipLayoutStore } from '../stores/pipLayoutStore'
|
||||
import { useEscapeDismiss } from '../hooks/useEscapeDismiss'
|
||||
import { usePipKeyboardShortcuts } from '../hooks/usePipKeyboardShortcuts'
|
||||
@@ -17,12 +20,20 @@ import { PipConnectionStateToast } from './notifications/PipConnectionStateToast
|
||||
import { PipReactionPortals } from './PipReactionPortals'
|
||||
|
||||
export const PipView = () => {
|
||||
return (
|
||||
<SidePanelStoreProvider value={pipLayoutStore}>
|
||||
<PipViewContent />
|
||||
</SidePanelStoreProvider>
|
||||
)
|
||||
}
|
||||
|
||||
const PipViewContent = () => {
|
||||
const browserSupportsScreenSharing = supportsScreenSharing()
|
||||
const { t } = useTranslation('rooms', {
|
||||
keyPrefix: 'options.items.pictureInPicture',
|
||||
})
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const { isSidePanelOpen, closePanel } = useSidePanel(pipLayoutStore)
|
||||
const { isSidePanelOpen, closePanel } = useSidePanel()
|
||||
|
||||
// Escape closes the side panel instead of the whole PiP window.
|
||||
useEscapeDismiss(containerRef, isSidePanelOpen, closePanel)
|
||||
@@ -53,7 +64,7 @@ export const PipView = () => {
|
||||
<PipStage />
|
||||
<PipReactionsToolbar />
|
||||
<PipControlBar showScreenShare={browserSupportsScreenSharing} />
|
||||
<SidePanel store={pipLayoutStore} />
|
||||
<SidePanel />
|
||||
<PipReactionPortals />
|
||||
<OverlayStack>
|
||||
<PipConnectionStateToast />
|
||||
|
||||
@@ -4,7 +4,6 @@ import { FeedbackMenuItem } from '@/features/rooms/livekit/components/controls/O
|
||||
import { EffectsMenuItem } from '@/features/rooms/livekit/components/controls/Options/EffectsMenuItem'
|
||||
import { SupportMenuItem } from '@/features/rooms/livekit/components/controls/Options/SupportMenuItem'
|
||||
import { PictureInPictureMenuItem } from '@/features/rooms/livekit/components/controls/Options/PictureInPictureMenuItem'
|
||||
import { pipLayoutStore } from '@/features/pip/stores/pipLayoutStore'
|
||||
import { PipOverflowItems } from './PipOverflowItems'
|
||||
import type { CollapsibleControl } from '../PipControlBar'
|
||||
|
||||
@@ -34,7 +33,7 @@ export const PipOptionsMenuItems = ({
|
||||
)}
|
||||
<MenuSection>
|
||||
<PictureInPictureMenuItem />
|
||||
<EffectsMenuItem store={pipLayoutStore} />
|
||||
<EffectsMenuItem />
|
||||
</MenuSection>
|
||||
<Separator />
|
||||
<MenuSection>
|
||||
|
||||
@@ -2,7 +2,6 @@ import { memo } from 'react'
|
||||
import type { TrackReferenceOrPlaceholder } from '@livekit/components-core'
|
||||
import { styled } from '@/styled-system/jsx'
|
||||
import { ParticipantTile } from '@/features/rooms/livekit/components/ParticipantTile'
|
||||
import { pipLayoutStore } from '../../stores/pipLayoutStore'
|
||||
import { getTrackKey } from '../../utils/pipTrackSelection'
|
||||
|
||||
type PipFocusLayoutProps = {
|
||||
@@ -26,7 +25,6 @@ export const PipFocusLayout = memo(
|
||||
<ParticipantTile
|
||||
key={getTrackKey(mainTrack)}
|
||||
trackRef={mainTrack}
|
||||
sidePanelStore={pipLayoutStore}
|
||||
/>
|
||||
</MainSlot>
|
||||
{thumbnailTrack && (
|
||||
@@ -34,7 +32,6 @@ export const PipFocusLayout = memo(
|
||||
<ParticipantTile
|
||||
key={getTrackKey(thumbnailTrack)}
|
||||
trackRef={thumbnailTrack}
|
||||
sidePanelStore={pipLayoutStore}
|
||||
/>
|
||||
</Thumbnail>
|
||||
)}
|
||||
|
||||
@@ -2,7 +2,6 @@ import { memo, useMemo, useRef } from 'react'
|
||||
import type { TrackReferenceOrPlaceholder } from '@livekit/components-core'
|
||||
import { styled } from '@/styled-system/jsx'
|
||||
import { ParticipantTile } from '@/features/rooms/livekit/components/ParticipantTile'
|
||||
import { pipLayoutStore } from '../../stores/pipLayoutStore'
|
||||
import { usePipElementSize } from '../../hooks/usePipElementSize'
|
||||
import { usePipFlipAnimations } from '../../hooks/usePipFlipAnimations'
|
||||
import { computePipGridLayout } from '../../utils/pipGrid'
|
||||
@@ -47,7 +46,7 @@ export const PipGridLayout = memo(({ tracks }: PipGridLayoutProps) => {
|
||||
<GridContainer ref={containerRef} style={gridStyle}>
|
||||
{tracks.map((track, index) => (
|
||||
<GridCell key={tileKeys[index]} style={placements[index]}>
|
||||
<ParticipantTile trackRef={track} sidePanelStore={pipLayoutStore} />
|
||||
<ParticipantTile trackRef={track} />
|
||||
</GridCell>
|
||||
))}
|
||||
</GridContainer>
|
||||
|
||||
@@ -27,7 +27,6 @@ import { HStack } from '@/styled-system/jsx'
|
||||
import { MutedMicIndicator } from './MutedMicIndicator'
|
||||
import { ParticipantPlaceholder } from './ParticipantPlaceholder'
|
||||
import { ParticipantTileFocus } from './ParticipantTileFocus'
|
||||
import type { SidePanelStore } from '../hooks/useSidePanel'
|
||||
import { FullScreenShareWarning } from './FullScreenShareWarning'
|
||||
import { ParticipantName } from './ParticipantName'
|
||||
import { getParticipantName } from '@/features/rooms/utils/getParticipantName'
|
||||
@@ -53,7 +52,6 @@ export function TrackRefContextIfNeeded(
|
||||
|
||||
interface ParticipantTileExtendedProps extends ParticipantTileProps {
|
||||
disableMetadata?: boolean
|
||||
sidePanelStore?: SidePanelStore
|
||||
}
|
||||
|
||||
export const ParticipantTile: (
|
||||
@@ -68,7 +66,6 @@ export const ParticipantTile: (
|
||||
onParticipantClick,
|
||||
disableSpeakingIndicator,
|
||||
disableMetadata,
|
||||
sidePanelStore,
|
||||
...htmlProps
|
||||
}: ParticipantTileExtendedProps,
|
||||
ref
|
||||
@@ -238,7 +235,6 @@ export const ParticipantTile: (
|
||||
<ParticipantTileFocus
|
||||
trackRef={trackReference}
|
||||
hasKeyboardFocus={hasKeyboardFocus}
|
||||
sidePanelStore={sidePanelStore}
|
||||
/>
|
||||
)}
|
||||
</ParticipantContextIfNeeded>
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { TrackReferenceOrPlaceholder } from '@livekit/components-core'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { type SidePanelStore, useSidePanel } from '../hooks/useSidePanel'
|
||||
import { useSidePanel } from '../hooks/useSidePanel'
|
||||
import { useFullScreen } from '../hooks/useFullScreen'
|
||||
import { Participant, Track } from 'livekit-client'
|
||||
import { MuteAlertDialog } from './MuteAlertDialog'
|
||||
@@ -74,9 +74,9 @@ const FocusButton = ({
|
||||
)
|
||||
}
|
||||
|
||||
const EffectsButton = ({ store }: { store?: SidePanelStore }) => {
|
||||
const EffectsButton = () => {
|
||||
const { t } = useTranslation('rooms', { keyPrefix: 'participantTileFocus' })
|
||||
const { isEffectsOpen, toggleEffects } = useSidePanel(store)
|
||||
const { isEffectsOpen, toggleEffects } = useSidePanel()
|
||||
return (
|
||||
<Button
|
||||
size={'sm'}
|
||||
@@ -132,11 +132,9 @@ const MOUSE_IDLE_TIME = 3000
|
||||
export const ParticipantTileFocus = ({
|
||||
trackRef,
|
||||
hasKeyboardFocus,
|
||||
sidePanelStore,
|
||||
}: {
|
||||
trackRef: TrackReferenceOrPlaceholder
|
||||
hasKeyboardFocus: boolean
|
||||
sidePanelStore?: SidePanelStore
|
||||
}) => {
|
||||
const [hovered, setHovered] = useState(false)
|
||||
const [opacity, setOpacity] = useState(0)
|
||||
@@ -218,7 +216,7 @@ export const ParticipantTileFocus = ({
|
||||
{!isScreenShare ? (
|
||||
<>
|
||||
{participant.isLocal ? (
|
||||
<EffectsButton store={sidePanelStore} />
|
||||
<EffectsButton />
|
||||
) : (
|
||||
canMute && <MuteButton participant={participant} />
|
||||
)}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Button, Div } from '@/primitives'
|
||||
import { RiArrowLeftLine, RiCloseLine } from '@remixicon/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ParticipantsList } from './controls/Participants/ParticipantsList'
|
||||
import { type SidePanelStore, useSidePanel } from '../hooks/useSidePanel'
|
||||
import { useSidePanel } from '../hooks/useSidePanel'
|
||||
import { ReactNode } from 'react'
|
||||
import { Chat } from '../prefabs/Chat'
|
||||
import { Effects } from './effects/Effects'
|
||||
@@ -143,7 +143,7 @@ const Panel = ({ isOpen, keepAlive = false, children }: PanelProps) => (
|
||||
{keepAlive || isOpen ? children : null}
|
||||
</div>
|
||||
)
|
||||
export const SidePanel = ({ store }: { store?: SidePanelStore }) => {
|
||||
export const SidePanel = () => {
|
||||
const {
|
||||
activePanelId,
|
||||
isParticipantsOpen,
|
||||
@@ -157,7 +157,7 @@ export const SidePanel = ({ store }: { store?: SidePanelStore }) => {
|
||||
activeSubPanelId,
|
||||
closePanel,
|
||||
goBack,
|
||||
} = useSidePanel(store)
|
||||
} = useSidePanel()
|
||||
const { t } = useTranslation('rooms', { keyPrefix: 'sidePanel' })
|
||||
const title = t(`heading.${activeSubPanelId || activePanelId}`)
|
||||
|
||||
|
||||
+3
-3
@@ -2,11 +2,11 @@ import { RiImageCircleAiFill } from '@remixicon/react'
|
||||
import { MenuItem } from 'react-aria-components'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { menuRecipe } from '@/primitives/menuRecipe'
|
||||
import { type SidePanelStore, useSidePanel } from '../../../hooks/useSidePanel'
|
||||
import { useSidePanel } from '../../../hooks/useSidePanel'
|
||||
|
||||
export const EffectsMenuItem = ({ store }: { store?: SidePanelStore }) => {
|
||||
export const EffectsMenuItem = () => {
|
||||
const { t } = useTranslation('rooms', { keyPrefix: 'options.items' })
|
||||
const { toggleEffects } = useSidePanel(store)
|
||||
const { toggleEffects } = useSidePanel()
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { createContext, useContext } from 'react'
|
||||
import { useSnapshot } from 'valtio'
|
||||
import { layoutStore } from '@/stores/layout'
|
||||
import { PanelId, SubPanelId } from '../types/panel'
|
||||
@@ -9,7 +10,13 @@ export type SidePanelStore = {
|
||||
activeSubPanelId: SubPanelId | null
|
||||
}
|
||||
|
||||
export const useSidePanel = (store: SidePanelStore = layoutStore) => {
|
||||
const SidePanelStoreContext = createContext<SidePanelStore>(layoutStore)
|
||||
|
||||
export const SidePanelStoreProvider = SidePanelStoreContext.Provider
|
||||
|
||||
export const useSidePanel = (store?: SidePanelStore) => {
|
||||
const currentStore = useContext(SidePanelStoreContext)
|
||||
store ??= currentStore
|
||||
const layoutSnap = useSnapshot(store)
|
||||
const activePanelId = layoutSnap.activePanelId
|
||||
const activeSubPanelId = layoutSnap.activeSubPanelId
|
||||
|
||||
Reference in New Issue
Block a user