Skip to content

An open sourced whiteboard starter based on white-web-sdk.

License

Notifications You must be signed in to change notification settings

Cambly/fastboard

 
 

Repository files navigation

@netless/fastboard

Docs | Sandbox | 中文

A starter library for making whiteboard web app, based on white-web-sdk, @netless/window-manager and netless-app.

Table of Contents

Install

npm add @netless/fastboard @netless/window-manager white-web-sdk

Note: @netless/window-manager and white-web-sdk are peerDependencies.

Usage

Vanilla JavaScript

import { createFastboard, createUI } from "@netless/fastboard";

async function main() {
  const fastboard = await createFastboard({
    // [1]
    sdkConfig: {
      appIdentifier: "whiteboard-appid",
      region: "us-sv", // "cn-hz" | "us-sv" | "sg" | "in-mum" | "eu"
    },
    // [2]
    joinRoom: {
      uid: "unique_id_for_each_client",
      uuid: "room-uuid",
      roomToken: "NETLESSROOM_...",
      // (optional)
      userPayload: {
        nickName: "foo",
      },
    },
    // [3] (optional)
    managerConfig: {
      cursor: true,
    },
    // [4] (optional)
    netlessApps: [],
  });

  const container = createContainer();

  const ui = createUI(fastboard, container);

  // .....

  // destroy Fastboard UI
  ui.destroy();

  // .....

  // destroy Fastboard (disconnect from the whiteboard room)
  fastboard.destroy();
}

function createContainer() {
  const container = document.createElement("div");
  // Must give it a visible size
  Object.assign(container.style, {
    height: "400px",
    border: "1px solid",
    background: "#f1f2f3",
  });
  document.body.appendChild(container);
  return container;
}

main().catch(console.error);

[1] Read more about the SDK config at Construct WhiteWebSDK object
[2] Read more about join room config at Construct Room and Player objects
[3] Read more about WindowManager config at WindowManager.mount()

React

Install @netless/fastboard-react, use the <Fastboard /> component.

npm add @netless/fastboard-react @netless/window-manager white-web-sdk react react-dom
import { useFastboard, Fastboard } from "@netless/fastboard-react";
import React from "react";
import { createRoot } from "react-dom/client";

function App() {
  const fastboard = useFastboard(() => ({
    sdkConfig: {
      appIdentifier: "whiteboard-appid",
      region: "us-sv", // "cn-hz" | "us-sv" | "sg" | "in-mum" | "eu"
    },
    joinRoom: {
      uid: "unique_id_for_each_client",
      uuid: "room-uuid",
      roomToken: "NETLESSROOM_...",
    },
  }));

  // Container must have a visible size
  return (
    <div
      style={{
        height: "400px",
        border: "1px solid",
        background: "#f1f2f3",
      }}
    >
      <Fastboard app={fastboard} />
    </div>
  );
}

createRoot(document.getElementById("app")).render(<App />);

Whiteboard Functions

Insert Picture

await fastboard.insertImage(fileUrl);

The fileUrl is the url to load the image file, like "src" in <img src>. Fastboard itself does not contain any logic about upload/save a file.

Redo & Undo

fastboard.undo();
fastboard.redo();

Move Camera

fastboard.moveCamera({ centerX: 0, centerY: 0, scale: 1 });
fastboard.moveCameraToContain({ originX: -300, originY: -200, width: 600, height: 400 });

Set Tool

fastboard.setAppliance("pencil");
fastboard.setAppliance("shape", "triangle");
fastboard.setStrokeWidth(2);
fastboard.setStrokeColor([r, g, b]);

Netless Apps

Register & Insert Apps

Except for built-in apps in Fastboard, you can also insert your own apps. To do that, You have to register app at each client before entering room (createFastboard):

import { register } from "@netless/fastboard";
import MyApp from "my-app";

register({ kind: MyApp.kind, src: MyApp });

Or you can set netlessApps in createFastboard config:

