kodadot/nft-gallery

View on GitHub
composables/party/useParty.ts

Summary

Maintainability
A
0 mins
Test Coverage
import PartySocket from 'partysocket'

type UsePartyParams<T> = {
  room: Ref<string>
  onMessage?: (value: T) => void
  disabled?: ComputedRef<boolean>
}

const PARTY_SOCKET_HOST = 'https://partykit.kodadot.workers.dev/'
const wss = ref(new Map<string, PartySocket>())

export default <T>({ room, onMessage, disabled }: UsePartyParams<T>) => {
  const { accountId } = useAuth()

  const connect = (room: string) => {
    console.log(`[PARTY::CONNECTION] Establishing connection with room ${room}`)

    if (wss.value.has(room)) {
      console.log(
        `[PARTY::CONNECTION] Connection with room ${room} already established ✅`,
      )
      attachMessageListener(wss.value.get(room) as PartySocket)
      return
    }

    const ws = new PartySocket({
      host: PARTY_SOCKET_HOST,
      room: room,
      id: accountId.value,
    })

    ws.addEventListener('open', () => {
      console.log('[PARTY::CONNECTION] Connection established 🎉')
    })

    ws.addEventListener('error', (error) => {
      console.log(
        `[PARTY::CONNECTION] Connection with room ${room} failed ❗️`,
        error,
      )
    })

    attachMessageListener(ws)

    wss.value.set(room, ws)
  }

  const attachMessageListener = (ws: PartySocket) => {
    ws.addEventListener('message', (event) => {
      const data = JSON.parse(event.data)
      if (onMessage) {
        onMessage(data)
      }
    })
  }

  const sendMessage = (value: any) => {
    wss.value.get(room.value)?.send(JSON.stringify(value))
  }

  const closeConnection = (room: string) => {
    const ws = wss.value.get(room) as PartySocket

    if (!ws) {
      return
    }

    console.log(`[PARTY::CONNECTION] Closing connection with room ${room}`)
    ws.close()
    wss.value.delete(room)
  }

  const closeAllCollections = () => {
    for (const [room] of wss.value) {
      closeConnection(room)
    }
  }

  watch(
    room,
    (value) => {
      if (value && !disabled?.value) {
        connect(value)
      }
    },
    { immediate: true },
  )

  watch(
    () => disabled?.value,
    (disabled) => {
      if (disabled) {
        closeConnection(room.value)
      }
    },
  )

  onBeforeUnmount(closeAllCollections)

  return { sendMessage }
}