From 47ce59833f0be83d2bb581c148d8ae07bb37d200 Mon Sep 17 00:00:00 2001 From: cheerchen Date: Thu, 26 Aug 2021 17:53:42 +0800 Subject: [PATCH] feat(whiteboard): support multi window --- desktop/renderer-app/package.json | 4 +- .../src/components/Whiteboard.less | 37 +-- .../src/components/Whiteboard.tsx | 73 +++--- .../src/pages/CloudStoragePage/index.tsx | 50 +--- .../src/stores/WhiteboardStore.ts | 145 ++++++++++- web/flat-web/package.json | 4 +- web/flat-web/src/components/Whiteboard.less | 37 +-- web/flat-web/src/components/Whiteboard.tsx | 73 +++--- .../CloudStoragePage/CloudStoragePanel.tsx | 51 +--- web/flat-web/src/stores/WhiteboardStore.ts | 162 +++++++++++- yarn.lock | 233 ++++++++---------- 11 files changed, 513 insertions(+), 356 deletions(-) diff --git a/desktop/renderer-app/package.json b/desktop/renderer-app/package.json index 5250c1329d4..ef5c262d2fd 100644 --- a/desktop/renderer-app/package.json +++ b/desktop/renderer-app/package.json @@ -8,13 +8,11 @@ "@netless/combine-player": "^1.1.4", "@netless/cursor-tool": "^0.1.0", "@netless/fetch-middleware": "^1.0.7", - "@netless/page-controller": "^0.0.4", "@netless/player-controller": "^0.0.9", - "@netless/preview-controller": "^0.0.9", "@netless/redo-undo": "^0.0.5", "@netless/tool-box": "^0.1.4", "@netless/video-js-plugin": "^0.3.6", - "@netless/zoom-controller": "^0.1.1", + "@netless/window-manager": "^0.1.39", "@videojs/vhs-utils": "^2.3.0", "agora-rtm-sdk": "^1.4.3", "antd": "^4.15.4", diff --git a/desktop/renderer-app/src/components/Whiteboard.less b/desktop/renderer-app/src/components/Whiteboard.less index b67f8a9404f..3b87e75f793 100644 --- a/desktop/renderer-app/src/components/Whiteboard.less +++ b/desktop/renderer-app/src/components/Whiteboard.less @@ -30,13 +30,10 @@ z-index: 3; bottom: 8px; left: 8px; -} -.zoom-controller-box { - position: absolute; - left: 76px; - z-index: 3; - bottom: 8px; + &.is-disabled { + display: none; + } } .page-controller-box { @@ -44,33 +41,9 @@ z-index: 3; bottom: 8px; right: 8px; -} -.page-controller-mid-box { - display: flex; - align-items: center; - justify-content: center; - background-color: white; - height: 32px; - padding-left: 4px; - padding-right: 4px; - border-radius: 4px; - user-select: none; - font-size: 12px; - box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.08); -} - -.page-preview-cell { - width: 24px; - height: 24px; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - background-color: white; - border-radius: 2px; - &:hover { - background: rgba(33, 35, 36, 0.1); + &.is-disabled { + display: none; } } diff --git a/desktop/renderer-app/src/components/Whiteboard.tsx b/desktop/renderer-app/src/components/Whiteboard.tsx index e84a03dfb1c..ac078a0c29d 100644 --- a/desktop/renderer-app/src/components/Whiteboard.tsx +++ b/desktop/renderer-app/src/components/Whiteboard.tsx @@ -1,16 +1,15 @@ -import PageController from "@netless/page-controller"; -import PreviewController from "@netless/preview-controller"; +import "@netless/window-manager/dist/style.css"; +import "./Whiteboard.less"; + import RedoUndo from "@netless/redo-undo"; import ToolBox from "@netless/tool-box"; -import ZoomController from "@netless/zoom-controller"; import classNames from "classnames"; import { observer } from "mobx-react-lite"; import React, { useCallback } from "react"; -import { RoomPhase } from "white-web-sdk"; -import pagesSVG from "../assets/image/pages.svg"; +import { WindowManager } from "@netless/window-manager"; import { WhiteboardStore } from "../stores/WhiteboardStore"; import { isSupportedImageType, onDropImage } from "../utils/dnd/image"; -import "./Whiteboard.less"; +import { ScenesController } from "flat-components"; export interface WhiteboardProps { whiteboardStore: WhiteboardStore; @@ -20,14 +19,22 @@ export const Whiteboard = observer(function Whiteboard({ whiteb const { room } = whiteboardStore; const bindWhiteboard = useCallback( - (ref: HTMLDivElement) => { - if (room) { - room.bindHtmlElement(ref); - if (room.phase === RoomPhase.Connected) { - room.scalePptToFit(); - } + async (ref: HTMLDivElement | null) => { + if (ref && room) { + await WindowManager.mount({ + room, + container: ref, + collectorStyles: { + position: "absolute", + right: "10px", + bottom: "60px", + }, + }); + whiteboardStore.onMainViewModeChange(); + whiteboardStore.onBoxStateChange(); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [room], ); @@ -66,37 +73,31 @@ export const Whiteboard = observer(function Whiteboard({ whiteb onDragOver={onDragOver} onDrop={onDrop} > -
- -
-
+
-
-
- -
- {"pages"} -
-
+
+
- - {/* */}
diff --git a/desktop/renderer-app/src/pages/CloudStoragePage/index.tsx b/desktop/renderer-app/src/pages/CloudStoragePage/index.tsx index fa55f39594a..044951634ca 100644 --- a/desktop/renderer-app/src/pages/CloudStoragePage/index.tsx +++ b/desktop/renderer-app/src/pages/CloudStoragePage/index.tsx @@ -11,7 +11,7 @@ import { queryConvertingTaskStatus } from "../../apiMiddleware/courseware-conver import { convertFinish } from "../../apiMiddleware/flatServer/storage"; import { useIsomorphicLayoutEffect } from "react-use"; import { MainPageLayoutContainer } from "../../components/MainPageLayoutContainer"; -import { RoomPhase, SceneDefinition } from "white-web-sdk"; +import { SceneDefinition } from "white-web-sdk"; import { useTranslation } from "react-i18next"; import { RequestErrorCode } from "../../constants/ErrorCode"; import { ServerRequestError } from "../../utils/error/ServerRequestError"; @@ -63,12 +63,9 @@ export const CloudStoragePage = observer(function CloudSt await insertImage(file); break; } - case ".mp3": { - insertAudio(file); - break; - } + case ".mp3": case ".mp4": { - insertVideo(file); + insertMediaFile(file); break; } case ".doc": @@ -92,6 +89,8 @@ export const CloudStoragePage = observer(function CloudSt } async function insertImage(file: CloudStorageFile): Promise { + await whiteboard?.setSwitchMainView(); + const room = whiteboard?.room; if (!room) { return; @@ -132,34 +131,8 @@ export const CloudStoragePage = observer(function CloudSt room.completeImageUpload(uuid, file.fileURL); } - function insertAudio(file: CloudStorageFile): void { - const room = whiteboard?.room; - if (!room) { - return; - } - - room.insertPlugin("video.js", { - originX: -240, - originY: -43, - width: 480, - height: 86, - attributes: { src: file.fileURL }, - }); - } - - function insertVideo(file: CloudStorageFile): void { - const room = whiteboard?.room; - if (!room) { - return; - } - - room.insertPlugin("video.js", { - originX: -240, - originY: -135, - width: 480, - height: 270, - attributes: { src: file.fileURL }, - }); + function insertMediaFile(file: CloudStorageFile): void { + whiteboard?.openMediaFile(file.fileURL, file.fileName); } async function insertDocs(file: CloudStorageFile, ext: string): Promise { @@ -208,19 +181,16 @@ export const CloudStoragePage = observer(function CloudSt f => ({ name: v4uuid(), ppt: { + src: f.conversionFileUrl, width: f.width, height: f.height, - src: f.conversionFileUrl, previewURL: f.preview, }, }), ); const uuid = v4uuid(); - room.putScenes(`/${taskUUID}/${uuid}`, scenes); - room.setScenePath(`/${taskUUID}/${uuid}/${scenes[0].name}`); - if (room.phase === RoomPhase.Connected) { - room.scalePptToFit(); - } + const scenesPath = `/${taskUUID}/${uuid}`; + whiteboard?.openDocsFile(scenesPath, file.fileName, scenes); } else { void message.error(t("unable-to-insert-courseware")); } diff --git a/desktop/renderer-app/src/stores/WhiteboardStore.ts b/desktop/renderer-app/src/stores/WhiteboardStore.ts index 5738b72dc07..2a36b0d8266 100644 --- a/desktop/renderer-app/src/stores/WhiteboardStore.ts +++ b/desktop/renderer-app/src/stores/WhiteboardStore.ts @@ -1,5 +1,6 @@ import "video.js/dist/video-js.css"; +import { WindowManager, BuildinApps } from "@netless/window-manager"; import { makeAutoObservable, observable, runInAction } from "mobx"; import { createPlugins, @@ -8,7 +9,9 @@ import { Room, RoomPhase, RoomState, + SceneDefinition, ViewMode, + ViewVisionMode, WhiteWebSdk, } from "white-web-sdk"; import { @@ -27,10 +30,15 @@ export class WhiteboardStore { public room: Room | null = null; public phase: RoomPhase = RoomPhase.Connecting; public viewMode: ViewMode | null = null; + public windowManager: WindowManager | null = null; public isWritable: boolean; public isShowPreviewPanel = false; public isFileOpen = false; public isKicked = false; + public isFocusWindow = false; + public isWindowMaximization = false; + public currentSceneIndex = 0; + public scenesCount = 0; /** is room Creator */ public readonly isCreator: boolean; @@ -71,6 +79,18 @@ export class WhiteboardStore { } }; + public updateWindowManager = (windowManager: WindowManager): void => { + this.windowManager = windowManager; + }; + + public updateCurrentSceneIndex = (currentSceneIndex: number): void => { + this.currentSceneIndex = currentSceneIndex; + }; + + public updateScenesCount = (scenesCount: number): void => { + this.scenesCount = scenesCount; + }; + public setFileOpen = (open: boolean): void => { this.isFileOpen = open; }; @@ -87,10 +107,100 @@ export class WhiteboardStore { this.isShowPreviewPanel = show; }; + public setFocusWindowManager = (isFocus: boolean): void => { + this.isFocusWindow = isFocus; + }; + + public setSwitchMainView = async (): Promise => { + if (this.windowManager && this.isFocusWindow) { + await this.windowManager.switchMainViewToWriter(); + } + }; + + public setWindowMaximization = (isMaximization: boolean): void => { + this.isWindowMaximization = isMaximization; + }; + + public addScene = (): void => { + if (this.room && this.windowManager) { + const currentScene = this.currentSceneIndex + 1; + const scenePath = this.room.state.sceneState.scenePath; + const pathName = this.scenesPathName(scenePath); + + this.room.putScenes(pathName, [{}], currentScene); + this.windowManager.setMainViewSceneIndex(this.currentSceneIndex + 1); + } + }; + + public preScene = (): void => { + if (this.windowManager && this.currentSceneIndex > 0) { + this.windowManager.setMainViewSceneIndex(this.currentSceneIndex - 1); + } + }; + + public nextScene = (): void => { + if (this.windowManager && this.currentSceneIndex < this.scenesCount - 1) { + this.windowManager.setMainViewSceneIndex(this.currentSceneIndex + 1); + } + }; + private preloadPPTResource = debounce(async (pptSrc: string): Promise => { await getCoursewarePreloader().preload(pptSrc); }, 2000); + public openDocsFile = async ( + scenePath: string, + title: string, + scenes: SceneDefinition[], + ): Promise => { + if (this.windowManager) { + await this.windowManager.addApp({ + kind: BuildinApps.DocsViewer, + options: { + scenePath, + title, + scenes: scenes, + }, + }); + } + }; + + public openMediaFile = async (resourceSrc: string, title: string): Promise => { + if (this.windowManager) { + await this.windowManager.addApp({ + kind: BuildinApps.MediaPlayer, + options: { + title, + }, + attributes: { + src: resourceSrc, + }, + }); + } + }; + + public onMainViewModeChange = (): void => { + if (this.windowManager) { + this.windowManager.emitter.on("mainViewModeChange", mode => { + const isWindow = mode !== ViewVisionMode.Writable; + this.setFocusWindowManager(isWindow); + if (!isWindow && this.room) { + this.updateCurrentSceneIndex(this.room.state.sceneState.index); + this.updateScenesCount(this.room.state.sceneState.scenes.length); + } + }); + } + }; + + public onBoxStateChange = (): void => { + if (this.windowManager) { + this.windowManager.emitter.on("boxStateChange", mode => { + const isMaximization = mode === "maximized"; + this.setWindowMaximization(isMaximization); + }); + } + }; + public async joinWhiteboardRoom(): Promise { if (!globalStore.userUUID) { throw new Error("Missing userUUID"); @@ -152,6 +262,8 @@ export class WhiteboardStore { changeToArrow: "a", changeToHand: "h", }, + useMultiViews: true, + invisiblePlugins: [WindowManager], }, { onPhaseChanged: phase => { @@ -175,6 +287,15 @@ export class WhiteboardStore { } catch (err) { console.log(err); } + + if ( + this.room && + this.windowManager && + this.windowManager.mainView.mode === ViewVisionMode.Writable + ) { + this.updateCurrentSceneIndex(this.room.state.sceneState.index); + this.updateScenesCount(this.room.state.sceneState.scenes.length); + } }, onDisconnectWithError: error => { this.preloadPPTResource.cancel(); @@ -222,19 +343,41 @@ export class WhiteboardStore { this.updateRoom(room); + this.updateCurrentSceneIndex(room.state.sceneState.index); + + this.updateScenesCount(room.state.sceneState.scenes.length); + + if (this.room) { + const windowManager = this.room.getInvisiblePlugin(WindowManager.kind) as WindowManager; + this.updateWindowManager(windowManager); + } + if (NODE_ENV === "development") { (window as any).room = room; + (window as any).manager = this.windowManager; } } public destroy(): void { - if (this.room) { + if (this.room && this.windowManager) { this.preloadPPTResource.cancel(); + this.windowManager.destroy(); this.room.callbacks.off(); } + if (NODE_ENV === "development") { (window as any).room = null; + (window as any).manager = null; } console.log(`Whiteboard unloaded: ${globalStore.whiteboardRoomUUID}`); } + + private scenesPathName = (scenePath: string): string => { + const cells = scenePath.split("/"); + const popCell = cells.pop(); + if (popCell === "") { + cells.pop(); + } + return cells.join("/"); + }; } diff --git a/web/flat-web/package.json b/web/flat-web/package.json index 1f341d97286..74f0df637f4 100644 --- a/web/flat-web/package.json +++ b/web/flat-web/package.json @@ -36,13 +36,11 @@ "@loadable/component": "^5.15.0", "@netless/combine-player": "^1.1.6", "@netless/cursor-tool": "^0.1.0", - "@netless/page-controller": "^0.0.4", "@netless/player-controller": "^0.0.9", - "@netless/preview-controller": "^0.0.9", "@netless/redo-undo": "^0.0.5", "@netless/tool-box": "^0.1.5", "@netless/video-js-plugin": "^0.3.6", - "@netless/zoom-controller": "^0.1.1", + "@netless/window-manager": "^0.1.39", "@videojs/vhs-utils": "^2.3.0", "@zip.js/zip.js": "^2.3.7", "agora-rtc-sdk-ng": "^4.5.0", diff --git a/web/flat-web/src/components/Whiteboard.less b/web/flat-web/src/components/Whiteboard.less index 11fbf83d7b9..ee6818cb0dc 100644 --- a/web/flat-web/src/components/Whiteboard.less +++ b/web/flat-web/src/components/Whiteboard.less @@ -29,13 +29,10 @@ z-index: 3; bottom: 8px; left: 8px; -} -.zoom-controller-box { - position: absolute; - left: 76px; - z-index: 3; - bottom: 8px; + &.is-disabled { + display: none; + } } .page-controller-box { @@ -43,33 +40,9 @@ z-index: 3; bottom: 8px; right: 8px; -} -.page-controller-mid-box { - display: flex; - align-items: center; - justify-content: center; - background-color: white; - height: 32px; - padding-left: 4px; - padding-right: 4px; - border-radius: 4px; - user-select: none; - font-size: 12px; - box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.08); -} - -.page-preview-cell { - width: 24px; - height: 24px; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - background-color: white; - border-radius: 2px; - &:hover { - background: rgba(33, 35, 36, 0.1); + &.is-disabled { + display: none; } } diff --git a/web/flat-web/src/components/Whiteboard.tsx b/web/flat-web/src/components/Whiteboard.tsx index e84a03dfb1c..f5bf26ef328 100644 --- a/web/flat-web/src/components/Whiteboard.tsx +++ b/web/flat-web/src/components/Whiteboard.tsx @@ -1,16 +1,15 @@ -import PageController from "@netless/page-controller"; -import PreviewController from "@netless/preview-controller"; +import "@netless/window-manager/dist/style.css"; +import "./Whiteboard.less"; + import RedoUndo from "@netless/redo-undo"; import ToolBox from "@netless/tool-box"; -import ZoomController from "@netless/zoom-controller"; +import { WindowManager } from "@netless/window-manager"; import classNames from "classnames"; import { observer } from "mobx-react-lite"; import React, { useCallback } from "react"; -import { RoomPhase } from "white-web-sdk"; -import pagesSVG from "../assets/image/pages.svg"; import { WhiteboardStore } from "../stores/WhiteboardStore"; import { isSupportedImageType, onDropImage } from "../utils/dnd/image"; -import "./Whiteboard.less"; +import { ScenesController } from "../../../../packages/flat-components/src"; export interface WhiteboardProps { whiteboardStore: WhiteboardStore; @@ -20,14 +19,22 @@ export const Whiteboard = observer(function Whiteboard({ whiteb const { room } = whiteboardStore; const bindWhiteboard = useCallback( - (ref: HTMLDivElement) => { - if (room) { - room.bindHtmlElement(ref); - if (room.phase === RoomPhase.Connected) { - room.scalePptToFit(); - } + async (ref: HTMLDivElement | null) => { + if (ref && room) { + await WindowManager.mount({ + room, + container: ref, + collectorStyles: { + position: "absolute", + right: "10px", + bottom: "60px", + }, + }); + whiteboardStore.onMainViewModeChange(); + whiteboardStore.onBoxStateChange(); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [room], ); @@ -66,37 +73,31 @@ export const Whiteboard = observer(function Whiteboard({ whiteb onDragOver={onDragOver} onDrop={onDrop} > -
- -
-
+
-
-
- -
- {"pages"} -
-
+
+
- - {/* */}
diff --git a/web/flat-web/src/pages/CloudStoragePage/CloudStoragePanel.tsx b/web/flat-web/src/pages/CloudStoragePage/CloudStoragePanel.tsx index 4e745c75a0a..5a535b771e9 100644 --- a/web/flat-web/src/pages/CloudStoragePage/CloudStoragePanel.tsx +++ b/web/flat-web/src/pages/CloudStoragePage/CloudStoragePanel.tsx @@ -9,7 +9,7 @@ import { CloudStorageStore, CloudStorageFile } from "./store"; import { queryConvertingTaskStatus } from "../../apiMiddleware/courseware-converting"; import { convertFinish } from "../../apiMiddleware/flatServer/storage"; import { useIsomorphicLayoutEffect } from "react-use"; -import { RoomPhase, SceneDefinition } from "white-web-sdk"; +import { SceneDefinition } from "white-web-sdk"; import { CloudStorageContainer } from "flat-components"; import { useTranslation } from "react-i18next"; import { RequestErrorCode } from "../../constants/ErrorCode"; @@ -55,12 +55,9 @@ export const CloudStoragePanel = observer(function Cloud await insertImage(file); break; } - case ".mp3": { - insertAudio(file); - break; - } + case ".mp3": case ".mp4": { - insertVideo(file); + insertMediaFile(file); break; } case ".doc": @@ -84,6 +81,8 @@ export const CloudStoragePanel = observer(function Cloud } async function insertImage(file: CloudStorageFile): Promise { + await whiteboard?.setSwitchMainView(); + const room = whiteboard?.room; if (!room) { return; @@ -124,34 +123,8 @@ export const CloudStoragePanel = observer(function Cloud room.completeImageUpload(uuid, file.fileURL); } - function insertAudio(file: CloudStorageFile): void { - const room = whiteboard?.room; - if (!room) { - return; - } - - room.insertPlugin("video.js", { - originX: -240, - originY: -43, - width: 480, - height: 86, - attributes: { src: file.fileURL }, - }); - } - - function insertVideo(file: CloudStorageFile): void { - const room = whiteboard?.room; - if (!room) { - return; - } - - room.insertPlugin("video.js", { - originX: -240, - originY: -135, - width: 480, - height: 270, - attributes: { src: file.fileURL }, - }); + function insertMediaFile(file: CloudStorageFile): void { + whiteboard?.openMediaFile(file.fileURL, file.fileName); } async function insertDocs(file: CloudStorageFile, ext: string): Promise { @@ -200,19 +173,17 @@ export const CloudStoragePanel = observer(function Cloud f => ({ name: v4uuid(), ppt: { + src: f.conversionFileUrl, width: f.width, height: f.height, - src: f.conversionFileUrl, previewURL: f.preview, }, }), ); + const uuid = v4uuid(); - room.putScenes(`/${taskUUID}/${uuid}`, scenes); - room.setScenePath(`/${taskUUID}/${uuid}/${scenes[0].name}`); - if (room.phase === RoomPhase.Connected) { - room.scalePptToFit(); - } + const scenesPath = `/${taskUUID}/${uuid}`; + whiteboard?.openDocsFile(scenesPath, file.fileName, scenes); } else { void message.error(t("unable-to-insert-courseware")); } diff --git a/web/flat-web/src/stores/WhiteboardStore.ts b/web/flat-web/src/stores/WhiteboardStore.ts index 37774f8a50f..82c086cc81d 100644 --- a/web/flat-web/src/stores/WhiteboardStore.ts +++ b/web/flat-web/src/stores/WhiteboardStore.ts @@ -8,7 +8,9 @@ import { Room, RoomPhase, RoomState, + SceneDefinition, ViewMode, + ViewVisionMode, WhiteWebSdk, } from "white-web-sdk"; import { @@ -22,20 +24,27 @@ import { globalStore } from "./GlobalStore"; import { isMobile, isWindows } from "react-device-detect"; import { debounce } from "lodash-es"; import { coursewarePreloader } from "../utils/CoursewarePreloader"; +import { WindowManager, BuildinApps } from "@netless/window-manager"; export class WhiteboardStore { public room: Room | null = null; public phase: RoomPhase = RoomPhase.Connecting; public viewMode: ViewMode | null = null; + public windowManager: WindowManager | null = null; public isWritable: boolean; public isShowPreviewPanel = false; public isFileOpen = false; public isKicked = false; + public isFocusWindow = false; + public isWindowMaximization = false; + public currentSceneIndex = 0; + public scenesCount = 0; /** is room Creator */ public readonly isCreator: boolean; + public readonly isSpeaker?: boolean; - public constructor(config: { isCreator: boolean }) { + public constructor(config: { isCreator: boolean; isSpeaker?: boolean }) { this.isCreator = config.isCreator; this.isWritable = config.isCreator; @@ -71,6 +80,18 @@ export class WhiteboardStore { } }; + public updateWindowManager = (windowManager: WindowManager): void => { + this.windowManager = windowManager; + }; + + public updateCurrentSceneIndex = (currentSceneIndex: number): void => { + this.currentSceneIndex = currentSceneIndex; + }; + + public updateScenesCount = (scenesCount: number): void => { + this.scenesCount = scenesCount; + }; + public setFileOpen = (open: boolean): void => { this.isFileOpen = open; }; @@ -87,6 +108,110 @@ export class WhiteboardStore { this.isShowPreviewPanel = show; }; + public setSwitchMainView = async (): Promise => { + if (this.windowManager && this.isFocusWindow) { + await this.windowManager.switchMainViewToWriter(); + } + }; + + public setFocusWindow = (isFocus: boolean): void => { + this.isFocusWindow = isFocus; + }; + + public setWindowMaximization = (isMaximization: boolean): void => { + this.isWindowMaximization = isMaximization; + }; + + public setWindowReadonlyState = (isReadonly: boolean): void => { + if (this.windowManager) { + this.windowManager.setReadonly(isReadonly); + } + }; + + public addScene = (): void => { + if (this.room && this.windowManager) { + const currentScene = this.currentSceneIndex + 1; + const scenePath = this.room.state.sceneState.scenePath; + const pathName = this.scenesPathName(scenePath); + + this.room.putScenes(pathName, [{}], currentScene); + this.windowManager.setMainViewSceneIndex(this.currentSceneIndex + 1); + } + }; + + public preScene = (): void => { + if (this.windowManager && this.currentSceneIndex > 0) { + this.windowManager.setMainViewSceneIndex(this.currentSceneIndex - 1); + } + }; + + public nextScene = (): void => { + if (this.windowManager && this.currentSceneIndex < this.scenesCount - 1) { + this.windowManager.setMainViewSceneIndex(this.currentSceneIndex + 1); + } + }; + + public openDocsFile = async ( + scenePath: string, + title: string, + scenes: SceneDefinition[], + ): Promise => { + if (this.windowManager) { + try { + await this.windowManager.addApp({ + kind: BuildinApps.DocsViewer, + options: { + scenePath, + title, + scenes: scenes, + }, + }); + } catch (err) { + console.log(err); + } + } + }; + + public openMediaFile = async (resourceSrc: string, title: string): Promise => { + if (this.windowManager) { + try { + await this.windowManager.addApp({ + kind: BuildinApps.MediaPlayer, + options: { + title, + }, + attributes: { + src: resourceSrc, + }, + }); + } catch (err) { + console.log(err); + } + } + }; + + public onMainViewModeChange = (): void => { + if (this.windowManager) { + this.windowManager.emitter.on("mainViewModeChange", mode => { + const isWindow = mode !== ViewVisionMode.Writable; + this.setFocusWindow(isWindow); + if (!isWindow && this.room) { + this.updateCurrentSceneIndex(this.room.state.sceneState.index); + this.updateScenesCount(this.room.state.sceneState.scenes.length); + } + }); + } + }; + + public onBoxStateChange = (): void => { + if (this.windowManager) { + this.windowManager.emitter.on("boxStateChange", mode => { + const isMaximization = mode === "maximized"; + this.setWindowMaximization(isMaximization); + }); + } + }; + public async joinWhiteboardRoom(): Promise { if (!globalStore.userUUID) { throw new Error("Missing userUUID"); @@ -148,6 +273,8 @@ export class WhiteboardStore { changeToArrow: "a", changeToHand: "h", }, + useMultiViews: true, + invisiblePlugins: [WindowManager], }, { onPhaseChanged: phase => { @@ -166,6 +293,15 @@ export class WhiteboardStore { console.log(err); } } + + if ( + this.room && + this.windowManager && + this.windowManager.mainView.mode === ViewVisionMode.Writable + ) { + this.updateCurrentSceneIndex(this.room.state.sceneState.index); + this.updateScenesCount(this.room.state.sceneState.scenes.length); + } }, onDisconnectWithError: error => { console.error(error); @@ -213,18 +349,31 @@ export class WhiteboardStore { this.updateRoom(room); + this.updateCurrentSceneIndex(room.state.sceneState.index); + + this.updateScenesCount(room.state.sceneState.scenes.length); + + if (this.room) { + const windowManager = this.room.getInvisiblePlugin(WindowManager.kind) as WindowManager; + this.updateWindowManager(windowManager); + } + if (NODE_ENV === "development") { (window as any).room = room; + (window as any).manager = this.windowManager; } } public destroy(): void { - if (this.room) { + if (this.room && this.windowManager) { this.preloadPPTResource.cancel(); + this.windowManager.destroy(); this.room.callbacks.off(); } + if (NODE_ENV === "development") { (window as any).room = null; + (window as any).manager = null; } console.log(`Whiteboard unloaded: ${globalStore.whiteboardRoomUUID}`); } @@ -232,4 +381,13 @@ export class WhiteboardStore { private preloadPPTResource = debounce(async (pptSrc: string): Promise => { await coursewarePreloader.preload(pptSrc); }, 2000); + + private scenesPathName = (scenePath: string): string => { + const cells = scenePath.split("/"); + const popCell = cells.pop(); + if (popCell === "") { + cells.pop(); + } + return cells.join("/"); + }; } diff --git a/yarn.lock b/yarn.lock index 7d818b7553c..1846689e082 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1857,6 +1857,19 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@netless/app-docs-viewer@^0.1.15": + version "0.1.15" + resolved "https://registry.npmjs.org/@netless/app-docs-viewer/-/app-docs-viewer-0.1.15.tgz#8b857c2d2e07889a621b87fde339e8bb3526465e" + integrity sha512-GZuevbDpU4sIyhN8SNrXW247dJmp5OsI18tiHFEU12fXDixwamKqCA3TNiuWD6+C8GmEcs/NvGeAI/yDui9WrA== + dependencies: + debounce-fn "^5.0.0" + vanilla-lazyload "^17.4.0" + +"@netless/app-media-player@0.1.0-beta.4": + version "0.1.0-beta.4" + resolved "https://registry.npmjs.org/@netless/app-media-player/-/app-media-player-0.1.0-beta.4.tgz#2283b8a1e0a104bd8d36a5dbe9798309041e262c" + integrity sha512-mwBrhITav9moFRS9lGmsWnLN1jBJhTjEfnQAVyLCjQvrzGGvZl+bakTSLhaazWvmdbo/V9YKoP0JlbytwAMHlg== + "@netless/canvas-polyfill@^0.0.4": version "0.0.4" resolved "https://registry.yarnpkg.com/@netless/canvas-polyfill/-/canvas-polyfill-0.0.4.tgz#b5f28eefeb9c1e8ff8253fa1b044ccb1dc1b7c9c" @@ -1888,18 +1901,6 @@ dependencies: query-string "^6.13.1" -"@netless/menu-box@^0.0.6": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@netless/menu-box/-/menu-box-0.0.6.tgz#2460ff7ddef6c07066ba1036ff15bfc647bbee28" - integrity sha512-ShiDPCFa4yk6JaP45DCiKr2Iyg7cmwP7fvO7/TkxEiaNWJJpNdPsFwlqzaE64p0INT5Jw0hGy0osNpYIhIfvhQ== - dependencies: - react-burger-menu "^2.7.1" - -"@netless/page-controller@^0.0.4": - version "0.0.4" - resolved "https://registry.yarnpkg.com/@netless/page-controller/-/page-controller-0.0.4.tgz#6f21140f35a279fc37db69f66332d187d180e5ae" - integrity sha512-eDGwbBSpIZB6efrQlTz+sO4oei6Zroiz7IslAxQVFBzmgUnLrbcYyjJm+oz4pP8u+PfyWEKdc6gJzh3kND1iIw== - "@netless/player-controller@^0.0.9": version "0.0.9" resolved "https://registry.yarnpkg.com/@netless/player-controller/-/player-controller-0.0.9.tgz#2c2bad03d1d51c623a09cfa3e36a022809242fbb" @@ -1908,18 +1909,19 @@ "@ant-design/icons" "^4.5.0" "@netless/combine-player" "^1.1.3" -"@netless/preview-controller@^0.0.9": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@netless/preview-controller/-/preview-controller-0.0.9.tgz#9b58c5eb360f76adcec7bfa86370488a1eae0531" - integrity sha512-F50uo/GF3dO9tSm3Lt2jlUNau59sie3uSigQ6g6XJpw74TfPBxn4I7ZVQk84Y576nuahGGdWrBaH0jcrFDN/BQ== - dependencies: - "@netless/menu-box" "^0.0.6" - "@netless/redo-undo@^0.0.5": version "0.0.5" resolved "https://registry.yarnpkg.com/@netless/redo-undo/-/redo-undo-0.0.5.tgz#c5b00f5940ef33a0d6a810cd0935f4d9c172ea52" integrity sha512-P8ceK3hSY2eMfFIjBeSpRsqXpjjTea9bBWyRF8t8q0kLR4ICld2VMFMRbytqZ8sjCFy9CgbicuBOdMj7juABIQ== +"@netless/telebox-insider@^0.1.13": + version "0.1.13" + resolved "https://registry.npmjs.org/@netless/telebox-insider/-/telebox-insider-0.1.13.tgz#b26930727bd982b464332a27c2109aa941bfa908" + integrity sha512-CzgejfkS+MKssokIFVDxHEwYY8+l1S0MXj2kqiFOmREm1FHWJsGSMvxNZ7h1wW5JDO/7PfFuPLiofbIMFYEvuQ== + dependencies: + eventemitter3 "^4.0.7" + stylefire "^7.0.3" + "@netless/tool-box@^0.1.4", "@netless/tool-box@^0.1.5": version "0.1.5" resolved "https://registry.yarnpkg.com/@netless/tool-box/-/tool-box-0.1.5.tgz#39977a0075c069aab90895bcee6268a8e6bf8afd" @@ -1930,16 +1932,24 @@ resolved "https://registry.yarnpkg.com/@netless/video-js-plugin/-/video-js-plugin-0.3.7.tgz#6c1f174f20e8a93634e1770e7e535c1302bdf22b" integrity sha512-UG1t9464w1bZT9kzdhxj/K7R6jqI9sqYfqfUQJ2w9JRWsNibL6O16OC81iwBJT6nkGXEVN7z2pqHvNg1OhKppw== +"@netless/window-manager@^0.1.39": + version "0.1.39" + resolved "https://registry.npmjs.org/@netless/window-manager/-/window-manager-0.1.39.tgz#efcdbde43a5934460bc8342f1fef01068d2f1daa" + integrity sha512-lrwLcTQels327EILdfsi9MWDPu5SUVFU3piunxfXokSVnwavuMOqCEt+SuH5VakTnUC7Sd7nqmMu7c1KUou5og== + dependencies: + "@netless/app-docs-viewer" "^0.1.15" + "@netless/app-media-player" "0.1.0-beta.4" + "@netless/telebox-insider" "^0.1.13" + emittery "^0.9.2" + lodash-es "^4.17.21" + nanoid "^3.1.25" + video.js ">=7" + "@netless/xml-js@1.6.15": version "1.6.15" resolved "https://registry.npmjs.org/@netless/xml-js/-/xml-js-1.6.15.tgz#46516d547b21149bcca732bb199d664791b3240a" integrity sha512-e0emMs7YtDB/ATUns1SJ61R9n9nfVvwwFodoc539Qt0ScksaCLCaFWgpEbLloj9sr60ry6Xd8QFHKULFIZB6zA== -"@netless/zoom-controller@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@netless/zoom-controller/-/zoom-controller-0.1.1.tgz#7386aa13b815e030cc69a29041a819a6ca4fc7aa" - integrity sha512-/ZOzy1AHs2Q6ZjFpazIche4i6904QM773EniWfYR0QnGfp7TwgCA8wNbfD1yMQIX49fOfWR3FQI0RlRN0hVn9w== - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1991,6 +2001,22 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.17.tgz#25fdbdfd282c2f86ddf3fcefbd98be99cd2627e2" integrity sha512-0p1rCgM3LLbAdwBnc7gqgnvjHg9KpbhcSphergHShlkWz8EdPawoMJ3/VbezI0mGC5eKCDzMaPgF9Yca6cKvrg== +"@popmotion/easing@^1.0.1": + version "1.0.2" + resolved "https://registry.npmjs.org/@popmotion/easing/-/easing-1.0.2.tgz#17d925c45b4bf44189e5a38038d149df42d8c0b4" + integrity sha512-IkdW0TNmRnWTeWI7aGQIVDbKXPWHVEYdGgd5ZR4SH/Ty/61p63jCjrPxX1XrR7IGkl08bjhJROStD7j+RKgoIw== + +"@popmotion/popcorn@^0.4.4": + version "0.4.4" + resolved "https://registry.npmjs.org/@popmotion/popcorn/-/popcorn-0.4.4.tgz#a5f906fccdff84526e3fcb892712d7d8a98d6adc" + integrity sha512-jYO/8319fKoNLMlY4ZJPiPu8Ea8occYwRZhxpaNn/kZsK4QG2E7XFlXZMJBsTWDw7I1i0uaqyC4zn1nwEezLzg== + dependencies: + "@popmotion/easing" "^1.0.1" + framesync "^4.0.1" + hey-listen "^1.0.8" + style-value-types "^3.1.7" + tslib "^1.10.0" + "@popperjs/core@^2.5.4", "@popperjs/core@^2.6.0": version "2.9.3" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.3.tgz#8b68da1ebd7fc603999cf6ebee34a4899a14b88e" @@ -4132,11 +4158,6 @@ ali-oss@^6.15.2: utility "^1.8.0" xml2js "^0.4.16" -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - ansi-align@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" @@ -4558,15 +4579,6 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= -ast-transform@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/ast-transform/-/ast-transform-0.0.0.tgz#74944058887d8283e189d954600947bc98fe0062" - integrity sha1-dJRAWIh9goPhidlUYAlHvJj+AGI= - dependencies: - escodegen "~1.2.0" - esprima "~1.0.4" - through "~2.3.4" - ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" @@ -4586,11 +4598,6 @@ ast-types@^0.14.2: dependencies: tslib "^2.0.1" -ast-types@^0.7.0: - version "0.7.8" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.7.8.tgz#902d2e0d60d071bdcd46dc115e1809ed11c138a9" - integrity sha1-kC0uDWDQcb3NRtwRXhgJ7RHBOKk= - astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -5076,13 +5083,6 @@ brorand@^1.0.1, brorand@^1.1.0: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= -browser-resolve@^1.8.1: - version "1.11.3" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" - integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ== - dependencies: - resolve "1.1.7" - browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -5114,15 +5114,6 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-optional@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-optional/-/browserify-optional-1.0.1.tgz#1e13722cfde0d85f121676c2a72ced533a018869" - integrity sha1-HhNyLP3g2F8SFnbCpyztUzoBiGk= - dependencies: - ast-transform "0.0.0" - ast-types "^0.7.0" - browser-resolve "^1.8.1" - browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" @@ -6476,6 +6467,13 @@ dayjs@1.x: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.6.tgz#288b2aa82f2d8418a6c9d4df5898c0737ad02a63" integrity sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw== +debounce-fn@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/debounce-fn/-/debounce-fn-5.0.0.tgz#1375e6b64a871e6fb6967c6ee05efbac08b65d9e" + integrity sha512-y0u25m4GMdDJ1oHX4ziszas15E4ryNoeFkQuZM/Z6yTy8jB8ity/jqSNWnQUi/csBBaQIad6Zd8eI1xKwtbFzw== + dependencies: + mimic-fn "^3.0.0" + debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -7190,6 +7188,11 @@ elliptic@^6.5.3: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +emittery@^0.9.2: + version "0.9.2" + resolved "https://registry.npmjs.org/emittery/-/emittery-0.9.2.tgz#0a57c40773c6da380115c85bd67d381dd9e22f6f" + integrity sha512-sweWHu3j4dQm+NjLPu17pv+m5lCeK7g4Ov0NgfbRUEyzLc59DYDeRYXqlxEvuolaToI0VR3ThjFAghzl7Acjfw== + "emoji-regex@>=6.0.0 <=6.1.1": version "6.1.1" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e" @@ -7481,17 +7484,6 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -escodegen@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.2.0.tgz#09de7967791cc958b7f89a2ddb6d23451af327e1" - integrity sha1-Cd55Z3kcyVi3+Jot220jRRrzJ+E= - dependencies: - esprima "~1.0.4" - estraverse "~1.5.0" - esutils "~1.0.0" - optionalDependencies: - source-map "~0.1.30" - eslint-config-prettier@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" @@ -7739,11 +7731,6 @@ esprima@^4.0.0, esprima@^4.0.1: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esprima@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" - integrity sha1-n1V+CPw7TSbs6d00+Pv0drYlha0= - esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" @@ -7768,11 +7755,6 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== -estraverse@~1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.5.1.tgz#867a3e8e58a9f84618afb6c2ddbcd916b7cbaf71" - integrity sha1-hno+jlip+EYYr7bC3bzZFrfLr3E= - estree-to-babel@^3.1.0: version "3.2.1" resolved "https://registry.yarnpkg.com/estree-to-babel/-/estree-to-babel-3.2.1.tgz#82e78315275c3ca74475fdc8ac1a5103c8a75bf5" @@ -7792,21 +7774,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -esutils@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" - integrity sha1-gVHTWOIMisx/t0XnRywAJf5JZXA= - etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= -eve@~0.5.1: - version "0.5.4" - resolved "https://registry.yarnpkg.com/eve/-/eve-0.5.4.tgz#67d080b9725291d7e389e34c26860dd97f1debaa" - integrity sha1-Z9CAuXJSkdfjieNMJoYN2X8d66o= - eventemitter3@^4.0.0, eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -8419,6 +8391,13 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +framesync@^4.0.0, framesync@^4.0.1: + version "4.1.0" + resolved "https://registry.npmjs.org/framesync/-/framesync-4.1.0.tgz#69a8db3ca432dc70d6a76ba882684a1497ef068a" + integrity sha512-MmgZ4wCoeVxNbx2xp5hN/zPDCbLSKiDt4BbbslK7j/pM2lg5S0vhTNv1v8BCVb99JPIo6hXBFdwzU7Q4qcAaoQ== + dependencies: + hey-listen "^1.0.5" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -9203,6 +9182,11 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hey-listen@^1.0.5, hey-listen@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" + integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== + highlight.js@^10.1.1, highlight.js@~10.7.0: version "10.7.3" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" @@ -11387,7 +11371,7 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-fn@^3.1.0: +mimic-fn@^3.0.0, mimic-fn@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== @@ -11696,7 +11680,7 @@ nano-css@^5.3.1: stacktrace-js "^2.0.2" stylis "^4.0.6" -nanoid@^3.1.23: +nanoid@^3.1.23, nanoid@^3.1.25: version "3.1.25" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q== @@ -13654,17 +13638,6 @@ rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-burger-menu@^2.7.1: - version "2.9.2" - resolved "https://registry.yarnpkg.com/react-burger-menu/-/react-burger-menu-2.9.2.tgz#7eaa1c040b9543f1de6dd5f8fd237fbff0655f13" - integrity sha512-NOVV0Svjydlo8b/Twd/BQZ7WYr6T5rdVtxTsS7iESFCdQekaK8DIZt78D+qFS4eUjy8q/VQ2H3SLy/xir/NN8Q== - dependencies: - browserify-optional "^1.0.0" - classnames "^2.2.6" - eve "~0.5.1" - prop-types "^15.7.2" - snapsvg-cjs "0.0.6" - react-colorful@^5.1.2: version "5.3.0" resolved "https://registry.yarnpkg.com/react-colorful/-/react-colorful-5.3.0.tgz#bcbae49c1affa9ab9a3c8063398c5948419296bd" @@ -14425,11 +14398,6 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= - resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.3.2, resolve@^1.8.1, resolve@^1.9.0: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" @@ -15066,20 +15034,6 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -snapsvg-cjs@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/snapsvg-cjs/-/snapsvg-cjs-0.0.6.tgz#3b2f56af2573d3d364c3ed5bf8885745f4d2dde1" - integrity sha1-Oy9WryVz09Nkw+1b+IhXRfTS3eE= - dependencies: - snapsvg "0.5.1" - -snapsvg@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/snapsvg/-/snapsvg-0.5.1.tgz#0caf52c79189a290746fc446cc5e863f6bdddfe3" - integrity sha1-DK9Sx5GJopB0b8RGzF6GP2vd3+M= - dependencies: - eve "~0.5.1" - sockjs-client@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.1.tgz#256908f6d5adfb94dabbdbd02c66362cca0f9ea6" @@ -15193,13 +15147,6 @@ source-map@^0.7.3, source-map@~0.7.2: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== -source-map@~0.1.30: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - integrity sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y= - dependencies: - amdefine ">=0.0.4" - sourcemap-codec@^1.4.4, sourcemap-codec@^1.4.8: version "1.4.8" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" @@ -15693,6 +15640,25 @@ style-to-object@0.3.0, style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" +style-value-types@^3.1.7: + version "3.2.0" + resolved "https://registry.npmjs.org/style-value-types/-/style-value-types-3.2.0.tgz#eb89cab1340823fa7876f3e289d29d99c92111bb" + integrity sha512-ih0mGsrYYmVvdDi++/66O6BaQPRPRMQHoZevNNdMMcPlP/cH28Rnfsqf1UEba/Bwfuw9T8BmIMwbGdzsPwQKrQ== + dependencies: + hey-listen "^1.0.8" + tslib "^1.10.0" + +stylefire@^7.0.3: + version "7.0.3" + resolved "https://registry.npmjs.org/stylefire/-/stylefire-7.0.3.tgz#9120ecbb084111788e0ddaa04074799750f20d1d" + integrity sha512-Q0l7NSeFz/OkX+o6/7Zg3VZxSAZeQzQpYomWmIpOehFM/rJNMSLVX5fgg6Q48ut2ETNKwdhm97mPNU643EBCoQ== + dependencies: + "@popmotion/popcorn" "^0.4.4" + framesync "^4.0.0" + hey-listen "^1.0.8" + style-value-types "^3.1.7" + tslib "^1.10.0" + stylis@^4.0.6: version "4.0.10" resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.10.tgz#446512d1097197ab3f02fb3c258358c3f7a14240" @@ -15956,7 +15922,7 @@ through2@^4.0.0: dependencies: readable-stream "3" -"through@>=2.2.7 <3", through@^2.3.8, through@~2.3, through@~2.3.4: +"through@>=2.2.7 <3", through@^2.3.8, through@~2.3: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -16797,6 +16763,11 @@ value-equal@^1.0.1: resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== +vanilla-lazyload@^17.4.0: + version "17.4.0" + resolved "https://registry.npmjs.org/vanilla-lazyload/-/vanilla-lazyload-17.4.0.tgz#09d65a5be46242b82b557b9ccd886613de76f4c2" + integrity sha512-4IVX93uLEgQGBdSCaSE1XJgeNNT1+sV8PKiImM21EkDGJBH3tTWL9wYrMA4xT5C2EIEfw8WkinUxUG+uMY2ZyA== + vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -16848,7 +16819,7 @@ video.js@7.10.2: videojs-font "3.2.0" videojs-vtt.js "^0.15.2" -"video.js@^6 || ^7", video.js@^7.8.4: +video.js@>=7, "video.js@^6 || ^7", video.js@^7.8.4: version "7.14.3" resolved "https://registry.yarnpkg.com/video.js/-/video.js-7.14.3.tgz#0b612c09a0a81ef9bce65c710e73291cb06dc32c" integrity sha512-6avCdSIfn5ss5NOgoQfY/xEfPNcz9DXSw+ZN80NwPguCdRd4VL4y40b/d7osYJwyCdF+YkvhqAW7dw4s0vBigg==