Skip to content
Snippets Groups Projects
room.js 3.62 KiB
Newer Older
  • Learn to ignore specific revisions
  • import uuidv4 from "uuid/v4"
    import yArray from "y-array"
    import yMap from "y-map"
    import yMemory from "y-memory"
    import Y from "yjs"
    
    import yWebrtc from "./y-webrtc/index.js"
    
    yMemory(Y)
    yMap(Y)
    yArray(Y)
    yWebrtc(Y)
    
    class Room extends EventTarget {
      constructor(name) {
        super()
        this.name = name
        this._y = null
        this.ownID = null
      }
    
    
    Giovanni Caruso's avatar
    Giovanni Caruso committed
      addPath([x, y, w, colour]) {
    
        const id = uuidv4()
    
    Giovanni Caruso's avatar
    Giovanni Caruso committed
        this._y.share.strokeAdd.set(id, Y.Array).push([[x, y, w, colour]])
    
        return id
      }
    
    
    Giovanni Caruso's avatar
    Giovanni Caruso committed
      extendPath(id, [x, y, w, colour]) {
        this._y.share.strokeAdd.get(id).push([[x, y, w, colour]])
    
    Nayeem Rahman's avatar
    Nayeem Rahman committed
        const paths = new Map()
    
    Nayeem Rahman's avatar
    Nayeem Rahman committed
        for (const id of this._y.share.strokeAdd.keys()) {
    
          paths.set(id, this._generatePath(id))
        }
    
        return paths
      }
    
      erasePoint(id, idx) {
        let eraseSet = this._y.share.strokeErase.get(id)
    
        if (!eraseSet) {
          eraseSet = this._y.share.strokeErase.set(id, Y.Map)
        }
    
        eraseSet.set(idx.toString(), true)
      }
    
      // Generate an array of points [x, y, exist] by merging the path's add and erase sets
      _generatePath(id) {
    
    Nayeem Rahman's avatar
    Nayeem Rahman committed
        const addSet = this._y.share.strokeAdd.get(id)
    
    Nayeem Rahman's avatar
    Nayeem Rahman committed
        const eraseSet = this._y.share.strokeErase.get(id) || { get: () => false }
    
    Giovanni Caruso's avatar
    Giovanni Caruso committed
          .map((p = [], i) => [p[0], p[1], p[2], p[3], !eraseSet.get(i.toString())])
    
      }
    
      inviteUser(id) {
        this._y.connector.connectToPeer(id)
      }
    
      async _initialise() {
        this._y = await Y({
          db: {
            name: "memory",
          },
          connector: {
            name: "webrtc",
            url: "/",
            room: this.name,
            onUserEvent: (event) => {
              if (event.action == "userID") {
                const { id } = event
                this.ownID = id
                this.dispatchEvent(new CustomEvent("allocateOwnID", { detail: id }))
              } else if (event.action == "userJoined") {
                const { user: id } = event
                this.dispatchEvent(new CustomEvent("userJoin", { detail: id }))
              } else if (event.action == "userLeft") {
                const { user: id } = event
                this.dispatchEvent(new CustomEvent("userLeave", { detail: id }))
              }
            },
          },
          share: {
    
            strokeAdd: "Map",
            strokeErase: "Map",
    
        this._y.share.strokeAdd.observe((lineEvent) => {
    
          if (lineEvent.type == "add") {
    
            const points = this._generatePath(lineEvent.name)
    
            const detail = { id: lineEvent.name, points }
            this.dispatchEvent(new CustomEvent("addOrUpdatePath", { detail }))
            lineEvent.value.observe((pointEvent) => {
              if (pointEvent.type == "insert") {
    
                const points = this._generatePath(lineEvent.name)
                const detail = { id: lineEvent.name, points }
                this.dispatchEvent(new CustomEvent("addOrUpdatePath", { detail }))
              }
            })
          }
        })
        this._y.share.strokeErase.observe((lineEvent) => {
          if (lineEvent.type == "add") {
            const points = this._generatePath(lineEvent.name)
            const detail = { id: lineEvent.name, points }
            this.dispatchEvent(new CustomEvent("addOrUpdatePath", { detail }))
            lineEvent.value.observe((pointEvent) => {
              if (pointEvent.type == "add") {
                const points = this._generatePath(lineEvent.name)
    
                const detail = { id: lineEvent.name, points }
                this.dispatchEvent(new CustomEvent("addOrUpdatePath", { detail }))
              }
            })
          }
        })
      }
    }
    
    export const connect = async (roomName) => {
      const room = new Room(roomName)
      await room._initialise()
      return room
    }