WindowManager is a window management system based on white-web-sdk InvisiblePlugin implementation.
This application provides the following.
- provides NetlessAppplug-inAPIsystem
- support APPto open as a window
- support application synchronization in each end
- cursor synchronization
- view angle following
- Install
- QuickStart
- concept
- references
- migration from whiteboard
- replay
- advanced use
- Develop custom APP
- Export PDF
pnpm
$ pnpm install @netless/window-manageryarn
$ yarn install @netless/window-managerimport { White-WebSdk } from "white-web-sdk";
import { WindowManager, BuiltinApps } from "@netless/window-manager";
import "@netless/window-manager/dist/style.css";
const sdk = new WhiteWebSdk({
    appIdentifier: "appIdentifier",
    useMobXState: true // make sure this option is turned on
});
sdk.joinRoom({
    uuid: "room uuid",
    roomToken: "room token",
    invisiblePlugins: [WindowManager],
    useMultiViews: true, // Multi-window must be enabled with useMultiViews
    disableMagixEventDispatchLimit: true, // Make sure this option is turned on
}).then(async room => {
    const manager = await WindowManager.mount(
        room,
        container
        // See below for full configuration
    );
});
containerSizeRatioIn order to ensure that the window is displayed at different resolutions, the whiteboard can only be synchronized in the same scale area
MainView, the main whiteboard, is the main whiteboard that sits underneath all windows.
Because of the multiple windows, we abstracted out a main whiteboard, and migrated some of the previous operations on room to mainView operations
collectoris the icon when the window is minimized, default sizewidth: 40px;height: 40px;
The original
cursorAdapterinSDKis not available in multi-window, if you need cursor synchronization, you need to enablecursoroption inmanager.
sdk.joinRoom({
    // cursorAdapter: cursorAdapter, the original cursorAdapter in sdk needs to be turned off
    userPayload: {
        nickName: "cursor name",
        avatar: "User avatar link",
    },
});
WindowManager.mount({
    cursor: true, // turn on cursor synchronization
});Static and dynamic PPTs are inserted into the whiteboard as App, and persisted to the whiteboard
App may be created automatically when the page is refreshed, no need to insert it repeatedly
If the App requires a scenePath, then a scenePath can only be opened at the same time, requiring a unique App instance
const appId = await manager.addApp({
    kind: BuiltinApps.DocsViewer,
    options: {
        scenePath: "/docs-viewer",
        title: "docs1", // optional
        scenes: [], // SceneDefinition[] Static/Dynamic Scene data
    },
});const appId = await manager.addApp({
    kind: BuiltinApps.MediaPlayer,
    options: {
        title: "test.mp3", // optional
    },
    attributes: {
        src: "xxxx", // audio/video url
    },
});Only the broadcast side, i.e. the teacher, needs to set the follow mode, the other side of the main whiteboard will follow the view of the broadcast side
Note that
manager'ssetViewModecannot be used at the same time asroom.setViewMode.
manager.setViewMode("broadcaster"); // turn on follow mode
manager.setViewMode("freedom"); // turn off follow modeGet the current broadcaster ID
manager.broadcastermanager.setReadonly(true); // all windows become readonly
manager.setReadonly(false); // unlock the readonly setting, note that if the current whiteboard isWritable is false, the whiteboard's state is the highest prioritymanager.switchMainViewToWriter();Switch the ScenePath of the main whiteboard and set the main whiteboard to writable state
manager.setMainViewScenePath(scenePath);Toggles the SceneIndex of the main whiteboard and sets the main whiteboard to writable state
manager.setMainViewSceneIndex(sceneIndex);manager.getMainViewScenePath();manager.getMainViewSceneIndex();manager.emitter.on("mainViewModeChange", mode => {
    // mode type is ViewVisionMode
});manager.emitter.on("boxStateChange", state => {
    if (state === "maximized") {
        // maximize
    }
    if (state === "minimized") {
        // minimized
    }
    if (state === "normal") {
        // return to normal
    }
});manager.emitter.on("broadcastChange", id => {
    // broadcast id changed
})manager.closeApp(appId);manager.destroy();pnpm install
pnpm build
cd example
pnpm install
pnpm dev