import type { Consumer, Device, Producer, Transport } from 'mediasoup-client/types' import type { Ref } from 'vue' import { createEventHook, createGlobalState } from '@vueuse/core' import { computed, ref, shallowRef } from 'vue' interface Snapshot { id: string ref: T [key: string]: any } export interface ProducerSnapshot extends Snapshot { paused: boolean kind: string appData: Record } export interface ConsumerSnapshot extends Snapshot { paused: boolean kind: string appData: Record track: MediaStreamTrack } export interface TransportSnapshot extends Snapshot { } function createEntityStore() { const store = ref(new Map()) as unknown as Ref> const onAddEvent = createEventHook() const onRemoveEvent = createEventHook() const values = computed(() => Array.from(store.value.values())) async function add(entity: T) { store.value.set(entity.id, entity) // eslint-disable-next-line ts/ban-ts-comment // @ts-expect-error await onAddEvent.trigger(entity) } async function remove(id: string) { store.value.delete(id) await onRemoveEvent.trigger(id) } function get(id: string) { return store.value.get(id) } function clear() { store.value.clear() } return { store, values, onAdd: onAddEvent.on, onRemove: onRemoveEvent.on, add, remove, get, clear, } } export const useMediasoup = createGlobalState(() => { const device = shallowRef() const sendTransport = shallowRef() const recvTransport = shallowRef() const producers = createEntityStore() producers.onAdd((producer) => { producer.ref.observer.on('pause', () => { producers.store.value.set(producer.id, { ...producer, paused: true }) }) producer.ref.observer.on('resume', () => { producers.store.value.set(producer.id, { ...producer, paused: false }) }) producer.ref.observer.on('close', () => producers.remove(producer.id)) }) const consumers = createEntityStore() consumers.onAdd((consumer) => { consumer.ref.on('trackended', () => consumer.ref.close()) consumer.ref.observer.on('pause', () => { consumers.store.value.set(consumer.id, { ...consumer, paused: true }) }) consumer.ref.observer.on('resume', () => { consumers.store.value.set(consumer.id, { ...consumer, paused: false }) }) consumer.ref.observer.on('close', () => consumers.remove(consumer.id)) }) const transports = createEntityStore() transports.onAdd((transport) => { transport.ref.observer.on('close', () => transports.remove(transport.id)) }) function clearAll() { device.value = undefined sendTransport.value = undefined recvTransport.value = undefined producers.clear() consumers.clear() transports.clear() } return { device, sendTransport, recvTransport, producers, consumers, transports, clearAll, } })