работаем бля работаем

This commit is contained in:
2026-05-09 03:21:44 +06:00
parent f845777bac
commit 0b148c6a7d
169 changed files with 15816 additions and 1005 deletions

View File

@@ -21,7 +21,7 @@
</PrimeAvatar>
<p class="flex-1 text-sm leading-5 font-medium text-color truncate w-0">
{{ client.displayName || client.username }}
{{ client.displayName || client.username || client.socketId }}
</p>
<Component :is="expanded ? ChevronUp : ChevronDown" v-if="!isMe" :size="20" class="text-muted-color" />

View File

@@ -85,7 +85,7 @@ export const useApp = createGlobalState(() => {
await muteInput()
await signaling.socket.value?.emitWithAck('updateClient', {
await signaling.socket.value?.emitWithAck('update-client', {
outputMuted: true,
})
@@ -98,7 +98,7 @@ export const useApp = createGlobalState(() => {
if (!previousInputMuted.value)
await unmuteInput()
await signaling.socket.value?.emitWithAck('updateClient', {
await signaling.socket.value?.emitWithAck('update-client', {
outputMuted: false,
})

View File

@@ -14,7 +14,7 @@ export const useClients = createGlobalState(() => {
if (!socket)
return
socket.on('clientChanged', (clientId: ChadClient['socketId'], updatedClient: UpdatedClient) => {
socket.on('client-updated', (clientId: ChadClient['socketId'], updatedClient: UpdatedClient) => {
const client = getClient(clientId)
if (!client)

View File

@@ -26,15 +26,15 @@ const ICE_SERVERS: RTCIceServer[] = [
]
export const useMediasoup = createSharedComposable(() => {
const { emit } = useEventBus()
const eventBus = useEventBus()
const signaling = useSignaling()
const { addClient, removeClient, me } = useClients()
const { addClient, removeClient, me, clients, updateClient } = useClients()
const preferences = usePreferences()
const { getShareStream } = useDevices()
const device = shallowRef<mediasoupClient.Device>()
const rtpCapabilities = shallowRef<mediasoupClient.types.RtpCapabilities>()
const routerRtpCapabilities = shallowRef<mediasoupClient.types.RtpCapabilities>()
const sendTransport = shallowRef<mediasoupClient.types.Transport>()
const recvTransport = shallowRef<mediasoupClient.types.Transport>()
@@ -79,18 +79,30 @@ export const useMediasoup = createSharedComposable(() => {
if (!socket)
return
socket.on('authenticated', async () => {
socket.on('new-client', (client) => {
addClient(client)
eventBus.emit('client:added', client)
})
socket.on('client-switched-channel', (client) => {
updateClient(client.socketId, client)
})
socket.on('initialized', async (initData) => {
if (!signaling.socket.value)
return
device.value = new mediasoupClient.Device()
rtpCapabilities.value = await signaling.socket.value.emitWithAck('getRtpCapabilities')
routerRtpCapabilities.value = initData.rtpCapabilities
await device.value.load({ routerRtpCapabilities: rtpCapabilities.value! })
clients.value = initData.clients
await device.value.load({ routerRtpCapabilities: routerRtpCapabilities.value! })
// Send transport
{
const transportInfo = await signaling.socket.value.emitWithAck('createTransport', { producing: true, consuming: false })
const transportInfo = await signaling.socket.value.emitWithAck('create-transport', { producing: true, consuming: false })
sendTransport.value = device.value.createSendTransport({
...transportInfo,
iceServers: [
@@ -101,7 +113,7 @@ export const useMediasoup = createSharedComposable(() => {
sendTransport.value.on('connect', async ({ dtlsParameters }, callback, errback) => {
try {
await signaling.socket.value!.emitWithAck('connectTransport', {
await signaling.socket.value!.emitWithAck('connect-transport', {
transportId: sendTransport.value!.id,
dtlsParameters,
})
@@ -135,7 +147,7 @@ export const useMediasoup = createSharedComposable(() => {
// Recv Transport
{
const transportInfo = await signaling.socket.value.emitWithAck('createTransport', { producing: false, consuming: true })
const transportInfo = await signaling.socket.value.emitWithAck('create-transport', { producing: false, consuming: true })
recvTransport.value = device.value.createRecvTransport({
...transportInfo,
iceServers: [
@@ -146,7 +158,7 @@ export const useMediasoup = createSharedComposable(() => {
recvTransport.value.on('connect', async ({ dtlsParameters }, callback, errback) => {
try {
await signaling.socket.value!.emitWithAck('connectTransport', {
await signaling.socket.value!.emitWithAck('connect-transport', {
transportId: recvTransport.value!.id,
dtlsParameters,
})
@@ -160,36 +172,33 @@ export const useMediasoup = createSharedComposable(() => {
}
})
}
//
// const joinedClients = (await signaling.socket.value.emitWithAck('join', {
// rtpCapabilities: routerRtpCapabilities.value,
// }))
//
// addClient(...joinedClients)
//
// if (me.value)
// eventBus.emit('socket:authenticated', { socketId: me.value.socketId })
//
const joinedClients = (await signaling.socket.value.emitWithAck('join', {
rtpCapabilities: rtpCapabilities.value,
}))
addClient(...joinedClients)
if (me.value)
emit('socket:authenticated', { socketId: me.value.socketId })
// TODO: при переподключении проверять inputMuted
await enableMic()
})
socket.on('newPeer', (client) => {
addClient(client)
emit('client:added', client)
})
socket.on('peerClosed', (id) => {
socket.on('client-disconnected', (id) => {
const { getClient } = useClients()
const client = getClient(id)
removeClient(id)
if (client)
emit('client:removed', client)
eventBus.emit('client:removed', client)
})
socket.on(
'newConsumer',
'new-consumer',
async (
{ id, producerId, kind, rtpParameters, socketId, appData, producerPaused },
cb,
@@ -216,18 +225,18 @@ export const useMediasoup = createSharedComposable(() => {
raw: markRaw(consumer),
}
emit('consumer:added', consumers.value[consumer.id]!)
eventBus.emit('consumer:added', consumers.value[consumer.id]!)
consumer.observer.on('resume', () => {
consumers.value[consumer.id]!.paused = false
emit('consumer:resumed', consumers.value[consumer.id]!)
eventBus.emit('consumer:resumed', consumers.value[consumer.id]!)
})
consumer.observer.on('pause', () => {
consumers.value[consumer.id]!.paused = true
emit('consumer:paused', consumers.value[consumer.id]!)
eventBus.emit('consumer:paused', consumers.value[consumer.id]!)
})
consumer.observer.on('close', () => {
@@ -236,7 +245,7 @@ export const useMediasoup = createSharedComposable(() => {
delete consumers.value[consumer.id]
if (consumerData)
emit('consumer:removed', consumerData)
eventBus.emit('consumer:removed', consumerData)
})
consumer.on('trackended', () => {
@@ -248,7 +257,7 @@ export const useMediasoup = createSharedComposable(() => {
)
socket.on(
'consumerClosed',
'consumer-closed',
async (
{ consumerId },
) => {
@@ -261,7 +270,7 @@ export const useMediasoup = createSharedComposable(() => {
},
)
socket.on('consumerPaused', ({ consumerId }) => {
socket.on('consumer-paused', ({ consumerId }) => {
const consumer = consumers.value[consumerId]
if (!consumer)
@@ -270,7 +279,7 @@ export const useMediasoup = createSharedComposable(() => {
consumer.raw.pause()
})
socket.on('consumerResumed', ({ consumerId }) => {
socket.on('consumer-resumed', ({ consumerId }) => {
const consumer = consumers.value[consumerId]
if (!consumer)
@@ -279,13 +288,13 @@ export const useMediasoup = createSharedComposable(() => {
consumer.raw.resume()
})
socket.on('speakingPeers', (value: SpeakingClient[]) => {
socket.on('speaking-clients', (value: SpeakingClient[]) => {
speakingClients.value = value
})
socket.on('disconnect', () => {
device.value = undefined
rtpCapabilities.value = undefined
routerRtpCapabilities.value = undefined
sendTransport.value?.close()
sendTransport.value = undefined
@@ -317,27 +326,28 @@ export const useMediasoup = createSharedComposable(() => {
raw: markRaw(producer),
}
emit('producer:added', producers.value[producer.id]!)
eventBus.emit('producer:added', producers.value[producer.id]!)
producer.observer.on('pause', () => {
producers.value[producer.id]!.paused = true
emit('producer:paused', producers.value[producer.id]!)
eventBus.emit('producer:paused', producers.value[producer.id]!)
})
producer.observer.on('resume', () => {
producers.value[producer.id]!.paused = false
emit('producer:resumed', producers.value[producer.id]!)
eventBus.emit('producer:resumed', producers.value[producer.id]!)
})
producer.observer.on('close', () => {
console.log('producer closed')
const producerData = producers.value[producer.id]
delete producers.value[producer.id]
if (producerData)
emit('producer:removed', producerData)
eventBus.emit('producer:removed', producerData)
})
producer.on('trackended', () => {
@@ -352,7 +362,7 @@ export const useMediasoup = createSharedComposable(() => {
try {
producer.raw.close()
await signaling.socket.value.emitWithAck('closeProducer', {
await signaling.socket.value.emitWithAck('close-producer', {
producerId: producer.id,
})
}
@@ -455,7 +465,7 @@ export const useMediasoup = createSharedComposable(() => {
await createProducer({
track,
streamId: 'share',
codec: device.value.rtpCapabilities.codecs?.find(
codec: device.value.sendRtpCapabilities.codecs?.find(
c => c.mimeType.toLowerCase() === 'video/AV1',
),
codecOptions: {
@@ -478,7 +488,7 @@ export const useMediasoup = createSharedComposable(() => {
try {
producer.raw.pause()
await signaling.socket.value.emitWithAck('pauseProducer', {
await signaling.socket.value.emitWithAck('pause-producer', {
producerId: producer.id,
})
}
@@ -494,7 +504,7 @@ export const useMediasoup = createSharedComposable(() => {
try {
producer.raw.resume()
await signaling.socket.value.emitWithAck('resumeProducer', {
await signaling.socket.value.emitWithAck('resume-producer', {
producerId: producer.id,
})
}
@@ -526,7 +536,7 @@ export const useMediasoup = createSharedComposable(() => {
speakingClients,
sendTransport,
recvTransport,
rtpCapabilities,
rtpCapabilities: routerRtpCapabilities,
device,
micProducer,
videoProducer,
@@ -536,5 +546,7 @@ export const useMediasoup = createSharedComposable(() => {
enableVideo,
enableShare,
disableProducer,
consumersArray,
producersArray,
}
})

View File

@@ -52,11 +52,39 @@
<PrimeScrollPanel class="bg-surface-900 rounded-xl overflow-hidden" style="min-height: 0">
<div v-auto-animate class="p-3 space-y-1">
<ClientRow v-for="client of clients" :key="client.userId" :client="client" />
<template v-for="channel in channels" :key="channel.id">
<PrimeDivider>
<PrimeButton size="small" variant="text" @click="joinChannel(channel)">
{{ channel.name }}
</PrimeButton>
</PrimeDivider>
<ClientRow v-for="client in clients.filter(_client => _client.channelId === channel.id)" :key="client.socketId" :client="client">
{{ client.userId }}
</ClientRow>
</template>
<!-- <ClientRow v-for="client of clients" :key="client.userId" :client="client" /> -->
</div>
</PrimeScrollPanel>
<div class="bg-surface-900 rounded-xl overflow-hidden p-3 flex flex-col min-h-full">
<dl>
<dt>Socket ID</dt>
<dd>{{ socket?.id }}</dd>
<br>
<dt>Producers</dt>
<dd v-for="producer in producersArray" :key="producer.id">
{{ producer.id }}
{{ producer.appData }}
</dd>
<br>
<dl>Consumers</dl>
<dd v-for="consumer in consumersArray" :key="consumer.id">
{{ consumer.id }}
{{ consumer.appData }}
</dd>
</dl>
<slot />
</div>
</div>
@@ -65,6 +93,7 @@
</template>
<script setup lang="ts">
import chadApi from '#shared/chad-api'
import {
Camera,
CameraOff,
@@ -80,6 +109,13 @@ import {
VolumeOff,
} from 'lucide-vue-next'
const channels = shallowRef<any[]>([])
;(async () => {
channels.value = await chadApi<any[]>('/channels', { method: 'GET' })
})()
const { me } = useClients()
const {
version,
clients,
@@ -93,7 +129,8 @@ const {
toggleVideo,
toggleShare,
} = useApp()
const { connect, connected } = useSignaling()
const { connect, connected, socket } = useSignaling()
const { consumersArray, producersArray } = useMediasoup()
interface Tab {
id: string
@@ -150,4 +187,30 @@ watch(activeTab, (activeTab) => {
})
connect()
async function joinChannel(channel) {
socket.value?.emit('join-channel', { channelId: channel.id })
}
watch(socket, (socket) => {
if (!socket)
return
socket.on('channel-removed', (channelId) => {
const idx = channels.value.findIndex(channel => channel.id === channelId)
if (idx === -1)
return
channels.value.splice(idx, 1)
triggerRef(channels)
})
socket.on('channel-created', (channel) => {
channels.value.push(channel)
triggerRef(channels)
})
}, { immediate: true })
</script>