import React, { useEffect, useReducer, useRef } from 'react'; import { createContext, useContextSelector } from 'use-context-selector'; import PropTypes from 'prop-types'; import { equals } from 'ramda'; import { PINNED_PAD_SUBSCRIPTION } from '/imports/ui/components/notes/queries'; import { ACTIONS, PRESENTATION_AREA, PANELS, LAYOUT_TYPE, } from '/imports/ui/components/layout/enums'; import DEFAULT_VALUES from '/imports/ui/components/layout/defaultValues'; import { INITIAL_INPUT_STATE, INITIAL_OUTPUT_STATE } from './initState'; import useUpdatePresentationAreaContentForPlugin from '/imports/ui/components/plugins-engine/ui-data-hooks/layout/presentation-area/utils'; import { isPresentationEnabled } from '/imports/ui/services/features'; import useDeduplicatedSubscription from '../../core/hooks/useDeduplicatedSubscription'; // variable to debug in console log const debug = false; const debugActions = (action, value) => { const baseStyles = [ 'color: #fff', 'background-color: #d64541', 'padding: 2px 4px', 'border-radius: 2px', ].join(';'); return debug && console.log(`%c${action}`, baseStyles, value); }; const providerPropTypes = { children: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.node), PropTypes.node, ]).isRequired, }; const LayoutContextSelector = createContext(); const initPresentationAreaContentActions = [{ type: ACTIONS.SET_PILE_CONTENT_FOR_PRESENTATION_AREA, value: { content: PRESENTATION_AREA.WHITEBOARD_OPEN, open: true, }, }]; const initState = { presentationAreaContentActions: initPresentationAreaContentActions, deviceType: null, isRTL: false, layoutType: DEFAULT_VALUES.layoutType, fontSize: DEFAULT_VALUES.fontSize, idChatOpen: '', fullscreen: { element: '', group: '', }, input: INITIAL_INPUT_STATE, output: INITIAL_OUTPUT_STATE, }; const reducer = (state, action) => { debugActions(action.type, action.value); switch (action.type) { case ACTIONS.SET_FOCUSED_CAMERA_ID: { const { cameraDock } = state.input; const { focusedId } = cameraDock; if (focusedId === action.value) return state; return { ...state, input: { ...state.input, cameraDock: { ...cameraDock, focusedId: action.value, }, }, }; } case ACTIONS.SET_LAYOUT_INPUT: { if (state.input === action.value) return state; return { ...state, input: action.value, }; } case ACTIONS.SET_AUTO_ARRANGE_LAYOUT: { const { autoarrAngeLayout } = state.input; if (autoarrAngeLayout === action.value) return state; return { ...state, input: { ...state.input, autoarrAngeLayout: action.value, }, }; } case ACTIONS.SET_IS_RTL: { const { isRTL } = state; if (isRTL === action.value) return state; return { ...state, isRTL: action.value, }; } // LAYOUT TYPE // using to load a different layout manager case ACTIONS.SET_LAYOUT_TYPE: { const { layoutType } = state.input; if (layoutType === action.value) return state; return { ...state, layoutType: action.value, }; } // FONT SIZE case ACTIONS.SET_FONT_SIZE: { const { fontSize } = state; if (fontSize === action.value) return state; return { ...state, fontSize: action.value, }; } // ID CHAT open in sidebar content panel case ACTIONS.SET_ID_CHAT_OPEN: { if (state.idChatOpen === action.value) return state; return { ...state, idChatOpen: action.value, }; } // DEVICE case ACTIONS.SET_DEVICE_TYPE: { const { deviceType } = state; if (deviceType === action.value) return state; return { ...state, deviceType: action.value, }; } // BROWSER case ACTIONS.SET_BROWSER_SIZE: { const { width, height } = action.value; const { browser } = state.input; if (browser.width === width && browser.height === height) { return state; } return { ...state, input: { ...state.input, browser: { width, height, }, }, }; } // BANNER BAR case ACTIONS.SET_HAS_BANNER_BAR: { const { bannerBar } = state.input; if (bannerBar.hasBanner === action.value) { return state; } return { ...state, input: { ...state.input, bannerBar: { ...bannerBar, hasBanner: action.value, }, }, }; } // NOTIFICATIONS BAR case ACTIONS.SET_HAS_NOTIFICATIONS_BAR: { const { notificationsBar } = state.input; if (notificationsBar.hasNotification === action.value) { return state; } return { ...state, input: { ...state.input, notificationsBar: { ...notificationsBar, hasNotification: action.value, }, }, }; } // NAV BAR case ACTIONS.SET_HAS_NAVBAR: { const { navBar } = state.input; if (navBar.hasNavBar === action.value) { return state; } return { ...state, input: { ...state.input, navBar: { ...navBar, hasNavBar: action.value, }, }, }; } case ACTIONS.SET_NAVBAR_OUTPUT: { const { display, width, height, top, left, tabOrder, zIndex, } = action.value; const { navBar } = state.output; if (navBar.display === display && navBar.width === width && navBar.height === height && navBar.top === top && navBar.left === left && navBar.zIndex === zIndex && navBar.tabOrder === tabOrder) { return state; } return { ...state, output: { ...state.output, navBar: { ...navBar, display, width, height, top, left, tabOrder, zIndex, }, }, }; } // ACTION BAR case ACTIONS.SET_HAS_ACTIONBAR: { const { actionBar } = state.input; if (actionBar.hasActionBar === action.value) { return state; } return { ...state, input: { ...state.input, actionBar: { ...actionBar, hasActionBar: action.value, }, }, }; } case ACTIONS.SET_ACTIONBAR_OUTPUT: { const { display, width, height, innerHeight, top, left, padding, tabOrder, zIndex, } = action.value; const { actionBar } = state.output; if (actionBar.display === display && actionBar.width === width && actionBar.height === height && actionBar.innerHeight === innerHeight && actionBar.top === top && actionBar.left === left && actionBar.padding === padding && actionBar.zIndex === zIndex && actionBar.tabOrder === tabOrder) { return state; } return { ...state, output: { ...state.output, actionBar: { ...actionBar, display, width, height, innerHeight, top, left, padding, tabOrder, zIndex, }, }, }; } // CAPTIONS case ACTIONS.SET_CAPTIONS_OUTPUT: { const { left, right, maxWidth, } = action.value; const { captions } = state.output; if (captions.left === left && captions.right === right && captions.maxWidth === maxWidth) { return state; } return { ...state, output: { ...state.output, captions: { ...captions, left, right, maxWidth, }, }, }; } // SIDEBAR NAVIGATION case ACTIONS.SET_SIDEBAR_NAVIGATION_IS_OPEN: { const { sidebarNavigation } = state.input; if (sidebarNavigation.isOpen === action.value) { return state; } return { ...state, input: { ...state.input, sidebarNavigation: { ...sidebarNavigation, isOpen: action.value, }, }, }; } case ACTIONS.SET_SIDEBAR_NAVIGATION_PANEL: { const { sidebarNavigation } = state.input; if (sidebarNavigation.sidebarNavPanel === action.value) { return state; } return { ...state, input: { ...state.input, sidebarNavigation: { ...sidebarNavigation, sidebarNavPanel: action.value, }, }, }; } case ACTIONS.SET_SIDEBAR_NAVIGATION_SIZE: { const { width, browserWidth } = action.value; const { sidebarNavigation } = state.input; if (sidebarNavigation.width === width && sidebarNavigation.browserWidth === browserWidth) { return state; } return { ...state, input: { ...state.input, sidebarNavigation: { ...sidebarNavigation, width, browserWidth, }, }, }; } case ACTIONS.SET_SIDEBAR_NAVIGATION_OUTPUT: { const { display, minWidth, width, maxWidth, minHeight, height, maxHeight, top, left, right, tabOrder, isResizable, zIndex, } = action.value; const { sidebarNavigation } = state.output; if (sidebarNavigation.display === display && sidebarNavigation.minWidth === minWidth && sidebarNavigation.maxWidth === maxWidth && sidebarNavigation.width === width && sidebarNavigation.minHeight === minHeight && sidebarNavigation.height === height && sidebarNavigation.maxHeight === maxHeight && sidebarNavigation.top === top && sidebarNavigation.left === left && sidebarNavigation.right === right && sidebarNavigation.tabOrder === tabOrder && sidebarNavigation.zIndex === zIndex && sidebarNavigation.isResizable === isResizable) { return state; } return { ...state, output: { ...state.output, sidebarNavigation: { ...sidebarNavigation, display, minWidth, width, maxWidth, minHeight, height, maxHeight, top, left, right, tabOrder, isResizable, zIndex, }, }, }; } case ACTIONS.SET_SIDEBAR_NAVIGATION_RESIZABLE_EDGE: { const { top, right, bottom, left, } = action.value; const { sidebarNavigation } = state.output; if (sidebarNavigation.resizableEdge.top === top && sidebarNavigation.resizableEdge.right === right && sidebarNavigation.resizableEdge.bottom === bottom && sidebarNavigation.resizableEdge.left === left) { return state; } return { ...state, output: { ...state.output, sidebarNavigation: { ...sidebarNavigation, resizableEdge: { top, right, bottom, left, }, }, }, }; } // SIDEBAR CONTENT case ACTIONS.SET_SIDEBAR_CONTENT_IS_OPEN: { const { sidebarContent, sidebarNavigation } = state.input; if (sidebarContent.isOpen === action.value) { return state; } // When opening content sidebar, the navigation sidebar should be opened as well if (action.value === true) sidebarNavigation.isOpen = true; return { ...state, input: { ...state.input, sidebarNavigation, sidebarContent: { ...sidebarContent, isOpen: action.value, }, }, }; } case ACTIONS.SET_SIDEBAR_CONTENT_PANEL: { const { sidebarContent } = state.input; if (sidebarContent.sidebarContentPanel === action.value) { return state; } return { ...state, input: { ...state.input, sidebarContent: { ...sidebarContent, sidebarContentPanel: action.value, }, }, }; } case ACTIONS.SET_SIDEBAR_CONTENT_SIZE: { const { width, browserWidth, height, browserHeight, } = action.value; const { sidebarContent } = state.input; if (sidebarContent.width === width && sidebarContent.browserWidth === browserWidth && sidebarContent.height === height && sidebarContent.browserHeight === browserHeight) { return state; } return { ...state, input: { ...state.input, sidebarContent: { ...sidebarContent, width, browserWidth, height, browserHeight, }, }, }; } case ACTIONS.SET_SIDEBAR_CONTENT_OUTPUT: { const { display, minWidth, width, maxWidth, minHeight, height, maxHeight, top, left, right, currentPanelType, tabOrder, isResizable, zIndex, } = action.value; const { sidebarContent } = state.output; if (sidebarContent.display === display && sidebarContent.minWidth === minWidth && sidebarContent.width === width && sidebarContent.maxWidth === maxWidth && sidebarContent.minHeight === minHeight && sidebarContent.height === height && sidebarContent.maxHeight === maxHeight && sidebarContent.top === top && sidebarContent.left === left && sidebarContent.right === right && sidebarContent.tabOrder === tabOrder && sidebarContent.zIndex === zIndex && sidebarContent.isResizable === isResizable) { return state; } return { ...state, output: { ...state.output, sidebarContent: { ...sidebarContent, display, minWidth, width, maxWidth, minHeight, height, maxHeight, top, left, right, currentPanelType, tabOrder, isResizable, zIndex, }, }, }; } case ACTIONS.SET_SIDEBAR_CONTENT_RESIZABLE_EDGE: { const { top, right, bottom, left, } = action.value; const { sidebarContent } = state.output; if (sidebarContent.resizableEdge.top === top && sidebarContent.resizableEdge.right === right && sidebarContent.resizableEdge.bottom === bottom && sidebarContent.resizableEdge.left === left) { return state; } return { ...state, output: { ...state.output, sidebarContent: { ...sidebarContent, resizableEdge: { top, right, bottom, left, }, }, }, }; } // MEDIA case ACTIONS.SET_MEDIA_AREA_SIZE: { const { width, height } = action.value; const { mediaArea } = state.output; if (mediaArea.width === width && mediaArea.height === height) { return state; } return { ...state, output: { ...state.output, mediaArea: { ...mediaArea, width, height, }, }, }; } // WEBCAMS case ACTIONS.SET_NUM_CAMERAS: { const { cameraDock } = state.input; if (cameraDock.numCameras === action.value) { return state; } return { ...state, input: { ...state.input, cameraDock: { ...cameraDock, numCameras: action.value, }, }, }; } case ACTIONS.SET_CAMERA_DOCK_IS_DRAGGING: { const { cameraDock } = state.input; if (cameraDock.isDragging === action.value) { return state; } return { ...state, input: { ...state.input, cameraDock: { ...cameraDock, isDragging: action.value, }, }, }; } case ACTIONS.SET_CAMERA_DOCK_IS_RESIZING: { const { cameraDock } = state.input; if (cameraDock.isResizing === action.value) { return state; } return { ...state, input: { ...state.input, cameraDock: { ...cameraDock, isResizing: action.value, }, }, }; } case ACTIONS.SET_CAMERA_DOCK_POSITION: { const { cameraDock } = state.input; if (cameraDock.position === action.value) { return state; } return { ...state, input: { ...state.input, cameraDock: { ...cameraDock, position: action.value, }, }, }; } case ACTIONS.SET_CAMERA_DOCK_SIZE: { const { width, height, browserWidth, browserHeight, } = action.value; const { cameraDock } = state.input; if (cameraDock.width === width && cameraDock.height === height && cameraDock.browserWidth === browserWidth && cameraDock.browserHeight === browserHeight) { return state; } return { ...state, input: { ...state.input, cameraDock: { ...cameraDock, width, height, browserWidth, browserHeight, }, }, }; } case ACTIONS.SET_CAMERA_DOCK_OPTIMAL_GRID_SIZE: { const { width, height } = action.value; const { cameraDock } = state.input; const { cameraOptimalGridSize } = cameraDock; if (cameraOptimalGridSize.width === width && cameraOptimalGridSize.height === height) { return state; } return { ...state, input: { ...state.input, cameraDock: { ...cameraDock, cameraOptimalGridSize: { width, height, }, }, }, }; } case ACTIONS.SET_CAMERA_DOCK_OUTPUT: { const { display, position, minWidth, width, maxWidth, presenterMaxWidth, minHeight, height, maxHeight, top, left, right, tabOrder, isDraggable, resizableEdge, zIndex, focusedId, } = action.value; const { cameraDock } = state.output; if (cameraDock.display === display && cameraDock.position === position && cameraDock.width === width && cameraDock.maxWidth === maxWidth && cameraDock.presenterMaxWidth === presenterMaxWidth && cameraDock.height === height && cameraDock.maxHeight === maxHeight && cameraDock.top === top && cameraDock.left === left && cameraDock.right === right && cameraDock.tabOrder === tabOrder && cameraDock.isDraggable === isDraggable && cameraDock.zIndex === zIndex && cameraDock.resizableEdge === resizableEdge && cameraDock.focusedId === focusedId) { return state; } return { ...state, output: { ...state.output, cameraDock: { ...cameraDock, display, position, minWidth, width, maxWidth, presenterMaxWidth, minHeight, height, maxHeight, top, left, right, tabOrder, isDraggable, resizableEdge, zIndex, focusedId, }, }, }; } case ACTIONS.SET_CAMERA_DOCK_IS_DRAGGABLE: { const { cameraDock } = state.output; if (cameraDock.isDraggable === action.value) { return state; } return { ...state, output: { ...state.output, cameraDock: { ...cameraDock, isDraggable: action.value, }, }, }; } // WEBCAMS DROP AREAS case ACTIONS.SET_DROP_AREAS: { const { dropZoneAreas } = state.output; if (dropZoneAreas === action.value) { return state; } return { ...state, output: { ...state.output, dropZoneAreas: action.value, }, }; } // PRESENTATION case ACTIONS.SET_PRESENTATION_IS_OPEN: { const { presentation } = state.input; if (presentation.isOpen === action.value) { return state; } return { ...state, input: { ...state.input, presentation: { ...presentation, isOpen: action.value, }, }, }; } case ACTIONS.SET_PRESENTATION_SLIDES_LENGTH: { const { presentation } = state.input; if (presentation.slidesLength === action.value) { return state; } return { ...state, input: { ...state.input, presentation: { ...presentation, slidesLength: action.value, }, }, }; } case ACTIONS.SET_PRESENTATION_NUM_CURRENT_SLIDE: { const { presentation } = state.input; if (presentation.currentSlide.num === action.value) { return state; } return { ...state, input: { ...state.input, presentation: { ...presentation, currentSlide: { ...presentation.currentSlide, num: action.value, }, }, }, }; } case ACTIONS.SET_PRESENTATION_CURRENT_SLIDE_SIZE: { const { width, height } = action.value; const { presentation } = state.input; const { currentSlide } = presentation; if (currentSlide.size.width === width && currentSlide.size.height === height) { return state; } return { ...state, input: { ...state.input, presentation: { ...presentation, currentSlide: { ...currentSlide, size: { width, height, }, }, }, }, }; } case ACTIONS.SET_PRESENTATION_RESIZABLE_EDGE: { const { top, right, bottom, left, } = action.value; const { presentation } = state.output; const { resizableEdge } = presentation; if (resizableEdge.top === top && resizableEdge.right === right && resizableEdge.bottom === bottom && resizableEdge.left === left) { return state; } return { ...state, output: { ...state.output, presentation: { ...presentation, resizableEdge: { top, right, bottom, left, }, }, }, }; } case ACTIONS.SET_PRESENTATION_SIZE: { const { width, height, browserWidth, browserHeight, } = action.value; const { presentation } = state.input; if (presentation.width === width && presentation.height === height && presentation.browserWidth === browserWidth && presentation.browserHeight === browserHeight) { return state; } return { ...state, input: { ...state.input, presentation: { ...presentation, width, height, browserWidth, browserHeight, }, }, }; } case ACTIONS.SET_PRESENTATION_OUTPUT: { const { display, minWidth, width, maxWidth, minHeight, height, maxHeight, top, left, right, tabOrder, isResizable, zIndex, } = action.value; const { presentation } = state.output; if (presentation.display === display && presentation.minWidth === minWidth && presentation.width === width && presentation.maxWidth === maxWidth && presentation.minHeight === minHeight && presentation.height === height && presentation.maxHeight === maxHeight && presentation.top === top && presentation.left === left && presentation.right === right && presentation.tabOrder === tabOrder && presentation.zIndex === zIndex && presentation.isResizable === isResizable) { return state; } return { ...state, output: { ...state.output, presentation: { ...presentation, display, minWidth, width, maxWidth, minHeight, height, maxHeight, top, left, right, tabOrder, isResizable, zIndex, }, }, }; } // FULLSCREEN case ACTIONS.SET_FULLSCREEN_ELEMENT: { const { fullscreen } = state; if (fullscreen.element === action.value.element && fullscreen.group === action.value.group) { return state; } return { ...state, fullscreen: { element: action.value.element, group: action.value.group, }, }; } // SCREEN SHARE case ACTIONS.SET_HAS_SCREEN_SHARE: { const { screenShare } = state.input; if (screenShare.hasScreenShare === action.value) { return state; } return { ...state, input: { ...state.input, screenShare: { ...screenShare, hasScreenShare: action.value, }, }, }; } case ACTIONS.SET_SCREEN_SHARE_SIZE: { const { width, height, browserWidth, browserHeight, } = action.value; const { screenShare } = state.input; if (screenShare.width === width && screenShare.height === height && screenShare.browserWidth === browserWidth && screenShare.browserHeight === browserHeight) { return state; } return { ...state, input: { ...state.input, screenShare: { ...screenShare, width, height, browserWidth, browserHeight, }, }, }; } case ACTIONS.SET_SCREEN_SHARE_OUTPUT: { const { width, height, top, left, right, zIndex, } = action.value; const { screenShare } = state.output; if (screenShare.width === width && screenShare.height === height && screenShare.top === top && screenShare.left === left && screenShare.right === right && screenShare.zIndex === zIndex) { return state; } return { ...state, output: { ...state.output, screenShare: { ...screenShare, width, height, top, left, right, zIndex, }, }, }; } // EXTERNAL VIDEO case ACTIONS.SET_HAS_EXTERNAL_VIDEO: { const { externalVideo } = state.input; if (externalVideo.hasExternalVideo === action.value) { return state; } return { ...state, input: { ...state.input, externalVideo: { ...externalVideo, hasExternalVideo: action.value, }, }, }; } case ACTIONS.SET_EXTERNAL_VIDEO_SIZE: { const { width, height, browserWidth, browserHeight, } = action.value; const { externalVideo } = state.input; if (externalVideo.width === width && externalVideo.height === height && externalVideo.browserWidth === browserWidth && externalVideo.browserHeight === browserHeight) { return state; } return { ...state, input: { ...state.input, externalVideo: { ...externalVideo, width, height, browserWidth, browserHeight, }, }, }; } case ACTIONS.SET_EXTERNAL_VIDEO_OUTPUT: { const { width, height, top, left, right, } = action.value; const { externalVideo } = state.output; if (externalVideo.width === width && externalVideo.height === height && externalVideo.top === top && externalVideo.left === left && externalVideo.right === right) { return state; } return { ...state, output: { ...state.output, externalVideo: { ...externalVideo, width, height, top, left, right, }, }, }; } // GENERIC COMPONENT case ACTIONS.SET_HAS_GENERIC_COMPONENT: { const { genericComponent } = state.input; if (genericComponent.genericComponentId === action.value) { return state; } return { ...state, input: { ...state.input, genericComponent: { ...genericComponent, genericComponentId: action.value, }, }, }; } case ACTIONS.SET_GENERIC_COMPONENT_OUTPUT: { const { width, height, top, left, right, } = action.value; const { genericComponent } = state.output; if (genericComponent.width === width && genericComponent.height === height && genericComponent.top === top && genericComponent.left === left && genericComponent.right === right) { return state; } return { ...state, output: { ...state.output, genericComponent: { ...genericComponent, width, height, top, left, right, }, }, }; } // NOTES case ACTIONS.SET_SHARED_NOTES_OUTPUT: { const { width, height, top, left, right, } = action.value; const { sharedNotes } = state.output; if (sharedNotes.width === width && sharedNotes.height === height && sharedNotes.top === top && sharedNotes.left === left && sharedNotes.right === right) { return state; } return { ...state, output: { ...state.output, sharedNotes: { ...sharedNotes, width, height, top, left, right, }, }, }; } case ACTIONS.SET_NOTES_IS_PINNED: { const { sharedNotes } = state.input; if (sharedNotes.isPinned === action.value) { return state; } return { ...state, input: { ...state.input, sharedNotes: { ...sharedNotes, isPinned: action.value, }, }, }; } case ACTIONS.SET_PILE_CONTENT_FOR_PRESENTATION_AREA: { const { presentationAreaContentActions } = state; if (action.value.open) { presentationAreaContentActions.push(action); } else { const indexOfOpenedContent = presentationAreaContentActions.findIndex((p) => { if (action.value.content === PRESENTATION_AREA.GENERIC_COMPONENT) { return ( p.value.content === action.value.content && p.value.open && p.value.genericComponentId === action.value.genericComponentId ); } return ( p.value.content === action.value.content && p.value.open ); }); if ( indexOfOpenedContent !== -1 ) presentationAreaContentActions.splice(indexOfOpenedContent, 1); } return { ...state, presentationAreaContentActions, }; } default: { throw new Error('Unexpected action'); } } }; const updatePresentationAreaContent = ( layoutContextState, previousPresentationAreaContentActions, layoutContextDispatch, ) => { const { layoutType } = layoutContextState; const { sidebarContent } = layoutContextState.input; const { presentationAreaContentActions: currentPresentationAreaContentActions, } = layoutContextState; if (!equals( currentPresentationAreaContentActions, previousPresentationAreaContentActions.current, )) { const CHAT_CONFIG = window.meetingClientSettings.public.chat; const PUBLIC_CHAT_ID = CHAT_CONFIG.public_id; // eslint-disable-next-line no-param-reassign previousPresentationAreaContentActions.current = currentPresentationAreaContentActions.slice(0); const lastIndex = currentPresentationAreaContentActions.length - 1; const lastPresentationContentInPile = currentPresentationAreaContentActions[lastIndex]; switch (lastPresentationContentInPile.value.content) { case PRESENTATION_AREA.GENERIC_COMPONENT: { layoutContextDispatch({ type: ACTIONS.SET_NOTES_IS_PINNED, value: !lastPresentationContentInPile.value.open, }); layoutContextDispatch({ type: ACTIONS.SET_HAS_GENERIC_COMPONENT, value: lastPresentationContentInPile.value.genericComponentId, }); break; } case PRESENTATION_AREA.PINNED_NOTES: { if ( (sidebarContent.isOpen || !isPresentationEnabled()) && (sidebarContent.sidebarContentPanel === PANELS.SHARED_NOTES || !isPresentationEnabled()) ) { if (layoutType === LAYOUT_TYPE.VIDEO_FOCUS) { layoutContextDispatch({ type: ACTIONS.SET_SIDEBAR_CONTENT_PANEL, value: PANELS.CHAT, }); layoutContextDispatch({ type: ACTIONS.SET_ID_CHAT_OPEN, value: PUBLIC_CHAT_ID, }); } else { layoutContextDispatch({ type: ACTIONS.SET_SIDEBAR_CONTENT_IS_OPEN, value: false, }); layoutContextDispatch({ type: ACTIONS.SET_SIDEBAR_CONTENT_PANEL, value: PANELS.NONE, }); } } layoutContextDispatch({ type: ACTIONS.SET_HAS_GENERIC_COMPONENT, value: undefined, }); layoutContextDispatch({ type: ACTIONS.SET_NOTES_IS_PINNED, value: lastPresentationContentInPile.value.open, }); break; } case PRESENTATION_AREA.EXTERNAL_VIDEO: { layoutContextDispatch({ type: ACTIONS.SET_HAS_GENERIC_COMPONENT, value: undefined, }); layoutContextDispatch({ type: ACTIONS.SET_NOTES_IS_PINNED, value: !lastPresentationContentInPile.value.open, }); layoutContextDispatch({ type: ACTIONS.SET_HAS_EXTERNAL_VIDEO, value: lastPresentationContentInPile.value.open, }); break; } case PRESENTATION_AREA.SCREEN_SHARE: { layoutContextDispatch({ type: ACTIONS.SET_HAS_GENERIC_COMPONENT, value: undefined, }); layoutContextDispatch({ type: ACTIONS.SET_NOTES_IS_PINNED, value: !lastPresentationContentInPile.value.open, }); layoutContextDispatch({ type: ACTIONS.SET_HAS_SCREEN_SHARE, value: lastPresentationContentInPile.value.open, }); break; } case PRESENTATION_AREA.WHITEBOARD_OPEN: { layoutContextDispatch({ type: ACTIONS.SET_HAS_SCREEN_SHARE, value: !lastPresentationContentInPile.value.open, }); layoutContextDispatch({ type: ACTIONS.SET_HAS_EXTERNAL_VIDEO, value: !lastPresentationContentInPile.value.open, }); layoutContextDispatch({ type: ACTIONS.SET_HAS_GENERIC_COMPONENT, value: undefined, }); layoutContextDispatch({ type: ACTIONS.PINNED_NOTES, value: !lastPresentationContentInPile.value.open, }); break; } default: break; } layoutContextDispatch({ type: ACTIONS.SET_PRESENTATION_IS_OPEN, value: true, }); } }; const LayoutContextProvider = (props) => { const previousPresentationAreaContentActions = useRef( [{ type: ACTIONS.SET_PILE_CONTENT_FOR_PRESENTATION_AREA, value: { content: PRESENTATION_AREA.WHITEBOARD_OPEN, open: true, }, }], ); const { data: pinnedPadData } = useDeduplicatedSubscription(PINNED_PAD_SUBSCRIPTION); const [layoutContextState, layoutContextDispatch] = useReducer(reducer, initState); const { children } = props; useEffect(() => { updatePresentationAreaContent( layoutContextState, previousPresentationAreaContentActions, layoutContextDispatch, ); }, [layoutContextState]); useEffect(() => { const isSharedNotesPinned = !!pinnedPadData && pinnedPadData.sharedNotes[0]?.pinned; if (isSharedNotesPinned) { layoutContextDispatch({ type: ACTIONS.SET_PILE_CONTENT_FOR_PRESENTATION_AREA, value: { content: PRESENTATION_AREA.PINNED_NOTES, open: true, }, }); } else { layoutContextDispatch({ type: ACTIONS.SET_PILE_CONTENT_FOR_PRESENTATION_AREA, value: { content: PRESENTATION_AREA.PINNED_NOTES, open: false, }, }); } }, [pinnedPadData]); useUpdatePresentationAreaContentForPlugin(layoutContextState); return ( {children} ); }; LayoutContextProvider.propTypes = providerPropTypes; const layoutSelect = ( selector, ) => useContextSelector(LayoutContextSelector, (layout) => selector(layout[0])); const layoutSelectInput = ( selector, ) => useContextSelector(LayoutContextSelector, (layout) => selector(layout[0].input)); const layoutSelectOutput = ( selector, ) => useContextSelector(LayoutContextSelector, (layout) => selector(layout[0].output)); const layoutDispatch = () => useContextSelector(LayoutContextSelector, (layout) => layout[1]); export { LayoutContextProvider, layoutSelect, layoutSelectInput, layoutSelectOutput, layoutDispatch, };