diff --git a/client/app/components.d.ts b/client/app/components.d.ts index 134d7b9..88eb6f6 100644 --- a/client/app/components.d.ts +++ b/client/app/components.d.ts @@ -17,6 +17,7 @@ declare module 'vue' { PrimeFloatLabel: typeof import('primevue/floatlabel')['default'] PrimeInputText: typeof import('primevue/inputtext')['default'] PrimePassword: typeof import('primevue/password')['default'] + PrimeProgressBar: typeof import('primevue/progressbar')['default'] PrimeScrollPanel: typeof import('primevue/scrollpanel')['default'] PrimeSelect: typeof import('primevue/select')['default'] PrimeSelectButton: typeof import('primevue/selectbutton')['default'] diff --git a/client/app/components/ClientRow.vue b/client/app/components/ClientRow.vue index 620393f..f7c5f4c 100644 --- a/client/app/components/ClientRow.vue +++ b/client/app/components/ClientRow.vue @@ -7,7 +7,12 @@ }" >
- + @@ -61,7 +66,7 @@ const props = defineProps<{ }>() const { outputMuted } = useApp() -const { consumers: allConsumers, micProducer } = useMediasoup() +const { consumers: allConsumers, micProducer, speakingClients } = useMediasoup() const { me } = useClients() const { show } = useFullscreenVideo() @@ -94,6 +99,10 @@ const audioTrack = computed(() => { return audioConsumer.value?.track }) +const speaking = computed(() => { + return speakingClients.value.find(speaker => speaker.clientId === props.client.socketId) +}) + const audioConsumerPaused = ref(false) const inputMuted = computed(() => { diff --git a/client/app/composables/use-mediasoup.ts b/client/app/composables/use-mediasoup.ts index d11e615..8314ee9 100644 --- a/client/app/composables/use-mediasoup.ts +++ b/client/app/composables/use-mediasoup.ts @@ -1,6 +1,8 @@ +import type { SpeakingClient } from '#shared/types' import type { MediaKind, ProducerOptions } from 'mediasoup-client/types' import { createSharedComposable } from '@vueuse/core' import * as mediasoupClient from 'mediasoup-client' +import { shallowRef } from 'vue' import { useDevices } from '~/composables/use-devices' import { usePreferences } from '~/composables/use-preferences' import { useSignaling } from '~/composables/use-signaling' @@ -40,6 +42,8 @@ export const useMediasoup = createSharedComposable(() => { const consumers = shallowRef>(new Map()) const producers = shallowRef>(new Map()) + const speakingClients = shallowRef([]) + watch(signaling.socket, (socket) => { if (!socket) return @@ -227,6 +231,10 @@ export const useMediasoup = createSharedComposable(() => { triggerRef(consumers) }) + + socket.on('speakingPeers', (value: SpeakingClient[]) => { + speakingClients.value = value + }) }, { immediate: true, flush: 'sync' }) async function enableProducer(type: ProducerType, options: ProducerOptions) { @@ -424,6 +432,7 @@ export const useMediasoup = createSharedComposable(() => { init, consumers, producers, + speakingClients, sendTransport, recvTransport, rtpCapabilities, diff --git a/client/shared/types.ts b/client/shared/types.ts index 515bda1..6aec3e8 100644 --- a/client/shared/types.ts +++ b/client/shared/types.ts @@ -8,3 +8,8 @@ export interface ChadClient { } export type UpdatedClient = Omit + +export interface SpeakingClient { + clientId: ChadClient['socketId'] + volume: number +} diff --git a/client/src-tauri/tauri.conf.json b/client/src-tauri/tauri.conf.json index 4b2a4e2..595db15 100644 --- a/client/src-tauri/tauri.conf.json +++ b/client/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "productName": "chad", - "version": "0.2.19", + "version": "0.2.20", "identifier": "xyz.koptilnya.chad", "build": { "frontendDist": "../.output/public",