front update
All checks were successful
Deploy / deploy (push) Successful in 38s

This commit is contained in:
Никита Круглицкий
2025-10-09 06:14:35 +06:00
parent fc43c8df96
commit e2064dba6c
11 changed files with 122 additions and 22 deletions

View File

@@ -1,12 +1,17 @@
import { createGlobalState } from '@vueuse/core'
import { useClients } from '~/composables/use-clients'
export const useApp = createGlobalState(() => {
const { clients } = useClients()
const mediasoup = useMediasoup()
const toast = useToast()
const inputMuted = ref(false)
const outputMuted = ref(false)
const me = computed(() => mediasoup.clients.value.find(client => client.isMe))
const previousInputMuted = ref(inputMuted.value)
const me = computed(() => clients.value.find(client => client.isMe))
function muteInput() {
inputMuted.value = true
@@ -38,15 +43,36 @@ export const useApp = createGlobalState(() => {
muteOutput()
}
watch(inputMuted, async (state) => {
if (state)
watch(inputMuted, async (inputMuted) => {
if (inputMuted) {
await mediasoup.muteMic()
else
}
else {
if (outputMuted.value) {
outputMuted.value = false
}
await mediasoup.unmuteMic()
}
const toastText = inputMuted ? 'Microphone muted' : 'Microphone activated'
toast.add({ severity: 'info', summary: toastText, closable: false, life: 1000 })
})
watch(outputMuted, (outputMuted) => {
if (outputMuted) {
previousInputMuted.value = inputMuted.value
muteInput()
}
else {
inputMuted.value = previousInputMuted.value
}
const toastText = outputMuted ? 'Sound muted' : 'Sound resumed'
toast.add({ severity: 'info', summary: toastText, closable: false, life: 1000 })
})
return {
clients: mediasoup.clients,
clients,
me,
inputMuted,
muteInput,

View File

@@ -0,0 +1,58 @@
import type { ChadClient, UpdatedClient } from '#shared/types'
import { createGlobalState } from '@vueuse/core'
export const useClients = createGlobalState(() => {
const signaling = useSignaling()
const toast = useToast()
const clients = shallowRef<ChadClient[]>([])
watch(signaling.socket, (socket) => {
if (!socket)
return
socket.on('clientChanged', (clientId: ChadClient['id'], updatedClient: UpdatedClient) => {
const client = getClient(clientId)
updateClient(clientId, updatedClient)
if (updatedClient.username)
toast.add({ severity: 'info', summary: `${client?.username} is now ${updatedClient.username}`, closable: false, life: 1000 })
})
})
function getClient(clientId: ChadClient['id']) {
return clients.value.find(client => client.id === clientId)
}
function addClient(...client: ChadClient[]) {
clients.value.push(...client)
triggerRef(clients)
}
function removeClient(clientId: ChadClient['id']) {
clients.value = clients.value.filter(client => client.id !== clientId)
}
function updateClient(clientId: ChadClient['id'], updatedClient: UpdatedClient) {
const clientIdx = clients.value.findIndex(client => client.id === clientId)
if (clientIdx === -1)
return
clients.value[clientIdx] = {
...clients.value[clientIdx],
...updatedClient,
} as ChadClient
triggerRef(clients)
}
return {
clients,
getClient,
addClient,
removeClient,
updateClient,
}
})

View File

@@ -18,8 +18,11 @@ const ICE_SERVERS: RTCIceServer[] = [
]
export const useMediasoup = createSharedComposable(() => {
const preferences = usePreferences()
const toast = useToast()
const signaling = useSignaling()
const { addClient, removeClient } = useClients()
const preferences = usePreferences()
const device = shallowRef<mediasoupClient.Device>()
const rtpCapabilities = shallowRef<mediasoupClient.types.RtpCapabilities>()
@@ -30,8 +33,6 @@ export const useMediasoup = createSharedComposable(() => {
const webcamProducer = shallowRef<mediasoupClient.types.Producer>()
const shareProducer = shallowRef<mediasoupClient.types.Producer>()
const clients = shallowRef<ChadClient[]>([])
const consumers = shallowRef<Map<string, mediasoupClient.types.Consumer>>(new Map())
const producers = shallowRef<Map<string, mediasoupClient.types.Producer>>(new Map())
@@ -121,21 +122,24 @@ export const useMediasoup = createSharedComposable(() => {
})
}
clients.value = (await signaling.socket.value.emitWithAck('join', {
const joinedClients = (await signaling.socket.value.emitWithAck('join', {
username: preferences.username.value,
rtpCapabilities: rtpCapabilities.value,
})).map(transformClient)
addClient(...joinedClients)
toast.add({ severity: 'success', summary: 'Joined', closable: false, life: 1000 })
await enableMic()
})
socket.on('newPeer', (client) => {
clients.value.push(transformClient(client))
triggerRef(clients)
addClient(transformClient(client))
})
socket.on('peerClosed', (id) => {
clients.value = clients.value.filter(client => client.id !== id)
removeClient(id)
})
socket.on(
@@ -317,7 +321,6 @@ export const useMediasoup = createSharedComposable(() => {
return {
init,
clients,
consumers,
producers,
sendTransport,

View File

@@ -3,6 +3,8 @@ import { createSharedComposable } from '@vueuse/core'
import { io } from 'socket.io-client'
export const useSignaling = createSharedComposable(() => {
const toast = useToast()
const socket = shallowRef<Socket>()
const connected = ref(false)
@@ -35,6 +37,13 @@ export const useSignaling = createSharedComposable(() => {
})
}, { immediate: true, flush: 'sync' })
watch(connected, (connected) => {
if (connected)
toast.add({ severity: 'success', summary: 'Connected', closable: false, life: 1000 })
else
toast.add({ severity: 'error', summary: 'Disconnected', closable: false, life: 1000 })
}, { immediate: true })
onScopeDispose(() => {
socket.value?.close()
})