diff --git a/client/Dockerfile.web b/client/Dockerfile.web index dd9b8ce..f7dfb55 100644 --- a/client/Dockerfile.web +++ b/client/Dockerfile.web @@ -2,9 +2,6 @@ FROM node:lts-alpine AS builder WORKDIR /app -RUN corepack enable -RUN yarn set version stable - COPY package.json yarn.lock .yarnrc.yml ./ COPY .yarn ./.yarn diff --git a/client/Dockerfile.windows b/client/Dockerfile.windows index 545218f..767ee1b 100644 --- a/client/Dockerfile.windows +++ b/client/Dockerfile.windows @@ -3,8 +3,6 @@ FROM node:lts AS builder WORKDIR /app -# RUN corepack enable yarn && yarn set version stable - COPY package.json yarn.lock .yarnrc.yml ./ COPY .yarn ./.yarn diff --git a/client/app/assets/styles/main.scss b/client/app/assets/styles/main.scss index 4303838..88d79fe 100644 --- a/client/app/assets/styles/main.scss +++ b/client/app/assets/styles/main.scss @@ -27,4 +27,21 @@ body { .p-scrollpanel-bar-y { translate: -0.25rem; +} + +.p-select-overlay { + /* Force dropdown width to match computed min-width from PrimeVue internals. */ + width: 0; +} + +.p-select-label { + width: 0; + overflow: hidden; + text-overflow: ellipsis; +} + +.p-select-option-label { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; } \ No newline at end of file diff --git a/client/app/components.d.ts b/client/app/components.d.ts index 4f8d51a..6e56067 100644 --- a/client/app/components.d.ts +++ b/client/app/components.d.ts @@ -28,4 +28,7 @@ declare module 'vue' { RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] } + export interface ComponentCustomProperties { + Tooltip: typeof import('primevue/tooltip')['default'] + } } diff --git a/client/app/components/ClientRow.vue b/client/app/components/ClientRow.vue index b1a0aaa..29df9b0 100644 --- a/client/app/components/ClientRow.vue +++ b/client/app/components/ClientRow.vue @@ -1,107 +1,129 @@ diff --git a/client/app/components/CollapseTransition.vue b/client/app/components/CollapseTransition.vue new file mode 100644 index 0000000..69ee217 --- /dev/null +++ b/client/app/components/CollapseTransition.vue @@ -0,0 +1,118 @@ + + + + + diff --git a/client/app/composables/use-app.ts b/client/app/composables/use-app.ts index cf27930..b59c15d 100644 --- a/client/app/composables/use-app.ts +++ b/client/app/composables/use-app.ts @@ -65,7 +65,7 @@ export const useApp = createGlobalState(() => { await muteInput() await signaling.socket.value?.emitWithAck('updateClient', { - outputMuted: false, + outputMuted: true, }) toast.add({ severity: 'info', summary: 'Sound muted', closable: false, life: 1000 }) diff --git a/client/app/composables/use-fullscreen-video.ts b/client/app/composables/use-fullscreen-video.ts new file mode 100644 index 0000000..61182ad --- /dev/null +++ b/client/app/composables/use-fullscreen-video.ts @@ -0,0 +1,51 @@ +import { createGlobalState, useEventListener } from '@vueuse/core' + +export const useFullscreenVideo = createGlobalState(() => { + const videoEl = shallowRef() + + const visible = computed(() => !!videoEl.value) + + async function show(stream: MediaStream) { + if (videoEl.value) { + videoEl.value.srcObject = stream + } + else { + const el = document.createElement('video') + el.srcObject = stream + el.autoplay = true + el.playsInline = true + el.controls = false + el.muted = true + // el.style.position = 'fixed' + // el.style.top = '0' + // el.style.left = '0' + // el.style.width = '1px' + // el.style.height = '1px' + // el.style.opacity = '0' + // el.style.pointerEvents = 'none' + + document.body.appendChild(el) + + videoEl.value = el + } + + await videoEl.value.requestFullscreen() + } + + function hide() { + videoEl.value?.remove() + } + + useEventListener(document, 'fullscreenchange', () => { + if (!document.fullscreenElement && videoEl.value) { + videoEl.value?.remove() + videoEl.value = undefined + } + }) + + return { + visible, + show, + hide, + } +}) diff --git a/client/app/composables/use-mediasoup.ts b/client/app/composables/use-mediasoup.ts index eaf67b6..90f58c3 100644 --- a/client/app/composables/use-mediasoup.ts +++ b/client/app/composables/use-mediasoup.ts @@ -1,7 +1,7 @@ -import type { ChadClient } from '#shared/types' import type { MediaKind, ProducerOptions } from 'mediasoup-client/types' import { createSharedComposable } from '@vueuse/core' import * as mediasoupClient from 'mediasoup-client' +import { useDevices } from '~/composables/use-devices' import { usePreferences } from '~/composables/use-preferences' import { useSignaling } from '~/composables/use-signaling' @@ -26,6 +26,7 @@ export const useMediasoup = createSharedComposable(() => { const signaling = useSignaling() const { addClient, removeClient } = useClients() const preferences = usePreferences() + const { getShareStream } = useDevices() const device = shallowRef() const rtpCapabilities = shallowRef() @@ -213,8 +214,6 @@ export const useMediasoup = createSharedComposable(() => { consumer.pause() - console.log(consumerId) - triggerRef(consumers) }) @@ -230,10 +229,6 @@ export const useMediasoup = createSharedComposable(() => { }) }, { immediate: true, flush: 'sync' }) - function getClientConsumers(socketId: ChadClient['socketId']) { - return consumers.value.values().filter(consumer => consumer.appData.socketId === socketId) - } - async function enableProducer(type: ProducerType, options: ProducerOptions) { const producer = getProducerByType(type) @@ -322,13 +317,7 @@ export const useMediasoup = createSharedComposable(() => { if (!device.value) return - const stream = await navigator.mediaDevices.getDisplayMedia({ - audio: false, - video: { - displaySurface: 'monitor', - frameRate: { max: 30 }, - }, - }) + const stream = await getShareStream() const track = stream.getVideoTracks()[0] @@ -442,7 +431,6 @@ export const useMediasoup = createSharedComposable(() => { micProducer, cameraProducer, shareProducer, - getClientConsumers, pauseProducer, resumeProducer, enableShare, diff --git a/client/app/layouts/default.vue b/client/app/layouts/default.vue index fe4f529..cc3cabd 100644 --- a/client/app/layouts/default.vue +++ b/client/app/layouts/default.vue @@ -1,5 +1,5 @@ - -