createFastboard({
  ..., // other config
  netlessApps: [MyApp],
});

Then add app into the room via:

fastboard.manager.addApp({ kind: MyApp.kind });

Read more about Netless Apps.

Insert PDF, PPT and PPTX

// insert PDF/PPT/PPTX to the main whiteboard
const appId = await fastboard.insertDocs("filename.pptx", conversionResponse);

The conversionResponse is the result of this api.

Note: If you're using the new projector api, there's another way:

const appId1 = await fastboard.insertDocs({
  fileType: "pdf",
  scenePath: `/pdf/${response.uuid}`,
  scenes: [
    { name: "1", ppt: { width: 714, height: 1010, src: images[1].url } },
    { name: "2", ppt: { width: 714, height: 1010, src: images[2].url } },
  ],
  title: "filename.pdf",
});

const appId2 = await fastboard.insertDocs({
  fileType: "pptx",
  scenePath: `/pptx/${response.uuid}`,
  taskId: response.uuid,
  title: "filename.pptx",
  // "https://convertcdn.netless.link/dynamicConvert" by default
  url: response.prefix,
});

Control the PDF/PPTX Apps

import { dispatchDocsEvent } from "@netless/fastboard";

dispatchDocsEvent(fastboard, "nextPage"); // prevPage, nextStep, prevStep
dispatchDocsEvent(fastboard, "jumpToPage", { page: 2 });

By default it will dispatch event to the focused PDF/PPTX app, you can also specify the appId:

dispatchDocsEvent(fastboard, "nextPage", { appId });

Set PPTX Render Options

import { register, SlideApp, addSlideHooks } from "@netless/fastboard";

register({
  kind: SlideApp.kind,
  src: SlideApp,
  appOptions: {
    // ... your slide options here
    // Note: import type {SlideOptions} to get type hints
  },
  addHooks: addSlideHooks,
});

Read more about these options.

Insert Video & Audio

const appId = await fastboard.insertMedia("filename.mp3", fileUrl);

The fileUrl is the url to load the media file, like "src" in <video src>. Fastboard itself does not contain any logic about upload/save a file.

const appId = await fastboard.manager.addApp({
  kind: "Monaco",
  options: { title: "Code Editor" },
});
const appId = await fastboard.manager.addApp({
  kind: "Countdown",
  options: { title: "Countdown" },
});
const appId = await fastboard.manager.addApp({
  kind: "GeoGebra",
  options: { title: "GeoGebra" },
});
const appId = await fastboard.manager.addApp({
  kind: "Plyr",
  options: { title: "YouTube" },
  attributes: {
    src: "https://www.youtube.com/embed/bTqVqk7FSmY",
    provider: "youtube",
  },
});
const appId = await fastboard.manager.addApp({
  kind: "EmbeddedPage",
  options: { title: "Google Docs" },
  attributes: {
    src: "https://docs.google.com/document/d/1bd4SRb5BmTUjPGrFxU2V7KI2g_mQ-HQUBxKTxsEn5e4/edit?usp=sharing",
  },
});

Note: EmbeddedPage uses <iframe> to display external web resources, you'd better not embedding 2 more nested iframes (i.e. webpage>iframe1>iframe2) in the same page.

More apps goto netless-app.

Customization

Fastboard isn't that customizable due to its fast design goal. You may find it hard to add buttons to the toolbar or move the toolbar to another place. In which case, you can hide the unwanted parts and write your own:

// vanilla js
const ui = createUI(fastboard, container);
ui.update({ config: { toolbar: { enable: false } } });

// react
return (
  <>
    <Fastboard app={fastboard} config={{ toolbar: { enable: false } }} />
    <YourOwnUIComponent />
  </>
);

Then refer to the doc: Write Your Own UI (for Fastboard).

License

MIT @ netless

About

An open sourced whiteboard starter based on white-web-sdk.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 48.6%
  • Svelte 38.9%
  • SCSS 8.0%
  • JavaScript 3.7%
  • HTML 0.8%