vue-parley 4.8.0 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -4
- package/dist/chat.css +52 -12
- package/dist/chunks/{Call-DCg-gZw0.mjs → Call-DY7-rM16.mjs} +2 -2
- package/dist/chunks/{Call-DCg-gZw0.mjs.map → Call-DY7-rM16.mjs.map} +1 -1
- package/dist/chunks/{Call-TF_c1JdN.cjs → Call-RREiDkV_.cjs} +2 -2
- package/dist/chunks/{Call-TF_c1JdN.cjs.map → Call-RREiDkV_.cjs.map} +1 -1
- package/dist/chunks/{index-CtBo8-sB.mjs → index-BoigqzSL.mjs} +182 -53
- package/dist/chunks/index-BoigqzSL.mjs.map +1 -0
- package/dist/chunks/{index-CWchKQBV.cjs → index-CynD-QrC.cjs} +181 -52
- package/dist/chunks/index-CynD-QrC.cjs.map +1 -0
- package/dist/chunks/{session-uawe-zUn.cjs → session-CYuGKjIt.cjs} +2 -2
- package/dist/chunks/{session-uawe-zUn.cjs.map → session-CYuGKjIt.cjs.map} +1 -1
- package/dist/chunks/{session-tbHRNyEm.mjs → session-ClK8dU3I.mjs} +2 -2
- package/dist/chunks/{session-tbHRNyEm.mjs.map → session-ClK8dU3I.mjs.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/types/app/components/ChatPage.vue.d.ts +17 -2
- package/dist/types/app/components/ChatPage.vue.d.ts.map +1 -1
- package/dist/types/app/components/chat/ChatMessages.vue.d.ts.map +1 -1
- package/dist/types/app/components/chat/ChatPageBar.vue.d.ts +6 -0
- package/dist/types/app/components/chat/ChatPageBar.vue.d.ts.map +1 -1
- package/dist/types/app/components/chat/ChatView.vue.d.ts +9 -1
- package/dist/types/app/components/chat/ChatView.vue.d.ts.map +1 -1
- package/dist/types/app/components/chat/contact/ChatList.vue.d.ts.map +1 -1
- package/dist/types/app/composables/useFlippedVirtualScroll.d.ts +1 -0
- package/dist/types/app/composables/useFlippedVirtualScroll.d.ts.map +1 -1
- package/dist/types/app/stores/chatStore.d.ts +1 -0
- package/dist/types/app/stores/chatStore.d.ts.map +1 -1
- package/dist/types/app/stores/messageStores.d.ts +4 -1
- package/dist/types/app/stores/messageStores.d.ts.map +1 -1
- package/dist/types/app/types/components/menu-options.d.ts +7 -1
- package/dist/types/app/types/components/menu-options.d.ts.map +1 -1
- package/dist/types/app/types/index.d.ts +1 -0
- package/dist/types/app/types/index.d.ts.map +1 -1
- package/package.json +16 -16
- package/dist/chunks/index-CWchKQBV.cjs.map +0 -1
- package/dist/chunks/index-CtBo8-sB.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
A drop-in Vue 3 chat and video-call UI. You supply the backend through a few handler objects; the package brings the screens, the state (Pinia stores), the translations and the styles.
|
|
4
4
|
|
|
5
|
-
Formerly `@yonus_amire01/chat`. To switch, replace that name with `vue-parley` in `package.json` and in imports; nothing else changed.
|
|
6
|
-
|
|
7
5
|
- Contact list with search, filters and infinite scroll
|
|
8
6
|
- Virtualised message list with text, image, file, voice and video messages, replies, edits, deletes, drafts and retries on failed sends
|
|
9
7
|
- Voice and video calls with screen sharing over plain browser WebRTC
|
|
@@ -112,10 +110,20 @@ Render the chat inside `<ClientOnly>`: its handlers are only installed in the br
|
|
|
112
110
|
| Slot | Where | Slot props |
|
|
113
111
|
| ------------------ | -------------------------------------------------- | ------------------------------- |
|
|
114
112
|
| `empty` | Replaces the "no conversation selected" placeholder | none |
|
|
115
|
-
| `header-actions` | Conversation header, beside the call button | `{ contact }`
|
|
113
|
+
| `header-actions` | Conversation header, beside the call button | `{ contact, compact }` |
|
|
116
114
|
| `conversation-top` | Between the header and the messages | `{ conversationId, contact }` |
|
|
117
115
|
| `above-input` | Above the input, while the conversation is active | `{ conversationId, contact }` |
|
|
118
116
|
|
|
117
|
+
The header folds by its own width (under 640px), not the screen's, since the list and the contact panel take from it. Folded, it keeps the voice call (or Join) and moves the video call into its "more options" menu, and `compact` is true. A host then hides its `header-actions` buttons; the menu lists the `headerOptions` prop in their place (`MenuOption[]`; `icon` is a Phosphor name or any component, `command` runs on select). The header is also a size container named `chat-header`, so host buttons can drop their labels with container queries (`@3xl/chat-header:inline`).
|
|
118
|
+
|
|
119
|
+
```vue
|
|
120
|
+
<ChatPage :header-options="[{ key: 'members', label: 'Members', icon: UsersIcon, command: openMembers }]">
|
|
121
|
+
<template #header-actions="{ compact }">
|
|
122
|
+
<MembersButton v-if="!compact" />
|
|
123
|
+
</template>
|
|
124
|
+
</ChatPage>
|
|
125
|
+
```
|
|
126
|
+
|
|
119
127
|
To build a different layout, use the exported building blocks instead: `ChatList`, `ChatConversation`, `ChatHeader`, `ChatMessages`, `ChatInput` and `ChatBubble`. They read the same stores, so they work together once `createChat()` is installed.
|
|
120
128
|
|
|
121
129
|
### Photos and videos
|
|
@@ -334,4 +342,4 @@ e2e/ Playwright tests and harness
|
|
|
334
342
|
|
|
335
343
|
[MIT](LICENSE)
|
|
336
344
|
|
|
337
|
-
Repository: [github.com/
|
|
345
|
+
Repository: [github.com/SaeedP11/vue-parley](https://github.com/SaeedP11/vue-parley)
|
package/dist/chat.css
CHANGED
|
@@ -403,6 +403,10 @@
|
|
|
403
403
|
@layer components;
|
|
404
404
|
|
|
405
405
|
@layer utilities {
|
|
406
|
+
:where(.vue-chat, .vue-chat *).\@container\/chat-header {
|
|
407
|
+
container: chat-header / inline-size;
|
|
408
|
+
}
|
|
409
|
+
|
|
406
410
|
:where(.vue-chat, .vue-chat *).\!pointer-events-none {
|
|
407
411
|
pointer-events: none !important;
|
|
408
412
|
}
|
|
@@ -1193,6 +1197,10 @@
|
|
|
1193
1197
|
width: calc(var(--spacing) * 64);
|
|
1194
1198
|
}
|
|
1195
1199
|
|
|
1200
|
+
:where(.vue-chat, .vue-chat *).w-64\! {
|
|
1201
|
+
width: calc(var(--spacing) * 64) !important;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1196
1204
|
:where(.vue-chat, .vue-chat *).w-70 {
|
|
1197
1205
|
width: calc(var(--spacing) * 70);
|
|
1198
1206
|
}
|
|
@@ -1245,6 +1253,10 @@
|
|
|
1245
1253
|
max-width: 60%;
|
|
1246
1254
|
}
|
|
1247
1255
|
|
|
1256
|
+
:where(.vue-chat, .vue-chat *).max-w-\[calc\(100vw-1\.5rem\)\]\! {
|
|
1257
|
+
max-width: calc(100vw - 1.5rem) !important;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1248
1260
|
:where(.vue-chat, .vue-chat *).max-w-\[calc\(100vw-2rem\)\] {
|
|
1249
1261
|
max-width: calc(100vw - 2rem);
|
|
1250
1262
|
}
|
|
@@ -1313,6 +1325,10 @@
|
|
|
1313
1325
|
transform-origin: 0 0;
|
|
1314
1326
|
}
|
|
1315
1327
|
|
|
1328
|
+
:where(.vue-chat, .vue-chat *).origin-top-right {
|
|
1329
|
+
transform-origin: 100% 0;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1316
1332
|
:where(.vue-chat, .vue-chat *).-translate-1\/2 {
|
|
1317
1333
|
--tw-translate-x: calc(calc(1 / 2 * 100%) * -1);
|
|
1318
1334
|
--tw-translate-y: calc(calc(1 / 2 * 100%) * -1);
|
|
@@ -1576,6 +1592,10 @@
|
|
|
1576
1592
|
row-gap: calc(var(--spacing) * .5);
|
|
1577
1593
|
}
|
|
1578
1594
|
|
|
1595
|
+
:where(.vue-chat, .vue-chat *).gap-y-0\.5\! {
|
|
1596
|
+
row-gap: calc(var(--spacing) * .5) !important;
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1579
1599
|
:where(.vue-chat, .vue-chat *).gap-y-1 {
|
|
1580
1600
|
row-gap: var(--spacing);
|
|
1581
1601
|
}
|
|
@@ -1807,6 +1827,16 @@
|
|
|
1807
1827
|
}
|
|
1808
1828
|
}
|
|
1809
1829
|
|
|
1830
|
+
:where(.vue-chat, .vue-chat *).border-chat-outline-variant\/70\! {
|
|
1831
|
+
border-color: #f0f0f0b3 !important;
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1835
|
+
:where(.vue-chat, .vue-chat *).border-chat-outline-variant\/70\! {
|
|
1836
|
+
border-color: color-mix(in oklab, var(--color-chat-outline-variant) 70%, transparent) !important;
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1810
1840
|
:where(.vue-chat, .vue-chat *).border-chat-primary {
|
|
1811
1841
|
border-color: var(--color-chat-primary);
|
|
1812
1842
|
}
|
|
@@ -3572,6 +3602,12 @@
|
|
|
3572
3602
|
}
|
|
3573
3603
|
}
|
|
3574
3604
|
|
|
3605
|
+
@container chat-header (min-width: 48rem) {
|
|
3606
|
+
:where(.vue-chat, .vue-chat *).\@3xl\/chat-header\:inline {
|
|
3607
|
+
display: inline;
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
|
|
3575
3611
|
:where(.vue-chat, .vue-chat *).ltr\:-scale-x-100:where(:dir(ltr), [dir="ltr"], [dir="ltr"] *) {
|
|
3576
3612
|
--tw-scale-x: calc(100% * -1);
|
|
3577
3613
|
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
@@ -3602,6 +3638,10 @@
|
|
|
3602
3638
|
left: auto !important;
|
|
3603
3639
|
}
|
|
3604
3640
|
|
|
3641
|
+
:where(.vue-chat, .vue-chat *).rtl\:origin-top-left:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) {
|
|
3642
|
+
transform-origin: 0 0;
|
|
3643
|
+
}
|
|
3644
|
+
|
|
3605
3645
|
:where(.vue-chat, .vue-chat *).rtl\:origin-top-right:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) {
|
|
3606
3646
|
transform-origin: 100% 0;
|
|
3607
3647
|
}
|
|
@@ -4187,15 +4227,15 @@
|
|
|
4187
4227
|
}
|
|
4188
4228
|
|
|
4189
4229
|
/* Styles remain exactly the same */
|
|
4190
|
-
:where(.vue-chat, .vue-chat *).flip-vertical[data-v-
|
|
4230
|
+
:where(.vue-chat, .vue-chat *).flip-vertical[data-v-c38cc418] {
|
|
4191
4231
|
transform: scaleY(-1);
|
|
4192
4232
|
will-change: transform;
|
|
4193
4233
|
}
|
|
4194
|
-
:where(.vue-chat, .vue-chat *)[data-index][data-v-
|
|
4234
|
+
:where(.vue-chat, .vue-chat *)[data-index][data-v-c38cc418] {
|
|
4195
4235
|
will-change: transform;
|
|
4196
4236
|
backface-visibility: hidden;
|
|
4197
4237
|
}
|
|
4198
|
-
@keyframes slide-in-right-
|
|
4238
|
+
@keyframes slide-in-right-c38cc418 {
|
|
4199
4239
|
0% {
|
|
4200
4240
|
opacity: 0;
|
|
4201
4241
|
transform: scaleY(-1) translateX(30px);
|
|
@@ -4205,7 +4245,7 @@
|
|
|
4205
4245
|
transform: scaleY(-1) translateX(0);
|
|
4206
4246
|
}
|
|
4207
4247
|
}
|
|
4208
|
-
@keyframes slide-in-left-
|
|
4248
|
+
@keyframes slide-in-left-c38cc418 {
|
|
4209
4249
|
0% {
|
|
4210
4250
|
opacity: 0;
|
|
4211
4251
|
transform: scaleY(-1) translateX(-30px);
|
|
@@ -4215,23 +4255,23 @@
|
|
|
4215
4255
|
transform: scaleY(-1) translateX(0);
|
|
4216
4256
|
}
|
|
4217
4257
|
}
|
|
4218
|
-
:where(.vue-chat, .vue-chat *).animate-slide-right[data-v-
|
|
4219
|
-
animation: slide-in-right-
|
|
4258
|
+
:where(.vue-chat, .vue-chat *).animate-slide-right[data-v-c38cc418] {
|
|
4259
|
+
animation: slide-in-right-c38cc418 300ms ease-out forwards;
|
|
4220
4260
|
will-change: transform, opacity;
|
|
4221
4261
|
}
|
|
4222
|
-
:where(.vue-chat, .vue-chat *).animate-slide-left[data-v-
|
|
4223
|
-
animation: slide-in-left-
|
|
4262
|
+
:where(.vue-chat, .vue-chat *).animate-slide-left[data-v-c38cc418] {
|
|
4263
|
+
animation: slide-in-left-c38cc418 300ms ease-out forwards;
|
|
4224
4264
|
will-change: transform, opacity;
|
|
4225
4265
|
}
|
|
4226
|
-
:where(.vue-chat, .vue-chat *)#list[data-v-
|
|
4266
|
+
:where(.vue-chat, .vue-chat *)#list[data-v-c38cc418] {
|
|
4227
4267
|
will-change: padding-top;
|
|
4228
4268
|
}
|
|
4229
|
-
:where(.vue-chat, .vue-chat *).animate-request-in[data-v-
|
|
4230
|
-
animation: request-in-
|
|
4269
|
+
:where(.vue-chat, .vue-chat *).animate-request-in[data-v-c38cc418] {
|
|
4270
|
+
animation: request-in-c38cc418 0.4s ease-out forwards;
|
|
4231
4271
|
overflow: hidden;
|
|
4232
4272
|
transform: scaleY(-1);
|
|
4233
4273
|
}
|
|
4234
|
-
@keyframes request-in-
|
|
4274
|
+
@keyframes request-in-c38cc418 {
|
|
4235
4275
|
0% {
|
|
4236
4276
|
opacity: 0;
|
|
4237
4277
|
max-height: 0;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ref, onMounted, onUnmounted, watch, nextTick, reactive, onBeforeUnmount, defineComponent, openBlock, createElementBlock, createBlock, unref, mergeProps, withCtx, createVNode, normalizeClass, computed, Fragment, normalizeStyle, createElementVNode, toDisplayString, withModifiers, createCommentVNode, withDirectives, vShow, renderList } from "vue";
|
|
2
|
-
import { u as useCallStore, a as useLocalI18n, c as chat, b as useDirection, d as useChatStore, f as formatDuration } from "./index-
|
|
2
|
+
import { u as useCallStore, a as useLocalI18n, c as chat, b as useDirection, d as useChatStore, f as formatDuration } from "./index-BoigqzSL.mjs";
|
|
3
3
|
import { useEventListener, useWindowSize, useDraggable } from "@vueuse/core";
|
|
4
4
|
import Avatar from "primevue/avatar";
|
|
5
5
|
import Button from "primevue/button";
|
|
@@ -1152,4 +1152,4 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1152
1152
|
export {
|
|
1153
1153
|
_sfc_main as default
|
|
1154
1154
|
};
|
|
1155
|
-
//# sourceMappingURL=Call-
|
|
1155
|
+
//# sourceMappingURL=Call-DY7-rM16.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Call-DCg-gZw0.mjs","sources":["../../app/composables/call/useCallUi.ts","../../app/composables/useCall.ts","../../app/composables/call/useSpeaking.ts","../../app/components/call/CallIcon.vue","../../app/components/call/CallButton.vue","../../app/components/call/Call.vue"],"sourcesContent":["import { nextTick, onMounted, onUnmounted, ref, watch, type Ref } from \"vue\";\nimport type { RemoteStream } from \"./peers\";\n\nexport interface CallUiOptions {\n localStream: Ref<MediaStream | null>;\n screenStream: Ref<MediaStream | null>;\n remoteVideos: Ref<Record<string, RemoteStream>>;\n remoteScreens: Ref<Record<string, RemoteStream>>;\n /** Re-attach streams when this changes: minimizing swaps the <video> elements. */\n isMinimized: () => boolean;\n}\n\nconst CONTROLS_HIDE_AFTER_MS = 3000;\n\n/** The call screen's view state, and keeping each <video> element showing the right stream. */\nexport function useCallUi(opts: CallUiOptions) {\n const { localStream, screenStream, remoteVideos, remoteScreens } = opts;\n\n // Template refs, bound by Call.vue.\n const localVideo = ref<HTMLVideoElement | null>(null);\n const localScreen = ref<HTMLVideoElement | null>(null);\n const remoteRefs = ref<Record<string, HTMLVideoElement | null>>({});\n const remoteScreenRefs = ref<Record<string, HTMLVideoElement | undefined>>({});\n const remoteParents = ref<Record<string, HTMLElement>>({});\n\n // --- Controls fade out after a few seconds without input ---\n const showControls = ref(true);\n let controlsTimeout: ReturnType<typeof setTimeout> | undefined;\n function resetControlsTimeout() {\n showControls.value = true;\n clearTimeout(controlsTimeout);\n controlsTimeout = setTimeout(\n () => (showControls.value = false),\n CONTROLS_HIDE_AFTER_MS,\n );\n }\n const inputEvents = [\"mousemove\", \"click\", \"keydown\"] as const;\n onMounted(() => {\n resetControlsTimeout();\n inputEvents.forEach((e) => document.addEventListener(e, resetControlsTimeout));\n });\n onUnmounted(() => {\n inputEvents.forEach((e) => document.removeEventListener(e, resetControlsTimeout));\n clearTimeout(controlsTimeout);\n // The call goes on; only this view lets go of its elements.\n detachAll();\n });\n\n // --- Fullscreen: the whole call, or a single tile ---\n const isFullscreen = ref(false);\n function toggleFullscreen(target: HTMLElement = document.documentElement) {\n if (!document.fullscreenElement) {\n void target.requestFullscreen?.();\n isFullscreen.value = true;\n } else {\n void document.exitFullscreen();\n isFullscreen.value = false;\n }\n }\n const toggleRemote = (tileId: string, el?: HTMLElement) => {\n const container = el ?? remoteParents.value[tileId];\n if (container) toggleFullscreen(container);\n };\n\n // --- Pausing a single tile ---\n const videoPaused = ref<Record<string, boolean>>({});\n function toggleVideoPause(tileId: string, el: HTMLVideoElement | null | undefined) {\n if (!(el instanceof HTMLVideoElement)) return;\n if (videoPaused.value[tileId]) void el.play();\n else el.pause();\n videoPaused.value[tileId] = !videoPaused.value[tileId];\n }\n\n // --- Keep each <video> showing its stream ---\n /** The browser refused to play a remote participant with sound until the user taps something. */\n const soundBlocked = ref(false);\n\n async function play(el: HTMLVideoElement) {\n try {\n await el.play();\n } catch (err) {\n if ((err as DOMException)?.name !== \"NotAllowedError\" || el.muted) return;\n // Mobile browsers (and desktop ones without prior interaction) refuse unmuted playback\n // that doesn't follow a tap, which would leave the tile black. Show the video muted and\n // offer a button to turn the sound on.\n el.muted = true;\n soundBlocked.value = true;\n await el.play().catch((e) => console.error(\"[vue-chat] Remote video can't play:\", e));\n }\n }\n\n /** Unmutes the remote participants; must run from a user gesture. */\n function enableSound() {\n soundBlocked.value = false;\n for (const el of Object.values(remoteRefs.value)) {\n if (!el) continue;\n el.muted = false;\n void play(el);\n }\n }\n\n const attach = (el: HTMLVideoElement | null | undefined, stream: MediaStream) => {\n if (!el) return;\n if (el.srcObject !== stream) el.srcObject = stream;\n void play(el);\n };\n\n watch(\n [localStream, opts.isMinimized],\n async () => {\n await nextTick();\n if (localStream.value && localVideo.value)\n localVideo.value.srcObject = localStream.value;\n },\n { immediate: true },\n );\n watch(\n [screenStream, opts.isMinimized],\n async () => {\n await nextTick();\n if (localScreen.value) localScreen.value.srcObject = screenStream.value;\n },\n { immediate: true },\n );\n watch(\n [() => ({ ...remoteVideos.value }), opts.isMinimized],\n async () => {\n await nextTick();\n for (const [id, { stream }] of Object.entries(remoteVideos.value))\n attach(remoteRefs.value[id], stream);\n },\n { immediate: true },\n );\n watch(\n [() => ({ ...remoteScreens.value }), opts.isMinimized],\n async () => {\n await nextTick();\n for (const [id, { stream }] of Object.entries(remoteScreens.value))\n attach(remoteScreenRefs.value[id], stream);\n },\n { immediate: true },\n );\n\n /** Detaches every <video>, so no element keeps a stopped stream alive. */\n function detachAll() {\n const all = [\n localVideo.value,\n localScreen.value,\n ...Object.values(remoteRefs.value),\n ...Object.values(remoteScreenRefs.value),\n ];\n for (const el of all) if (el) el.srcObject = null;\n }\n\n return {\n localVideo,\n localScreen,\n remoteRefs,\n remoteScreenRefs,\n remoteParents,\n showControls,\n resetControlsTimeout,\n isFullscreen,\n toggleFullscreen: () => toggleFullscreen(),\n toggleRemote,\n videoPaused,\n toggleVideoPause,\n soundBlocked,\n enableSound,\n detachAll,\n };\n}\n","import { ref } from \"vue\";\nimport { useCallStore } from \"~/stores/callStore\";\nimport { useCallUi } from \"./call/useCallUi\";\n\n/**\n * The view side of the running call, for Call.vue. The call itself (signalling, peers, media)\n * lives in the call store, so unmounting this view doesn't end it.\n */\nexport default function useCall() {\n const callStore = useCallStore();\n const session = callStore.session;\n if (!session) {\n throw new Error(\"[vue-chat] useCall() needs a running call: callStore.startCall() first\");\n }\n const { media, peers } = session;\n\n const ui = useCallUi({\n localStream: media.localStream,\n screenStream: media.screenStream,\n remoteVideos: peers.remoteVideos,\n remoteScreens: peers.remoteScreens,\n isMinimized: () => callStore.isMinimized,\n });\n\n async function switchCamera(deviceId: string) {\n const stream = await session!.switchCamera(deviceId);\n // Same stream object with a new track: the preview has to be told.\n if (stream && ui.localVideo.value) ui.localVideo.value.srcObject = stream;\n }\n\n return {\n // Call state\n participantCount: session.participantCount,\n tileCount: session.tileCount,\n localStream: media.localStream,\n remoteVideos: peers.remoteVideos,\n remoteScreens: peers.remoteScreens,\n // Local media\n cameras: media.cameras,\n isAudioOn: media.isAudioOn,\n isVideoOn: media.isVideoOn,\n isScreenSharing: media.isScreenSharing,\n isFlashlightOn: media.isFlashlightOn,\n isFlashlightSupported: media.isFlashlightSupported,\n toggleAudio: media.toggleAudio,\n toggleVideo: media.toggleVideo,\n toggleFlashlight: media.toggleFlashlight,\n toggleScreenShare: session.toggleScreenShare,\n switchCamera,\n endCall: callStore.endCall,\n // View\n showCameraModal: ref(false),\n showControls: ui.showControls,\n resetControlsTimeout: ui.resetControlsTimeout,\n isFullscreen: ui.isFullscreen,\n toggleFullscreen: ui.toggleFullscreen,\n toggleRemote: ui.toggleRemote,\n videoPaused: ui.videoPaused,\n soundBlocked: ui.soundBlocked,\n enableSound: ui.enableSound,\n toggleVideoPause: ui.toggleVideoPause,\n localVideo: ui.localVideo,\n localScreen: ui.localScreen,\n remoteRefs: ui.remoteRefs,\n remoteScreenRefs: ui.remoteScreenRefs,\n remoteParents: ui.remoteParents,\n };\n}\n","import { onBeforeUnmount, reactive, watch } from \"vue\";\n\n// RMS of the waveform (0–1) above which a voice counts as speaking, and how long it stays lit\n// after dropping below, so the ring doesn't flicker between words.\nconst THRESHOLD = 0.04;\nconst HOLD_MS = 400;\nconst POLL_MS = 120;\n\ninterface Meter {\n stream: MediaStream;\n source: MediaStreamAudioSourceNode;\n analyser: AnalyserNode;\n buffer: Uint8Array<ArrayBuffer>;\n lastLoud: number;\n}\n\n/**\n * Who is speaking, per tile id: a level meter on each stream's audio, through one shared\n * AudioContext. Ids whose stream is null, or has no audio track, are never speaking.\n */\nexport function useSpeaking(streams: () => Record<string, MediaStream | null | undefined>) {\n const speaking = reactive<Record<string, boolean>>({});\n const meters = new Map<string, Meter>();\n let context: AudioContext | null = null;\n let timer: ReturnType<typeof setInterval> | undefined;\n\n const drop = (id: string) => {\n const meter = meters.get(id);\n if (!meter) return;\n meter.source.disconnect();\n meters.delete(id);\n delete speaking[id];\n };\n\n const poll = () => {\n const now = performance.now();\n for (const [id, meter] of meters) {\n meter.analyser.getByteTimeDomainData(meter.buffer);\n let sum = 0;\n for (const sample of meter.buffer) {\n const centred = (sample - 128) / 128;\n sum += centred * centred;\n }\n if (Math.sqrt(sum / meter.buffer.length) > THRESHOLD) meter.lastLoud = now;\n const lit = now - meter.lastLoud < HOLD_MS;\n if (speaking[id] !== lit) speaking[id] = lit;\n }\n };\n\n watch(\n streams,\n (current) => {\n for (const id of [...meters.keys()]) {\n if (current[id] !== meters.get(id)!.stream) drop(id);\n }\n\n for (const [id, stream] of Object.entries(current)) {\n if (!stream || meters.has(id) || !stream.getAudioTracks().length) continue;\n if (typeof AudioContext === \"undefined\") return;\n context ??= new AudioContext();\n // Created after the call was started by a click, so it is normally running already.\n if (context.state === \"suspended\") void context.resume().catch(() => {});\n\n const source = context.createMediaStreamSource(stream);\n const analyser = context.createAnalyser();\n analyser.fftSize = 512;\n // Only measured, never routed to the speakers: the <video> elements play the sound.\n source.connect(analyser);\n meters.set(id, {\n stream,\n source,\n analyser,\n buffer: new Uint8Array(analyser.fftSize),\n lastLoud: 0,\n });\n }\n\n if (meters.size && !timer) timer = setInterval(poll, POLL_MS);\n if (!meters.size && timer) {\n clearInterval(timer);\n timer = undefined;\n }\n },\n { immediate: true, deep: 1 },\n );\n\n onBeforeUnmount(() => {\n clearInterval(timer);\n for (const id of [...meters.keys()]) drop(id);\n void context?.close().catch(() => {});\n });\n\n return speaking;\n}\n","<script setup lang=\"ts\">\n/**\n * The call screen's icons: Google's Material Symbols (Rounded, weight 400), the set Google Meet\n * uses, so the controls read the way people already know them. Only the icons the call needs are\n * inlined, as SVG paths, so the library takes no icon dependency for them.\n *\n * Material Symbols: Copyright Google LLC, Apache License 2.0\n * (https://github.com/google/material-design-icons/blob/master/LICENSE).\n */\nconst ICONS = {\n mic:\n \"<path fill=\\\"currentColor\\\" d=\\\"M9.875 13.125Q9 12.25 9 11V5q0-1.25.875-2.125T12 2t2.125.875T15 5v6q0 1.25-.875 2.125T12 14t-2.125-.875M11 20v-2.075q-2.3-.325-3.937-1.95t-1.988-3.95q-.05-.425.225-.725T6 11t.713.288T7.1 12q.35 1.75 1.738 2.875T12 16q1.8 0 3.175-1.137T16.9 12q.1-.425.388-.712T18 11t.7.3t.225.725q-.35 2.275-1.975 3.925T13 17.925V20q0 .425-.288.713T12 21t-.712-.288T11 20\\\"/>\",\n micOff:\n \"<path fill=\\\"currentColor\\\" d=\\\"M16.8 14.575q-.35-.2-.45-.612t.1-.763q.175-.275.288-.587t.162-.638q.1-.425.388-.7T18 11t.7.3t.225.725q-.075.575-.262 1.125t-.488 1.05q-.2.35-.612.463t-.763-.088m-3.5-4.125L9.575 6.725Q9.3 6.45 9.15 6.088T9 5.325V5q0-1.25.875-2.125T12 2t2.125.875T15 5v4.725q0 .675-.612.938T13.3 10.45M11 20v-2.1q-2.3-.3-3.937-1.925t-1.988-3.95q-.05-.425.225-.725T6 11t.713.288T7.1 12q.35 1.75 1.738 2.875T12 16q.85 0 1.613-.262T15 15l1.425 1.425q-.725.575-1.588.963T13 17.9V20q0 .425-.288.713T12 21t-.712-.288T11 20m8.1 1.9l-17-17q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l17 17q.275.275.275.7t-.275.7t-.7.275t-.7-.275\\\"/>\",\n videocam:\n \"<path fill=\\\"currentColor\\\" d=\\\"M4 20q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4h12q.825 0 1.413.588T18 6v4.5l3.15-3.15q.25-.25.55-.125t.3.475v8.6q0 .35-.3.475t-.55-.125L18 13.5V18q0 .825-.587 1.413T16 20z\\\"/>\",\n videocamOff:\n \"<path fill=\\\"currentColor\\\" d=\\\"m18 10.5l3.15-3.15q.25-.25.55-.125t.3.475v8.6q0 .35-.3.475t-.55-.125l-3.325-3.325q-.25.35-.712.425t-.813-.275L8.525 5.7q-.25-.25-.288-.525t.088-.55t.35-.45T9.25 4H16q.825 0 1.413.588T18 6zm1.85 12.15L1.35 4.15q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l18.5 18.5q.275.275.275.7t-.275.7t-.7.275t-.7-.275M4 4l14 14q0 .825-.587 1.413T16 20H4q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4\\\"/>\",\n presentToAll:\n \"<path fill=\\\"currentColor\\\" d=\\\"M11 11.825V15q0 .425.288.713T12 16t.713-.288T13 15v-3.15l.9.875q.3.275.7.288t.7-.288t.3-.712t-.3-.713l-2.6-2.6q-.3-.3-.7-.3t-.7.3l-2.6 2.6q-.3.3-.287.7t.312.7q.3.275.7.288t.7-.288zM4 20q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4h16q.825 0 1.413.588T22 6v12q0 .825-.587 1.413T20 20z\\\"/>\",\n cancelPresentation:\n \"<path fill=\\\"currentColor\\\" d=\\\"m10.6 12l-1.9 1.9q-.275.275-.275.7t.275.7t.7.275t.7-.275l1.9-1.9l1.9 1.9q.275.275.7.275t.7-.275t.275-.7t-.275-.7L13.4 12l1.9-1.9q.275-.275.275-.7t-.275-.7t-.7-.275t-.7.275L12 10.6l-1.9-1.9q-.275-.275-.7-.275t-.7.275t-.275.7t.275.7zM4 20q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4h16q.825 0 1.413.588T22 6v12q0 .825-.587 1.413T20 20z\\\"/>\",\n callEnd:\n \"<path fill=\\\"currentColor\\\" d=\\\"M12 8q2.95 0 5.813 1.188T22.9 12.75q.3.3.3.7t-.3.7l-2.3 2.25q-.275.275-.638.3t-.662-.2l-2.9-2.2q-.2-.15-.3-.35t-.1-.45v-2.85q-.95-.3-1.95-.475T12 10t-2.05.175T8 10.65v2.85q0 .25-.1.45t-.3.35l-2.9 2.2q-.3.225-.663.2t-.637-.3l-2.3-2.25q-.3-.3-.3-.7t.3-.7q2.2-2.375 5.075-3.562T12 8\\\"/>\",\n fullscreen:\n \"<path fill=\\\"currentColor\\\" d=\\\"M5 19h2q.425 0 .713.288T8 20t-.288.713T7 21H4q-.425 0-.712-.288T3 20v-3q0-.425.288-.712T4 16t.713.288T5 17zm14 0v-2q0-.425.288-.712T20 16t.713.288T21 17v3q0 .425-.288.713T20 21h-3q-.425 0-.712-.288T16 20t.288-.712T17 19zM5 5v2q0 .425-.288.713T4 8t-.712-.288T3 7V4q0-.425.288-.712T4 3h3q.425 0 .713.288T8 4t-.288.713T7 5zm14 0h-2q-.425 0-.712-.288T16 4t.288-.712T17 3h3q.425 0 .713.288T21 4v3q0 .425-.288.713T20 8t-.712-.288T19 7z\\\"/>\",\n fullscreenExit:\n \"<path fill=\\\"currentColor\\\" d=\\\"M6 18H4q-.425 0-.712-.288T3 17t.288-.712T4 16h3q.425 0 .713.288T8 17v3q0 .425-.288.713T7 21t-.712-.288T6 20zm12 0v2q0 .425-.288.713T17 21t-.712-.288T16 20v-3q0-.425.288-.712T17 16h3q.425 0 .713.288T21 17t-.288.713T20 18zM6 6V4q0-.425.288-.712T7 3t.713.288T8 4v3q0 .425-.288.713T7 8H4q-.425 0-.712-.288T3 7t.288-.712T4 6zm12 0h2q.425 0 .713.288T21 7t-.288.713T20 8h-3q-.425 0-.712-.288T16 7V4q0-.425.288-.712T17 3t.713.288T18 4z\\\"/>\",\n flashlightOn:\n \"<path fill=\\\"currentColor\\\" d=\\\"M6 5V4q0-.825.588-1.412T8 2h8q.825 0 1.413.588T18 4v1zm7.063 10.063q.437-.438.437-1.063t-.437-1.062T12 12.5t-1.062.438T10.5 14t.438 1.063T12 15.5t1.063-.437M8 20v-9L6.325 8.5q-.175-.25-.25-.525T6 7.4V7h12v.4q0 .3-.075.575t-.25.525L16 11v9q0 .825-.587 1.413T14 22h-4q-.825 0-1.412-.587T8 20\\\"/>\",\n flashlightOff:\n \"<path fill=\\\"currentColor\\\" d=\\\"M8 20v-9.2L2.1 4.9q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l17 17q.275.275.275.7t-.275.7t-.7.275t-.7-.275L16 18.8V20q0 .825-.587 1.413T14 22h-4q-.825 0-1.412-.587T8 20M7.85 5l-1.7-1.7q.2-.575.7-.937T8 2h8q.825 0 1.413.588T18 4v1zM16 13.15L9.85 7H18v.4q0 .3-.075.575t-.25.525L16 11z\\\"/>\",\n pause:\n \"<path fill=\\\"currentColor\\\" d=\\\"M16 19q-.825 0-1.412-.587T14 17V7q0-.825.588-1.412T16 5t1.413.588T18 7v10q0 .825-.587 1.413T16 19m-8 0q-.825 0-1.412-.587T6 17V7q0-.825.588-1.412T8 5t1.413.588T10 7v10q0 .825-.587 1.413T8 19\\\"/>\",\n play:\n \"<path fill=\\\"currentColor\\\" d=\\\"M8 17.175V6.825q0-.425.3-.713t.7-.287q.125 0 .263.037t.262.113l8.15 5.175q.225.15.338.375t.112.475t-.112.475t-.338.375l-8.15 5.175q-.125.075-.262.113T9 18.175q-.4 0-.7-.288t-.3-.712\\\"/>\",\n group:\n \"<path fill=\\\"currentColor\\\" d=\\\"M1 17.2q0-.85.438-1.562T2.6 14.55q1.55-.775 3.15-1.162T9 13t3.25.388t3.15 1.162q.725.375 1.163 1.088T17 17.2v.8q0 .825-.587 1.413T15 20H3q-.825 0-1.412-.587T1 18zM18.45 20q.275-.45.413-.962T19 18v-1q0-1.1-.612-2.113T16.65 13.15q1.275.15 2.4.513t2.1.887q.9.5 1.375 1.112T23 17v1q0 .825-.587 1.413T21 20zM6.175 10.825Q5 9.65 5 8t1.175-2.825T9 4t2.825 1.175T13 8t-1.175 2.825T9 12t-2.825-1.175m11.65 0Q16.65 12 15 12q-.275 0-.7-.062t-.7-.138q.675-.8 1.038-1.775T15 8t-.362-2.025T13.6 4.2q.35-.125.7-.163T15 4q1.65 0 2.825 1.175T19 8t-1.175 2.825\\\"/>\",\n pictureInPicture:\n \"<path fill=\\\"currentColor\\\" d=\\\"M4 20q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4h16q.825 0 1.413.588T22 6v12q0 .825-.587 1.413T20 20zm8-3h6q.425 0 .713-.288T19 16v-4q0-.425-.288-.712T18 11h-6q-.425 0-.712.288T11 12v4q0 .425.288.713T12 17m3-3\\\"/>\",\n openInFull:\n \"<path fill=\\\"currentColor\\\" d=\\\"M4 21q-.425 0-.712-.288T3 20v-6q0-.425.288-.712T4 13t.713.288T5 14v3.6L17.6 5H14q-.425 0-.712-.288T13 4t.288-.712T14 3h6q.425 0 .713.288T21 4v6q0 .425-.288.713T20 11t-.712-.288T19 10V6.4L6.4 19H10q.425 0 .713.288T11 20t-.288.713T10 21z\\\"/>\",\n volumeUp:\n \"<path fill=\\\"currentColor\\\" d=\\\"M19 11.975q0-2.075-1.1-3.787t-2.95-2.563q-.375-.175-.55-.537t-.05-.738q.15-.4.538-.575t.787 0Q18.1 4.85 19.55 7.063T21 11.974t-1.45 4.913t-3.875 3.287q-.4.175-.788 0t-.537-.575q-.125-.375.05-.737t.55-.538q1.85-.85 2.95-2.562t1.1-3.788M7 15H4q-.425 0-.712-.288T3 14v-4q0-.425.288-.712T4 9h3l3.3-3.3q.475-.475 1.088-.213t.612.938v11.15q0 .675-.612.938T10.3 18.3zm9.5-3q0 1.05-.475 1.988t-1.25 1.537q-.25.15-.513.013T14 15.1V8.85q0-.3.263-.437t.512.012q.775.625 1.25 1.575t.475 2\\\"/>\",\n cameraSwitch:\n \"<path fill=\\\"currentColor\\\" d=\\\"M8 17q-.825 0-1.412-.587T6 15V9q0-.825.588-1.412T8 7h1l.7-.7q.15-.15.338-.225T10.425 6h3.15q.2 0 .388.075t.337.225l.7.7h1q.825 0 1.412.588T18 9v6q0 .825-.587 1.413T16 17zm4-3q.825 0 1.413-.587T14 12t-.587-1.412T12 10t-1.412.588T10 12t.588 1.413T12 14m0 10q-4.4 0-7.712-2.762T.174 14.275Q.1 13.85.337 13.5T1 13.1t.75.213t.4.687q.65 3.275 3.113 5.475T11.1 21.95l-.85-.85q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l3.3 3.3q.175.175.113.4t-.288.275q-.675.175-1.362.25T12 24m0-24q4.4 0 7.713 2.75t4.112 6.975q.075.425-.162.775t-.663.4t-.75-.213t-.4-.687q-.65-3.275-3.113-5.475T12.9 2.05l.85.85q.275.275.275.7t-.275.7t-.7.275t-.7-.275L9.05 1Q8.875.825 8.938.6t.287-.275Q9.9.15 10.588.075T12 0\\\"/>\",\n arrowDropUp:\n \"<path fill=\\\"currentColor\\\" d=\\\"M8.2 14q-.225 0-.362-.15T7.7 13.5q0-.05.15-.35l3.625-3.625q.125-.125.25-.175T12 9.3t.275.05t.25.175l3.625 3.625q.075.075.113.163t.037.187q0 .2-.137.35T15.8 14z\\\"/>\",\n moreVert:\n \"<path fill=\\\"currentColor\\\" d=\\\"M12 20q-.825 0-1.412-.587T10 18t.588-1.412T12 16t1.413.588T14 18t-.587 1.413T12 20m0-6q-.825 0-1.412-.587T10 12t.588-1.412T12 10t1.413.588T14 12t-.587 1.413T12 14m0-6q-.825 0-1.412-.587T10 6t.588-1.412T12 4t1.413.588T14 6t-.587 1.413T12 8\\\"/>\",\n check:\n \"<path fill=\\\"currentColor\\\" d=\\\"m9.55 15.15l8.475-8.475q.3-.3.7-.3t.7.3t.3.713t-.3.712l-9.175 9.2q-.3.3-.7.3t-.7-.3L4.55 13q-.3-.3-.288-.712t.313-.713t.713-.3t.712.3z\\\"/>\",\n} as const;\n\nexport type CallIconName = keyof typeof ICONS;\n\ndefineProps<{ name: CallIconName }>();\n</script>\n\n<template>\n <!-- eslint-disable-next-line vue/no-v-html -- static paths from ICONS above, never user input -->\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\" v-html=\"ICONS[name]\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * IconButton for the call screen: an icon-only, round PrimeVue Button showing a Material Symbol\n * (CallIcon). Any Button prop (severity, size, dt...) and listener passes through.\n */\nimport Button from \"primevue/button\";\nimport CallIcon, { type CallIconName } from \"./CallIcon.vue\";\n\ndefineOptions({ inheritAttrs: false });\n\nwithDefaults(\n defineProps<{\n icon: CallIconName;\n /** Accessible name; the button has no visible text. */\n label: string;\n iconClass?: string;\n }>(),\n { iconClass: \"size-5\" },\n);\n</script>\n\n<template>\n <Button rounded text severity=\"secondary\" v-bind=\"$attrs\" :aria-label=\"label\">\n <template #icon>\n <CallIcon :name=\"icon\" :class=\"iconClass\" />\n </template>\n </Button>\n</template>\n","<script setup lang=\"ts\">\nimport { useCallStore } from \"~/stores/callStore\";\nimport { useChatStore } from \"~/stores/chatStore\";\nimport { formatDuration } from \"~/utils/format\";\nimport useLocalI18n, { useDirection } from \"~/composables/useLocalI18n\";\nimport { chat } from \"@i18n/locales\";\nimport useCall from \"~/composables/useCall\";\nimport { useSpeaking } from \"~/composables/call/useSpeaking\";\nimport { useDraggable, useEventListener, useWindowSize } from \"@vueuse/core\";\nimport { ref, computed, watch, onMounted, nextTick } from \"vue\";\nimport Avatar from \"primevue/avatar\";\nimport Button from \"primevue/button\";\nimport Menu from \"primevue/menu\";\nimport Tooltip from \"primevue/tooltip\";\nimport type { MenuItem } from \"primevue/menuitem\";\nimport CallButton from \"./CallButton.vue\";\nimport CallIcon from \"./CallIcon.vue\";\n\nconst vTooltip = Tooltip;\n\nconst callStore = useCallStore();\nconst minimizedRef = ref<HTMLElement | null>(null);\nconst bodyRef = ref<HTMLElement | null>(null);\n\nconst { t } = useLocalI18n(chat);\nconst { dir } = useDirection();\n\n// Named after whoever is on the other end of the conversation the call belongs to.\nconst chatStore = useChatStore();\nconst callTitle = computed(() => {\n const contact = callStore.channelId ? chatStore.getContactById(callStore.channelId) : null;\n const name = contact ? `${contact.name} ${contact.lastName ?? \"\"}`.trim() : \"\";\n return name || t(\"chat.call.title\");\n});\n\nconst {\n toggleVideoPause,\n toggleRemote,\n participantCount,\n endCall,\n toggleFullscreen,\n toggleFlashlight,\n toggleScreenShare,\n toggleAudio,\n toggleVideo,\n switchCamera,\n isFlashlightSupported,\n tileCount,\n isAudioOn,\n isVideoOn,\n isFlashlightOn,\n isFullscreen,\n isScreenSharing,\n showControls,\n resetControlsTimeout,\n cameras,\n videoPaused,\n localStream,\n localVideo,\n localScreen,\n remoteParents,\n remoteRefs,\n remoteScreens,\n remoteScreenRefs,\n remoteVideos,\n soundBlocked,\n enableSound,\n} = useCall();\n\n// --- Controls ---\n\n// The call screen is dark whatever the host's colour scheme, so its controls use fixed tokens\n// instead of the theme's: translucent white at rest, white when a feature is on (Meet's \"lit\"),\n// red when the microphone or camera is off.\nconst translucent = {\n background: \"rgb(255 255 255 / 0.12)\",\n hoverBackground: \"rgb(255 255 255 / 0.2)\",\n activeBackground: \"rgb(255 255 255 / 0.28)\",\n borderColor: \"transparent\",\n hoverBorderColor: \"transparent\",\n activeBorderColor: \"transparent\",\n color: \"#ffffff\",\n hoverColor: \"#ffffff\",\n activeColor: \"#ffffff\",\n};\nconst lit = {\n background: \"#ffffff\",\n hoverBackground: \"rgb(255 255 255 / 0.9)\",\n activeBackground: \"rgb(255 255 255 / 0.8)\",\n borderColor: \"#ffffff\",\n hoverBorderColor: \"#ffffff\",\n activeBorderColor: \"#ffffff\",\n color: \"#171717\",\n hoverColor: \"#171717\",\n activeColor: \"#171717\",\n};\n// Tailwind's red-500 to red-700.\nconst off = {\n background: \"#ef4444\",\n hoverBackground: \"#dc2626\",\n activeBackground: \"#b91c1c\",\n borderColor: \"transparent\",\n hoverBorderColor: \"transparent\",\n activeBorderColor: \"transparent\",\n color: \"#ffffff\",\n hoverColor: \"#ffffff\",\n activeColor: \"#ffffff\",\n};\nconst callScheme = { root: { secondary: translucent, contrast: lit, danger: off } };\nconst callButtonDt = { colorScheme: { light: callScheme, dark: callScheme } };\n\n// Its menus are dark too, Tailwind's neutral-800 under white text, in either host scheme.\nconst callMenuDt = {\n root: { background: \"#262626\", borderColor: \"rgb(255 255 255 / 0.1)\", color: \"#f5f5f5\" },\n item: {\n focusBackground: \"rgb(255 255 255 / 0.1)\",\n color: \"#f5f5f5\",\n focusColor: \"#ffffff\",\n icon: { color: \"#a3a3a3\", focusColor: \"#ffffff\" },\n },\n submenuLabel: { background: \"transparent\", color: \"#a3a3a3\" },\n};\n\n// Pills, as in Google Meet: wider than tall, so the bar reads as one row of controls.\nconst barButton = {\n dt: callButtonDt,\n text: false,\n size: \"large\",\n iconClass: \"size-6\",\n class: \"h-12! w-12! sm:w-14!\",\n} as const;\n\n// Tile actions sit on the video: small round buttons, shown on hover or focus where there is a\n// pointer that hovers, always on touch screens.\nconst tileButton = {\n dt: callButtonDt,\n text: false,\n size: \"small\",\n iconClass: \"size-4.5\",\n class: \"size-9!\",\n} as const;\nconst tileActions =\n \"absolute end-2 bottom-2 z-20 flex items-center gap-x-1.5 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none [@media(hover:none)]:opacity-100\";\nconst nameChip =\n \"max-w-[60%] truncate rounded-md bg-black/55 px-2 py-0.5 text-label-sm text-white backdrop-blur-sm select-none\";\n\n// Meet's shortcuts, on the tooltip and in the keyboard: Ctrl+D the microphone, Ctrl+E the camera.\nconst isMac = typeof navigator !== \"undefined\" && /Mac|iPhone|iPad/.test(navigator.platform);\nconst keys = (key: string) => (isMac ? `⌘ ${key}` : `Ctrl + ${key}`);\nconst withKeys = (label: string, key: string) => `${label} (${keys(key)})`;\n// Tooltips are appended to <body>, outside the chat, so they take its font and reset with them.\nconst tip = (value: string) => ({ value, class: \"vue-chat font-chat-family\" });\n\nconst audioLabel = computed(() =>\n isAudioOn.value ? t(\"chat.call.controls.mute\") : t(\"chat.call.controls.unmute\"),\n);\nconst videoLabel = computed(() =>\n isVideoOn.value ? t(\"chat.call.controls.cameraOff\") : t(\"chat.call.controls.cameraOn\"),\n);\nconst shareLabel = computed(() =>\n isScreenSharing.value\n ? t(\"chat.call.controls.stopSharing\")\n : t(\"chat.call.controls.shareScreen\"),\n);\nconst fullscreenLabel = computed(() =>\n isFullscreen.value\n ? t(\"chat.call.controls.exitFullscreen\")\n : t(\"chat.call.controls.fullscreen\"),\n);\n\nuseEventListener(window, \"keydown\", (event: KeyboardEvent) => {\n if (!callStore.isActive || callStore.isMinimized) return;\n if (!(isMac ? event.metaKey : event.ctrlKey) || event.altKey || event.shiftKey) return;\n const key = event.key.toLowerCase();\n if (key !== \"d\" && key !== \"e\") return;\n // Both are browser shortcuts too (bookmark, search), which the call takes over while it's open.\n event.preventDefault();\n if (key === \"d\") toggleAudio();\n else toggleVideo();\n});\n\n// The camera in use: read off the track when the call starts, then whatever was picked.\nconst currentCameraId = ref<string | null>(null);\nwatch(\n localStream,\n (stream) => {\n currentCameraId.value = stream?.getVideoTracks()[0]?.getSettings().deviceId ?? null;\n },\n { immediate: true },\n);\n\nconst cameraMenu = ref<InstanceType<typeof Menu> | null>(null);\nconst cameraItems = computed<MenuItem[]>(() => [\n {\n label: t(\"chat.call.controls.cameras\"),\n items: cameras.value.map((camera, index) => ({\n label: camera.label || `${t(\"chat.call.controls.chooseCamera\")} ${index + 1}`,\n callIcon: camera.deviceId === currentCameraId.value ? \"check\" : undefined,\n command: () => {\n currentCameraId.value = camera.deviceId;\n void switchCamera(camera.deviceId);\n },\n })),\n },\n]);\n\nconst moreMenu = ref<InstanceType<typeof Menu> | null>(null);\nconst moreItems = computed<MenuItem[]>(() => [\n {\n label: fullscreenLabel.value,\n callIcon: isFullscreen.value ? \"fullscreenExit\" : \"fullscreen\",\n command: () => toggleFullscreen(),\n },\n ...(isFlashlightSupported.value\n ? [\n {\n label: isFlashlightOn.value\n ? t(\"chat.call.controls.flashlightOff\")\n : t(\"chat.call.controls.flashlightOn\"),\n callIcon: isFlashlightOn.value ? \"flashlightOff\" : \"flashlightOn\",\n command: () => toggleFlashlight(),\n },\n ]\n : []),\n]);\n\n// --- Speaking ---\n\nconst speaking = useSpeaking(() => ({\n self: isAudioOn.value ? localStream.value : null,\n ...Object.fromEntries(\n Object.entries(remoteVideos.value).map(([id, remote]) => [id, remote.stream]),\n ),\n}));\nconst speakingRing = (on: boolean | undefined) =>\n on ? \"ring-sky-400\" : \"ring-transparent\";\n\n// --- Picture-in-picture ---\n\n// Minimized, the call plays live behind its controls: the remote participant on show, or the\n// user's own camera when nobody else is there.\nconst pipVideoRef = ref<HTMLVideoElement | null>(null);\nconst activeRemoteIndex = ref(0);\n\nconst remoteVideoEntries = computed(() => Object.entries(remoteVideos.value));\nconst hasRemoteVideos = computed(() => remoteVideoEntries.value.length > 0);\nconst activeRemoteUserId = computed<string | null>(() => {\n const entries = remoteVideoEntries.value;\n if (entries.length === 0) return null;\n return entries[activeRemoteIndex.value % entries.length][0];\n});\n\nconst pipStream = computed<MediaStream | null>(() => {\n if (hasRemoteVideos.value) {\n const id = activeRemoteUserId.value;\n return id ? (remoteVideos.value[id]?.stream ?? null) : null;\n }\n return localStream.value ?? null;\n});\n\nfunction cycleRemote() {\n const count = remoteVideoEntries.value.length;\n if (count === 0) return;\n activeRemoteIndex.value = (activeRemoteIndex.value + 1) % count;\n}\n\nwatch(\n [pipStream, () => callStore.isMinimized],\n async () => {\n await nextTick();\n const el = pipVideoRef.value;\n if (!el) return;\n const stream = pipStream.value;\n if (stream && el.srcObject !== stream) {\n el.srcObject = stream;\n el.play().catch(() => {});\n } else if (!stream && el.srcObject) {\n el.srcObject = null;\n }\n },\n { immediate: true },\n);\n\nonMounted(() => {\n bodyRef.value = document.body;\n});\n\n// Dragged anywhere, then snapped to the nearest corner on release.\nconst { width: windowWidth, height: windowHeight } = useWindowSize();\n\nconst PIP_WIDTH = 280; // w-70\nconst PIP_HEIGHT = 160; // h-40\nconst PADDING = 16;\n// Top and bottom corners stay this far from the edges, clear of the chat header and the composer.\nconst PIP_INSET_Y = 96;\n\nconst { x, y, isDragging } = useDraggable(minimizedRef, {\n initialValue: {\n x: typeof window !== \"undefined\" ? window.innerWidth - PIP_WIDTH - PADDING : PADDING,\n y: PIP_INSET_Y,\n },\n disabled: computed(() => !callStore.isMinimized),\n});\n\nwatch(isDragging, (dragging) => {\n if (!dragging && callStore.isMinimized) {\n const maxX = windowWidth.value - PIP_WIDTH - PADDING;\n const maxY = windowHeight.value - PIP_HEIGHT - PIP_INSET_Y;\n x.value = x.value < windowWidth.value / 2 ? PADDING : maxX;\n y.value = y.value < windowHeight.value / 2 ? PIP_INSET_Y : maxY;\n }\n});\n\n// Each time it is minimized it starts in the top corner on the reading end.\nwatch(\n () => callStore.isMinimized,\n (isMinimized) => {\n if (isMinimized) {\n nextTick(() => {\n const isRtl = dir.value === \"rtl\";\n x.value = isRtl ? PADDING : windowWidth.value - PIP_WIDTH - PADDING;\n // The top corner, where it covers older messages rather than the composer.\n y.value = PIP_INSET_Y;\n });\n }\n },\n { immediate: true },\n);\n\n// Kept on screen whatever the window does.\nconst clampedStyle = computed(() => {\n if (!callStore.isMinimized) return {};\n\n const maxX = windowWidth.value - PIP_WIDTH - PADDING;\n const maxY = windowHeight.value - PIP_HEIGHT - PADDING;\n\n return {\n left: `${Math.max(PADDING, Math.min(x.value, maxX))}px`,\n top: `${Math.max(PADDING, Math.min(y.value, maxY))}px`,\n };\n});\n</script>\n\n<template>\n <!-- Picture-in-picture: the call shrunk to a draggable window over the app. -->\n <div\n v-if=\"callStore.isActive && callStore.isMinimized\"\n ref=\"minimizedRef\"\n data-testid=\"call-pip\"\n :style=\"clampedStyle\"\n :dir=\"dir\"\n class=\"vue-chat font-chat-family fixed z-9999 h-40 w-70 cursor-move touch-none overflow-hidden rounded-2xl bg-neutral-900 shadow-2xl ring-1 ring-white/10\"\n :class=\"[!isDragging && 'transition-all duration-300 ease-out motion-reduce:transition-none']\"\n >\n <video\n ref=\"pipVideoRef\"\n muted\n autoplay\n playsinline\n class=\"pointer-events-none absolute inset-0 size-full object-cover\"\n />\n <div\n class=\"pointer-events-none absolute inset-0 bg-linear-to-t from-black/60 via-transparent to-black/30\"\n />\n\n <div class=\"absolute inset-x-3 top-3 flex items-center justify-between\">\n <div\n class=\"flex items-center gap-x-2 rounded-full bg-black/45 px-3 py-1.5 text-label-sm text-white backdrop-blur-sm select-none\"\n >\n <span class=\"relative flex size-2.5\">\n <span class=\"absolute inline-flex size-full animate-ping rounded-full bg-red-500/60 motion-reduce:animate-none\" />\n <span class=\"relative inline-flex size-2.5 rounded-full bg-red-500\" />\n </span>\n <span dir=\"ltr\" class=\"tabular-nums\">{{ formatDuration(callStore.elapsedTime) }}</span>\n </div>\n\n <CallButton\n icon=\"callEnd\"\n :label=\"t('chat.call.controls.endCall')\"\n severity=\"danger\"\n :dt=\"callButtonDt\"\n :text=\"false\"\n icon-class=\"size-5\"\n class=\"h-9! w-12!\"\n data-testid=\"call-pip-end\"\n @pointerdown.stop\n @click.stop=\"endCall\"\n />\n </div>\n\n <div class=\"absolute inset-x-3 bottom-3 flex items-center justify-between\">\n <div class=\"flex items-center gap-1.5\">\n <Button\n :label=\"String(participantCount)\"\n :aria-label=\"t('chat.call.controls.nextParticipant')\"\n :disabled=\"!hasRemoteVideos\"\n :dt=\"callButtonDt\"\n severity=\"secondary\"\n size=\"small\"\n rounded\n class=\"h-8!\"\n @pointerdown.stop\n @click.stop=\"cycleRemote\"\n >\n <template #icon>\n <CallIcon name=\"group\" class=\"size-4\" />\n </template>\n </Button>\n\n <span\n v-if=\"!isAudioOn\"\n class=\"flex size-8 items-center justify-center rounded-full bg-red-500 text-white\"\n >\n <CallIcon name=\"micOff\" class=\"size-4\" />\n </span>\n <span\n v-if=\"!isVideoOn\"\n class=\"flex size-8 items-center justify-center rounded-full bg-red-500 text-white\"\n >\n <CallIcon name=\"videocamOff\" class=\"size-4\" />\n </span>\n </div>\n\n <CallButton\n icon=\"openInFull\"\n :label=\"t('chat.call.controls.maximize')\"\n :dt=\"callButtonDt\"\n :text=\"false\"\n icon-class=\"size-4.5\"\n class=\"size-9!\"\n data-testid=\"call-maximize\"\n @pointerdown.stop\n @click.stop=\"callStore.maximize()\"\n />\n </div>\n </div>\n\n <!-- The full call screen. -->\n <div\n v-show=\"callStore.isActive && !callStore.isMinimized\"\n data-testid=\"call-view\"\n :dir=\"dir\"\n class=\"vue-chat font-chat-family fixed inset-0 z-60 flex size-full flex-col bg-neutral-900 text-white\"\n >\n <!-- Stage -->\n <div\n class=\"relative min-h-0 flex-1 px-3 pt-16 pb-2 md:p-4\"\n @mousemove=\"resetControlsTimeout\"\n >\n <!-- The browser blocked the others' sound until a tap: they play muted until then. -->\n <Button\n v-if=\"soundBlocked\"\n :label=\"t('chat.call.controls.enableSound')\"\n :dt=\"callButtonDt\"\n severity=\"contrast\"\n rounded\n data-testid=\"call-enable-sound\"\n class=\"absolute! top-6 left-1/2 z-30 -translate-x-1/2 shadow-lg\"\n @click=\"enableSound\"\n >\n <template #icon>\n <CallIcon name=\"volumeUp\" class=\"size-5\" />\n </template>\n </Button>\n\n <div\n v-show=\"tileCount\"\n class=\"grid size-full min-h-0 min-w-0 grid-cols-1 gap-3 md:grid-cols-[repeat(auto-fit,minmax(300px,1fr))] md:gap-4\"\n >\n <!-- Own screen share -->\n <div\n v-show=\"isScreenSharing\"\n :ref=\"(el) => (remoteParents['self_screen'] = el as any)\"\n class=\"group relative flex min-h-0 overflow-hidden rounded-2xl bg-neutral-800\"\n >\n <video\n ref=\"localScreen\"\n autoplay\n muted\n playsinline\n class=\"absolute inset-0 size-full object-contain\"\n />\n <div class=\"absolute start-2 bottom-2 z-20 flex max-w-[60%] items-center gap-x-1.5\">\n <span class=\"flex size-7 shrink-0 items-center justify-center rounded-full bg-black/55 backdrop-blur-sm\">\n <CallIcon name=\"presentToAll\" class=\"size-4\" />\n </span>\n <span :class=\"nameChip\">{{ t(\"chat.call.yourPresentation\") }}</span>\n </div>\n <div :class=\"tileActions\">\n <CallButton\n :icon=\"videoPaused['self_screen'] ? 'play' : 'pause'\"\n :label=\"videoPaused['self_screen'] ? t('chat.call.controls.playVideo') : t('chat.call.controls.pauseVideo')\"\n v-bind=\"tileButton\"\n @click=\"toggleVideoPause('self_screen', localScreen as any)\"\n />\n <CallButton\n :icon=\"isFullscreen ? 'fullscreenExit' : 'fullscreen'\"\n :label=\"fullscreenLabel\"\n v-bind=\"tileButton\"\n @click=\"toggleRemote('self_screen')\"\n />\n </div>\n </div>\n\n <!-- Remote cameras -->\n <div\n v-for=\"(remote, remoteUserId) in remoteVideos\"\n :key=\"`remote-${remoteUserId}`\"\n data-testid=\"call-remote-video\"\n :ref=\"(el) => (remoteParents[`remote_video_${remoteUserId}`] = el as any)\"\n class=\"group relative flex min-h-0 overflow-hidden rounded-2xl bg-neutral-800 ring-3 ring-inset transition-shadow motion-reduce:transition-none\"\n :class=\"speakingRing(speaking[remoteUserId])\"\n >\n <video\n :ref=\"(el) => { if (el) remoteRefs[remoteUserId] = el as any; }\"\n autoplay\n playsinline\n class=\"absolute inset-0 size-full object-cover\"\n />\n <span :class=\"[nameChip, 'absolute start-2 bottom-2 z-20']\">\n <bdi>{{ remote.name }}</bdi>\n </span>\n <div :class=\"tileActions\">\n <CallButton\n :icon=\"videoPaused[`remote_video_${remoteUserId}`] ? 'play' : 'pause'\"\n :label=\"videoPaused[`remote_video_${remoteUserId}`] ? t('chat.call.controls.playVideo') : t('chat.call.controls.pauseVideo')\"\n v-bind=\"tileButton\"\n @click=\"toggleVideoPause(`remote_video_${remoteUserId}`, remoteRefs[remoteUserId] as any)\"\n />\n <CallButton\n :icon=\"isFullscreen ? 'fullscreenExit' : 'fullscreen'\"\n :label=\"fullscreenLabel\"\n v-bind=\"tileButton\"\n @click=\"toggleRemote(`remote_video_${remoteUserId}`)\"\n />\n </div>\n </div>\n\n <!-- Remote screen shares -->\n <div\n v-for=\"(remote, remoteUserId) in remoteScreens\"\n :key=\"`remote-screen-${remoteUserId}`\"\n data-testid=\"call-remote-screen\"\n :ref=\"(el) => (remoteParents[`remote_screen_${remoteUserId}`] = el as any)\"\n class=\"group relative flex min-h-0 overflow-hidden rounded-2xl bg-neutral-800\"\n >\n <video\n :ref=\"(el) => { if (el) remoteScreenRefs[remoteUserId] = el as any; }\"\n autoplay\n muted\n playsinline\n class=\"absolute inset-0 size-full object-contain\"\n />\n <div class=\"absolute start-2 bottom-2 z-20 flex max-w-[60%] items-center gap-x-1.5\">\n <span class=\"flex size-7 shrink-0 items-center justify-center rounded-full bg-black/55 backdrop-blur-sm\">\n <CallIcon name=\"presentToAll\" class=\"size-4\" />\n </span>\n <span :class=\"nameChip\">\n {{ t(\"chat.call.presentationOf\", { name: remote.name }) }}\n </span>\n </div>\n <div :class=\"tileActions\">\n <CallButton\n :icon=\"videoPaused[`remote_screen_${remoteUserId}`] ? 'play' : 'pause'\"\n :label=\"videoPaused[`remote_screen_${remoteUserId}`] ? t('chat.call.controls.playVideo') : t('chat.call.controls.pauseVideo')\"\n v-bind=\"tileButton\"\n @click=\"toggleVideoPause(`remote_screen_${remoteUserId}`, remoteScreenRefs[remoteUserId] || null)\"\n />\n <CallButton\n :icon=\"isFullscreen ? 'fullscreenExit' : 'fullscreen'\"\n :label=\"fullscreenLabel\"\n v-bind=\"tileButton\"\n @click=\"toggleRemote(`remote_screen_${remoteUserId}`)\"\n />\n </div>\n </div>\n </div>\n\n <!-- Own camera: the whole stage when alone, a small floating tile once others show. -->\n <div\n :ref=\"(el) => (remoteParents['self_cam'] = el as any)\"\n class=\"group overflow-hidden rounded-2xl bg-neutral-800 ring-3 ring-inset transition-shadow [clip-path:inset(0_round_var(--radius-2xl))] motion-reduce:transition-none\"\n :class=\"[\n tileCount\n ? 'absolute end-5 bottom-4 z-10 aspect-video w-36 sm:w-56 md:end-6 md:bottom-6 md:w-64'\n : 'relative size-full',\n speakingRing(speaking.self),\n ]\"\n >\n <video\n ref=\"localVideo\"\n data-testid=\"call-local-video\"\n autoplay\n muted\n playsinline\n class=\"pointer-events-none absolute inset-0 size-full -scale-x-100 rounded-[inherit] object-cover\"\n />\n\n <div\n v-if=\"!isVideoOn\"\n class=\"absolute inset-0 flex flex-col items-center justify-center gap-y-2 bg-neutral-800\"\n >\n <Avatar\n :label=\"t('chat.call.you').slice(0, 1)\"\n shape=\"circle\"\n :size=\"tileCount ? 'large' : 'xlarge'\"\n class=\"bg-sky-600! text-white! select-none\"\n />\n <p v-if=\"!tileCount\" class=\"text-label-md text-neutral-300 select-none\">\n {{ t(\"chat.call.cameraIsOff\") }}\n </p>\n </div>\n\n <span\n v-if=\"!isAudioOn\"\n class=\"absolute end-2 top-2 z-20 flex size-7 items-center justify-center rounded-full bg-red-500 text-white\"\n :title=\"t('chat.call.controls.unmute')\"\n >\n <CallIcon name=\"micOff\" class=\"size-4\" />\n </span>\n\n <span :class=\"[nameChip, 'absolute start-2 bottom-2 z-20']\">{{ t(\"chat.call.you\") }}</span>\n\n <div v-if=\"!tileCount\" :class=\"tileActions\">\n <CallButton\n :icon=\"videoPaused['self_cam'] ? 'play' : 'pause'\"\n :label=\"videoPaused['self_cam'] ? t('chat.call.controls.playVideo') : t('chat.call.controls.pauseVideo')\"\n v-bind=\"tileButton\"\n @click=\"toggleVideoPause('self_cam', localVideo as any)\"\n />\n </div>\n </div>\n </div>\n\n <!-- Control bar: time and title, the controls, then the people and minimize. On phones the\n two sides move to the top of the screen, leaving the controls a row of their own. -->\n <div\n class=\"grid h-20 shrink-0 grid-cols-1 items-center px-3 transition-opacity duration-300 motion-reduce:transition-none md:relative md:grid-cols-[1fr_auto_1fr] md:px-6\"\n :class=\"showControls ? 'opacity-100' : 'opacity-0'\"\n @mouseenter=\"resetControlsTimeout\"\n @mousemove=\"resetControlsTimeout\"\n >\n <div\n class=\"absolute start-4 top-4 flex min-w-0 items-center gap-x-3 text-body-md select-none md:static\"\n >\n <span dir=\"ltr\" class=\"tabular-nums\">{{ formatDuration(callStore.elapsedTime) }}</span>\n <span class=\"hidden h-4 w-px bg-white/30 md:block\" />\n <span class=\"hidden truncate md:block\">{{ callTitle }}</span>\n </div>\n\n <div class=\"flex items-center justify-center gap-x-2 sm:gap-x-3\">\n <CallButton\n v-tooltip.top=\"tip(withKeys(audioLabel, 'D'))\"\n :icon=\"isAudioOn ? 'mic' : 'micOff'\"\n :label=\"audioLabel\"\n :severity=\"isAudioOn ? 'secondary' : 'danger'\"\n :aria-keyshortcuts=\"isMac ? 'Meta+D' : 'Control+D'\"\n v-bind=\"barButton\"\n data-testid=\"call-toggle-audio\"\n :data-active=\"isAudioOn\"\n @click=\"toggleAudio\"\n />\n\n <!-- The camera, with Meet's caret for picking which one when there are several. -->\n <div class=\"flex items-center rounded-full\" :class=\"cameras.length > 1 && 'bg-white/12'\">\n <CallButton\n v-if=\"cameras.length > 1\"\n v-tooltip.top=\"tip(t('chat.call.controls.chooseCamera'))\"\n icon=\"arrowDropUp\"\n :label=\"t('chat.call.controls.chooseCamera')\"\n :dt=\"callButtonDt\"\n text\n severity=\"secondary\"\n icon-class=\"size-6\"\n class=\"h-12! w-8! rounded-e-none! ps-1!\"\n aria-haspopup=\"true\"\n @click=\"cameraMenu?.toggle($event)\"\n />\n <CallButton\n v-tooltip.top=\"tip(withKeys(videoLabel, 'E'))\"\n :icon=\"isVideoOn ? 'videocam' : 'videocamOff'\"\n :label=\"videoLabel\"\n :severity=\"isVideoOn ? 'secondary' : 'danger'\"\n :aria-keyshortcuts=\"isMac ? 'Meta+E' : 'Control+E'\"\n v-bind=\"barButton\"\n data-testid=\"call-toggle-video\"\n :data-active=\"isVideoOn\"\n @click=\"toggleVideo\"\n />\n </div>\n\n <CallButton\n v-tooltip.top=\"tip(shareLabel)\"\n :icon=\"isScreenSharing ? 'cancelPresentation' : 'presentToAll'\"\n :label=\"shareLabel\"\n :severity=\"isScreenSharing ? 'contrast' : 'secondary'\"\n v-bind=\"barButton\"\n data-testid=\"call-toggle-screen\"\n :data-active=\"isScreenSharing\"\n @click=\"toggleScreenShare\"\n />\n\n <CallButton\n v-tooltip.top=\"tip(t('chat.call.controls.more'))\"\n icon=\"moreVert\"\n :label=\"t('chat.call.controls.more')\"\n v-bind=\"barButton\"\n class=\"h-12! w-10! sm:w-12!\"\n aria-haspopup=\"true\"\n data-testid=\"call-more\"\n @click=\"moreMenu?.toggle($event)\"\n />\n\n <CallButton\n v-tooltip.top=\"tip(t('chat.call.controls.endCall'))\"\n icon=\"callEnd\"\n :label=\"t('chat.call.controls.endCall')\"\n severity=\"danger\"\n :dt=\"callButtonDt\"\n :text=\"false\"\n size=\"large\"\n icon-class=\"size-6\"\n class=\"h-12! w-16! sm:w-18!\"\n data-testid=\"call-end\"\n @click=\"endCall\"\n />\n </div>\n\n <div class=\"absolute end-3 top-2.5 flex items-center justify-end gap-x-2 md:static\">\n <div\n data-testid=\"call-participants\"\n class=\"flex h-10 items-center gap-x-1.5 rounded-full bg-white/12 px-3 text-label-md select-none\"\n :title=\"t('chat.call.participants', participantCount)\"\n >\n <CallIcon name=\"group\" class=\"size-5\" />\n <span aria-hidden=\"true\">{{ participantCount }}</span>\n <span class=\"sr-only\">{{ t(\"chat.call.participants\", participantCount) }}</span>\n </div>\n <CallButton\n v-tooltip.top=\"tip(t('chat.call.controls.minimize'))\"\n icon=\"pictureInPicture\"\n :label=\"t('chat.call.controls.minimize')\"\n :dt=\"callButtonDt\"\n :text=\"false\"\n icon-class=\"size-5\"\n class=\"size-10!\"\n data-testid=\"call-minimize\"\n @click=\"callStore.minimize\"\n />\n </div>\n </div>\n\n <Menu ref=\"cameraMenu\" :model=\"cameraItems\" popup :dir=\"dir\" :dt=\"callMenuDt\" class=\"vue-chat\">\n <template #itemicon=\"{ item }\">\n <CallIcon v-if=\"item.callIcon\" :name=\"item.callIcon\" class=\"size-5 text-sky-400\" />\n <span v-else class=\"size-5\" />\n </template>\n </Menu>\n <Menu ref=\"moreMenu\" :model=\"moreItems\" popup :dir=\"dir\" :dt=\"callMenuDt\" class=\"vue-chat\">\n <template #itemicon=\"{ item }\">\n <CallIcon :name=\"item.callIcon\" class=\"size-5 text-neutral-400\" />\n </template>\n </Menu>\n </div>\n</template>\n"],"names":["_createElementBlock","_openBlock","_createBlock","_unref","_mergeProps","$attrs","_createVNode","CallIcon","_normalizeClass","_createElementVNode","_toDisplayString","CallButton","_withModifiers","_withDirectives","_Fragment","_renderList","_withCtx","_vShow"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Call-DY7-rM16.mjs","sources":["../../app/composables/call/useCallUi.ts","../../app/composables/useCall.ts","../../app/composables/call/useSpeaking.ts","../../app/components/call/CallIcon.vue","../../app/components/call/CallButton.vue","../../app/components/call/Call.vue"],"sourcesContent":["import { nextTick, onMounted, onUnmounted, ref, watch, type Ref } from \"vue\";\nimport type { RemoteStream } from \"./peers\";\n\nexport interface CallUiOptions {\n localStream: Ref<MediaStream | null>;\n screenStream: Ref<MediaStream | null>;\n remoteVideos: Ref<Record<string, RemoteStream>>;\n remoteScreens: Ref<Record<string, RemoteStream>>;\n /** Re-attach streams when this changes: minimizing swaps the <video> elements. */\n isMinimized: () => boolean;\n}\n\nconst CONTROLS_HIDE_AFTER_MS = 3000;\n\n/** The call screen's view state, and keeping each <video> element showing the right stream. */\nexport function useCallUi(opts: CallUiOptions) {\n const { localStream, screenStream, remoteVideos, remoteScreens } = opts;\n\n // Template refs, bound by Call.vue.\n const localVideo = ref<HTMLVideoElement | null>(null);\n const localScreen = ref<HTMLVideoElement | null>(null);\n const remoteRefs = ref<Record<string, HTMLVideoElement | null>>({});\n const remoteScreenRefs = ref<Record<string, HTMLVideoElement | undefined>>({});\n const remoteParents = ref<Record<string, HTMLElement>>({});\n\n // --- Controls fade out after a few seconds without input ---\n const showControls = ref(true);\n let controlsTimeout: ReturnType<typeof setTimeout> | undefined;\n function resetControlsTimeout() {\n showControls.value = true;\n clearTimeout(controlsTimeout);\n controlsTimeout = setTimeout(\n () => (showControls.value = false),\n CONTROLS_HIDE_AFTER_MS,\n );\n }\n const inputEvents = [\"mousemove\", \"click\", \"keydown\"] as const;\n onMounted(() => {\n resetControlsTimeout();\n inputEvents.forEach((e) => document.addEventListener(e, resetControlsTimeout));\n });\n onUnmounted(() => {\n inputEvents.forEach((e) => document.removeEventListener(e, resetControlsTimeout));\n clearTimeout(controlsTimeout);\n // The call goes on; only this view lets go of its elements.\n detachAll();\n });\n\n // --- Fullscreen: the whole call, or a single tile ---\n const isFullscreen = ref(false);\n function toggleFullscreen(target: HTMLElement = document.documentElement) {\n if (!document.fullscreenElement) {\n void target.requestFullscreen?.();\n isFullscreen.value = true;\n } else {\n void document.exitFullscreen();\n isFullscreen.value = false;\n }\n }\n const toggleRemote = (tileId: string, el?: HTMLElement) => {\n const container = el ?? remoteParents.value[tileId];\n if (container) toggleFullscreen(container);\n };\n\n // --- Pausing a single tile ---\n const videoPaused = ref<Record<string, boolean>>({});\n function toggleVideoPause(tileId: string, el: HTMLVideoElement | null | undefined) {\n if (!(el instanceof HTMLVideoElement)) return;\n if (videoPaused.value[tileId]) void el.play();\n else el.pause();\n videoPaused.value[tileId] = !videoPaused.value[tileId];\n }\n\n // --- Keep each <video> showing its stream ---\n /** The browser refused to play a remote participant with sound until the user taps something. */\n const soundBlocked = ref(false);\n\n async function play(el: HTMLVideoElement) {\n try {\n await el.play();\n } catch (err) {\n if ((err as DOMException)?.name !== \"NotAllowedError\" || el.muted) return;\n // Mobile browsers (and desktop ones without prior interaction) refuse unmuted playback\n // that doesn't follow a tap, which would leave the tile black. Show the video muted and\n // offer a button to turn the sound on.\n el.muted = true;\n soundBlocked.value = true;\n await el.play().catch((e) => console.error(\"[vue-chat] Remote video can't play:\", e));\n }\n }\n\n /** Unmutes the remote participants; must run from a user gesture. */\n function enableSound() {\n soundBlocked.value = false;\n for (const el of Object.values(remoteRefs.value)) {\n if (!el) continue;\n el.muted = false;\n void play(el);\n }\n }\n\n const attach = (el: HTMLVideoElement | null | undefined, stream: MediaStream) => {\n if (!el) return;\n if (el.srcObject !== stream) el.srcObject = stream;\n void play(el);\n };\n\n watch(\n [localStream, opts.isMinimized],\n async () => {\n await nextTick();\n if (localStream.value && localVideo.value)\n localVideo.value.srcObject = localStream.value;\n },\n { immediate: true },\n );\n watch(\n [screenStream, opts.isMinimized],\n async () => {\n await nextTick();\n if (localScreen.value) localScreen.value.srcObject = screenStream.value;\n },\n { immediate: true },\n );\n watch(\n [() => ({ ...remoteVideos.value }), opts.isMinimized],\n async () => {\n await nextTick();\n for (const [id, { stream }] of Object.entries(remoteVideos.value))\n attach(remoteRefs.value[id], stream);\n },\n { immediate: true },\n );\n watch(\n [() => ({ ...remoteScreens.value }), opts.isMinimized],\n async () => {\n await nextTick();\n for (const [id, { stream }] of Object.entries(remoteScreens.value))\n attach(remoteScreenRefs.value[id], stream);\n },\n { immediate: true },\n );\n\n /** Detaches every <video>, so no element keeps a stopped stream alive. */\n function detachAll() {\n const all = [\n localVideo.value,\n localScreen.value,\n ...Object.values(remoteRefs.value),\n ...Object.values(remoteScreenRefs.value),\n ];\n for (const el of all) if (el) el.srcObject = null;\n }\n\n return {\n localVideo,\n localScreen,\n remoteRefs,\n remoteScreenRefs,\n remoteParents,\n showControls,\n resetControlsTimeout,\n isFullscreen,\n toggleFullscreen: () => toggleFullscreen(),\n toggleRemote,\n videoPaused,\n toggleVideoPause,\n soundBlocked,\n enableSound,\n detachAll,\n };\n}\n","import { ref } from \"vue\";\nimport { useCallStore } from \"~/stores/callStore\";\nimport { useCallUi } from \"./call/useCallUi\";\n\n/**\n * The view side of the running call, for Call.vue. The call itself (signalling, peers, media)\n * lives in the call store, so unmounting this view doesn't end it.\n */\nexport default function useCall() {\n const callStore = useCallStore();\n const session = callStore.session;\n if (!session) {\n throw new Error(\"[vue-chat] useCall() needs a running call: callStore.startCall() first\");\n }\n const { media, peers } = session;\n\n const ui = useCallUi({\n localStream: media.localStream,\n screenStream: media.screenStream,\n remoteVideos: peers.remoteVideos,\n remoteScreens: peers.remoteScreens,\n isMinimized: () => callStore.isMinimized,\n });\n\n async function switchCamera(deviceId: string) {\n const stream = await session!.switchCamera(deviceId);\n // Same stream object with a new track: the preview has to be told.\n if (stream && ui.localVideo.value) ui.localVideo.value.srcObject = stream;\n }\n\n return {\n // Call state\n participantCount: session.participantCount,\n tileCount: session.tileCount,\n localStream: media.localStream,\n remoteVideos: peers.remoteVideos,\n remoteScreens: peers.remoteScreens,\n // Local media\n cameras: media.cameras,\n isAudioOn: media.isAudioOn,\n isVideoOn: media.isVideoOn,\n isScreenSharing: media.isScreenSharing,\n isFlashlightOn: media.isFlashlightOn,\n isFlashlightSupported: media.isFlashlightSupported,\n toggleAudio: media.toggleAudio,\n toggleVideo: media.toggleVideo,\n toggleFlashlight: media.toggleFlashlight,\n toggleScreenShare: session.toggleScreenShare,\n switchCamera,\n endCall: callStore.endCall,\n // View\n showCameraModal: ref(false),\n showControls: ui.showControls,\n resetControlsTimeout: ui.resetControlsTimeout,\n isFullscreen: ui.isFullscreen,\n toggleFullscreen: ui.toggleFullscreen,\n toggleRemote: ui.toggleRemote,\n videoPaused: ui.videoPaused,\n soundBlocked: ui.soundBlocked,\n enableSound: ui.enableSound,\n toggleVideoPause: ui.toggleVideoPause,\n localVideo: ui.localVideo,\n localScreen: ui.localScreen,\n remoteRefs: ui.remoteRefs,\n remoteScreenRefs: ui.remoteScreenRefs,\n remoteParents: ui.remoteParents,\n };\n}\n","import { onBeforeUnmount, reactive, watch } from \"vue\";\n\n// RMS of the waveform (0–1) above which a voice counts as speaking, and how long it stays lit\n// after dropping below, so the ring doesn't flicker between words.\nconst THRESHOLD = 0.04;\nconst HOLD_MS = 400;\nconst POLL_MS = 120;\n\ninterface Meter {\n stream: MediaStream;\n source: MediaStreamAudioSourceNode;\n analyser: AnalyserNode;\n buffer: Uint8Array<ArrayBuffer>;\n lastLoud: number;\n}\n\n/**\n * Who is speaking, per tile id: a level meter on each stream's audio, through one shared\n * AudioContext. Ids whose stream is null, or has no audio track, are never speaking.\n */\nexport function useSpeaking(streams: () => Record<string, MediaStream | null | undefined>) {\n const speaking = reactive<Record<string, boolean>>({});\n const meters = new Map<string, Meter>();\n let context: AudioContext | null = null;\n let timer: ReturnType<typeof setInterval> | undefined;\n\n const drop = (id: string) => {\n const meter = meters.get(id);\n if (!meter) return;\n meter.source.disconnect();\n meters.delete(id);\n delete speaking[id];\n };\n\n const poll = () => {\n const now = performance.now();\n for (const [id, meter] of meters) {\n meter.analyser.getByteTimeDomainData(meter.buffer);\n let sum = 0;\n for (const sample of meter.buffer) {\n const centred = (sample - 128) / 128;\n sum += centred * centred;\n }\n if (Math.sqrt(sum / meter.buffer.length) > THRESHOLD) meter.lastLoud = now;\n const lit = now - meter.lastLoud < HOLD_MS;\n if (speaking[id] !== lit) speaking[id] = lit;\n }\n };\n\n watch(\n streams,\n (current) => {\n for (const id of [...meters.keys()]) {\n if (current[id] !== meters.get(id)!.stream) drop(id);\n }\n\n for (const [id, stream] of Object.entries(current)) {\n if (!stream || meters.has(id) || !stream.getAudioTracks().length) continue;\n if (typeof AudioContext === \"undefined\") return;\n context ??= new AudioContext();\n // Created after the call was started by a click, so it is normally running already.\n if (context.state === \"suspended\") void context.resume().catch(() => {});\n\n const source = context.createMediaStreamSource(stream);\n const analyser = context.createAnalyser();\n analyser.fftSize = 512;\n // Only measured, never routed to the speakers: the <video> elements play the sound.\n source.connect(analyser);\n meters.set(id, {\n stream,\n source,\n analyser,\n buffer: new Uint8Array(analyser.fftSize),\n lastLoud: 0,\n });\n }\n\n if (meters.size && !timer) timer = setInterval(poll, POLL_MS);\n if (!meters.size && timer) {\n clearInterval(timer);\n timer = undefined;\n }\n },\n { immediate: true, deep: 1 },\n );\n\n onBeforeUnmount(() => {\n clearInterval(timer);\n for (const id of [...meters.keys()]) drop(id);\n void context?.close().catch(() => {});\n });\n\n return speaking;\n}\n","<script setup lang=\"ts\">\n/**\n * The call screen's icons: Google's Material Symbols (Rounded, weight 400), the set Google Meet\n * uses, so the controls read the way people already know them. Only the icons the call needs are\n * inlined, as SVG paths, so the library takes no icon dependency for them.\n *\n * Material Symbols: Copyright Google LLC, Apache License 2.0\n * (https://github.com/google/material-design-icons/blob/master/LICENSE).\n */\nconst ICONS = {\n mic:\n \"<path fill=\\\"currentColor\\\" d=\\\"M9.875 13.125Q9 12.25 9 11V5q0-1.25.875-2.125T12 2t2.125.875T15 5v6q0 1.25-.875 2.125T12 14t-2.125-.875M11 20v-2.075q-2.3-.325-3.937-1.95t-1.988-3.95q-.05-.425.225-.725T6 11t.713.288T7.1 12q.35 1.75 1.738 2.875T12 16q1.8 0 3.175-1.137T16.9 12q.1-.425.388-.712T18 11t.7.3t.225.725q-.35 2.275-1.975 3.925T13 17.925V20q0 .425-.288.713T12 21t-.712-.288T11 20\\\"/>\",\n micOff:\n \"<path fill=\\\"currentColor\\\" d=\\\"M16.8 14.575q-.35-.2-.45-.612t.1-.763q.175-.275.288-.587t.162-.638q.1-.425.388-.7T18 11t.7.3t.225.725q-.075.575-.262 1.125t-.488 1.05q-.2.35-.612.463t-.763-.088m-3.5-4.125L9.575 6.725Q9.3 6.45 9.15 6.088T9 5.325V5q0-1.25.875-2.125T12 2t2.125.875T15 5v4.725q0 .675-.612.938T13.3 10.45M11 20v-2.1q-2.3-.3-3.937-1.925t-1.988-3.95q-.05-.425.225-.725T6 11t.713.288T7.1 12q.35 1.75 1.738 2.875T12 16q.85 0 1.613-.262T15 15l1.425 1.425q-.725.575-1.588.963T13 17.9V20q0 .425-.288.713T12 21t-.712-.288T11 20m8.1 1.9l-17-17q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l17 17q.275.275.275.7t-.275.7t-.7.275t-.7-.275\\\"/>\",\n videocam:\n \"<path fill=\\\"currentColor\\\" d=\\\"M4 20q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4h12q.825 0 1.413.588T18 6v4.5l3.15-3.15q.25-.25.55-.125t.3.475v8.6q0 .35-.3.475t-.55-.125L18 13.5V18q0 .825-.587 1.413T16 20z\\\"/>\",\n videocamOff:\n \"<path fill=\\\"currentColor\\\" d=\\\"m18 10.5l3.15-3.15q.25-.25.55-.125t.3.475v8.6q0 .35-.3.475t-.55-.125l-3.325-3.325q-.25.35-.712.425t-.813-.275L8.525 5.7q-.25-.25-.288-.525t.088-.55t.35-.45T9.25 4H16q.825 0 1.413.588T18 6zm1.85 12.15L1.35 4.15q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l18.5 18.5q.275.275.275.7t-.275.7t-.7.275t-.7-.275M4 4l14 14q0 .825-.587 1.413T16 20H4q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4\\\"/>\",\n presentToAll:\n \"<path fill=\\\"currentColor\\\" d=\\\"M11 11.825V15q0 .425.288.713T12 16t.713-.288T13 15v-3.15l.9.875q.3.275.7.288t.7-.288t.3-.712t-.3-.713l-2.6-2.6q-.3-.3-.7-.3t-.7.3l-2.6 2.6q-.3.3-.287.7t.312.7q.3.275.7.288t.7-.288zM4 20q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4h16q.825 0 1.413.588T22 6v12q0 .825-.587 1.413T20 20z\\\"/>\",\n cancelPresentation:\n \"<path fill=\\\"currentColor\\\" d=\\\"m10.6 12l-1.9 1.9q-.275.275-.275.7t.275.7t.7.275t.7-.275l1.9-1.9l1.9 1.9q.275.275.7.275t.7-.275t.275-.7t-.275-.7L13.4 12l1.9-1.9q.275-.275.275-.7t-.275-.7t-.7-.275t-.7.275L12 10.6l-1.9-1.9q-.275-.275-.7-.275t-.7.275t-.275.7t.275.7zM4 20q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4h16q.825 0 1.413.588T22 6v12q0 .825-.587 1.413T20 20z\\\"/>\",\n callEnd:\n \"<path fill=\\\"currentColor\\\" d=\\\"M12 8q2.95 0 5.813 1.188T22.9 12.75q.3.3.3.7t-.3.7l-2.3 2.25q-.275.275-.638.3t-.662-.2l-2.9-2.2q-.2-.15-.3-.35t-.1-.45v-2.85q-.95-.3-1.95-.475T12 10t-2.05.175T8 10.65v2.85q0 .25-.1.45t-.3.35l-2.9 2.2q-.3.225-.663.2t-.637-.3l-2.3-2.25q-.3-.3-.3-.7t.3-.7q2.2-2.375 5.075-3.562T12 8\\\"/>\",\n fullscreen:\n \"<path fill=\\\"currentColor\\\" d=\\\"M5 19h2q.425 0 .713.288T8 20t-.288.713T7 21H4q-.425 0-.712-.288T3 20v-3q0-.425.288-.712T4 16t.713.288T5 17zm14 0v-2q0-.425.288-.712T20 16t.713.288T21 17v3q0 .425-.288.713T20 21h-3q-.425 0-.712-.288T16 20t.288-.712T17 19zM5 5v2q0 .425-.288.713T4 8t-.712-.288T3 7V4q0-.425.288-.712T4 3h3q.425 0 .713.288T8 4t-.288.713T7 5zm14 0h-2q-.425 0-.712-.288T16 4t.288-.712T17 3h3q.425 0 .713.288T21 4v3q0 .425-.288.713T20 8t-.712-.288T19 7z\\\"/>\",\n fullscreenExit:\n \"<path fill=\\\"currentColor\\\" d=\\\"M6 18H4q-.425 0-.712-.288T3 17t.288-.712T4 16h3q.425 0 .713.288T8 17v3q0 .425-.288.713T7 21t-.712-.288T6 20zm12 0v2q0 .425-.288.713T17 21t-.712-.288T16 20v-3q0-.425.288-.712T17 16h3q.425 0 .713.288T21 17t-.288.713T20 18zM6 6V4q0-.425.288-.712T7 3t.713.288T8 4v3q0 .425-.288.713T7 8H4q-.425 0-.712-.288T3 7t.288-.712T4 6zm12 0h2q.425 0 .713.288T21 7t-.288.713T20 8h-3q-.425 0-.712-.288T16 7V4q0-.425.288-.712T17 3t.713.288T18 4z\\\"/>\",\n flashlightOn:\n \"<path fill=\\\"currentColor\\\" d=\\\"M6 5V4q0-.825.588-1.412T8 2h8q.825 0 1.413.588T18 4v1zm7.063 10.063q.437-.438.437-1.063t-.437-1.062T12 12.5t-1.062.438T10.5 14t.438 1.063T12 15.5t1.063-.437M8 20v-9L6.325 8.5q-.175-.25-.25-.525T6 7.4V7h12v.4q0 .3-.075.575t-.25.525L16 11v9q0 .825-.587 1.413T14 22h-4q-.825 0-1.412-.587T8 20\\\"/>\",\n flashlightOff:\n \"<path fill=\\\"currentColor\\\" d=\\\"M8 20v-9.2L2.1 4.9q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l17 17q.275.275.275.7t-.275.7t-.7.275t-.7-.275L16 18.8V20q0 .825-.587 1.413T14 22h-4q-.825 0-1.412-.587T8 20M7.85 5l-1.7-1.7q.2-.575.7-.937T8 2h8q.825 0 1.413.588T18 4v1zM16 13.15L9.85 7H18v.4q0 .3-.075.575t-.25.525L16 11z\\\"/>\",\n pause:\n \"<path fill=\\\"currentColor\\\" d=\\\"M16 19q-.825 0-1.412-.587T14 17V7q0-.825.588-1.412T16 5t1.413.588T18 7v10q0 .825-.587 1.413T16 19m-8 0q-.825 0-1.412-.587T6 17V7q0-.825.588-1.412T8 5t1.413.588T10 7v10q0 .825-.587 1.413T8 19\\\"/>\",\n play:\n \"<path fill=\\\"currentColor\\\" d=\\\"M8 17.175V6.825q0-.425.3-.713t.7-.287q.125 0 .263.037t.262.113l8.15 5.175q.225.15.338.375t.112.475t-.112.475t-.338.375l-8.15 5.175q-.125.075-.262.113T9 18.175q-.4 0-.7-.288t-.3-.712\\\"/>\",\n group:\n \"<path fill=\\\"currentColor\\\" d=\\\"M1 17.2q0-.85.438-1.562T2.6 14.55q1.55-.775 3.15-1.162T9 13t3.25.388t3.15 1.162q.725.375 1.163 1.088T17 17.2v.8q0 .825-.587 1.413T15 20H3q-.825 0-1.412-.587T1 18zM18.45 20q.275-.45.413-.962T19 18v-1q0-1.1-.612-2.113T16.65 13.15q1.275.15 2.4.513t2.1.887q.9.5 1.375 1.112T23 17v1q0 .825-.587 1.413T21 20zM6.175 10.825Q5 9.65 5 8t1.175-2.825T9 4t2.825 1.175T13 8t-1.175 2.825T9 12t-2.825-1.175m11.65 0Q16.65 12 15 12q-.275 0-.7-.062t-.7-.138q.675-.8 1.038-1.775T15 8t-.362-2.025T13.6 4.2q.35-.125.7-.163T15 4q1.65 0 2.825 1.175T19 8t-1.175 2.825\\\"/>\",\n pictureInPicture:\n \"<path fill=\\\"currentColor\\\" d=\\\"M4 20q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4h16q.825 0 1.413.588T22 6v12q0 .825-.587 1.413T20 20zm8-3h6q.425 0 .713-.288T19 16v-4q0-.425-.288-.712T18 11h-6q-.425 0-.712.288T11 12v4q0 .425.288.713T12 17m3-3\\\"/>\",\n openInFull:\n \"<path fill=\\\"currentColor\\\" d=\\\"M4 21q-.425 0-.712-.288T3 20v-6q0-.425.288-.712T4 13t.713.288T5 14v3.6L17.6 5H14q-.425 0-.712-.288T13 4t.288-.712T14 3h6q.425 0 .713.288T21 4v6q0 .425-.288.713T20 11t-.712-.288T19 10V6.4L6.4 19H10q.425 0 .713.288T11 20t-.288.713T10 21z\\\"/>\",\n volumeUp:\n \"<path fill=\\\"currentColor\\\" d=\\\"M19 11.975q0-2.075-1.1-3.787t-2.95-2.563q-.375-.175-.55-.537t-.05-.738q.15-.4.538-.575t.787 0Q18.1 4.85 19.55 7.063T21 11.974t-1.45 4.913t-3.875 3.287q-.4.175-.788 0t-.537-.575q-.125-.375.05-.737t.55-.538q1.85-.85 2.95-2.562t1.1-3.788M7 15H4q-.425 0-.712-.288T3 14v-4q0-.425.288-.712T4 9h3l3.3-3.3q.475-.475 1.088-.213t.612.938v11.15q0 .675-.612.938T10.3 18.3zm9.5-3q0 1.05-.475 1.988t-1.25 1.537q-.25.15-.513.013T14 15.1V8.85q0-.3.263-.437t.512.012q.775.625 1.25 1.575t.475 2\\\"/>\",\n cameraSwitch:\n \"<path fill=\\\"currentColor\\\" d=\\\"M8 17q-.825 0-1.412-.587T6 15V9q0-.825.588-1.412T8 7h1l.7-.7q.15-.15.338-.225T10.425 6h3.15q.2 0 .388.075t.337.225l.7.7h1q.825 0 1.412.588T18 9v6q0 .825-.587 1.413T16 17zm4-3q.825 0 1.413-.587T14 12t-.587-1.412T12 10t-1.412.588T10 12t.588 1.413T12 14m0 10q-4.4 0-7.712-2.762T.174 14.275Q.1 13.85.337 13.5T1 13.1t.75.213t.4.687q.65 3.275 3.113 5.475T11.1 21.95l-.85-.85q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l3.3 3.3q.175.175.113.4t-.288.275q-.675.175-1.362.25T12 24m0-24q4.4 0 7.713 2.75t4.112 6.975q.075.425-.162.775t-.663.4t-.75-.213t-.4-.687q-.65-3.275-3.113-5.475T12.9 2.05l.85.85q.275.275.275.7t-.275.7t-.7.275t-.7-.275L9.05 1Q8.875.825 8.938.6t.287-.275Q9.9.15 10.588.075T12 0\\\"/>\",\n arrowDropUp:\n \"<path fill=\\\"currentColor\\\" d=\\\"M8.2 14q-.225 0-.362-.15T7.7 13.5q0-.05.15-.35l3.625-3.625q.125-.125.25-.175T12 9.3t.275.05t.25.175l3.625 3.625q.075.075.113.163t.037.187q0 .2-.137.35T15.8 14z\\\"/>\",\n moreVert:\n \"<path fill=\\\"currentColor\\\" d=\\\"M12 20q-.825 0-1.412-.587T10 18t.588-1.412T12 16t1.413.588T14 18t-.587 1.413T12 20m0-6q-.825 0-1.412-.587T10 12t.588-1.412T12 10t1.413.588T14 12t-.587 1.413T12 14m0-6q-.825 0-1.412-.587T10 6t.588-1.412T12 4t1.413.588T14 6t-.587 1.413T12 8\\\"/>\",\n check:\n \"<path fill=\\\"currentColor\\\" d=\\\"m9.55 15.15l8.475-8.475q.3-.3.7-.3t.7.3t.3.713t-.3.712l-9.175 9.2q-.3.3-.7.3t-.7-.3L4.55 13q-.3-.3-.288-.712t.313-.713t.713-.3t.712.3z\\\"/>\",\n} as const;\n\nexport type CallIconName = keyof typeof ICONS;\n\ndefineProps<{ name: CallIconName }>();\n</script>\n\n<template>\n <!-- eslint-disable-next-line vue/no-v-html -- static paths from ICONS above, never user input -->\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\" v-html=\"ICONS[name]\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * IconButton for the call screen: an icon-only, round PrimeVue Button showing a Material Symbol\n * (CallIcon). Any Button prop (severity, size, dt...) and listener passes through.\n */\nimport Button from \"primevue/button\";\nimport CallIcon, { type CallIconName } from \"./CallIcon.vue\";\n\ndefineOptions({ inheritAttrs: false });\n\nwithDefaults(\n defineProps<{\n icon: CallIconName;\n /** Accessible name; the button has no visible text. */\n label: string;\n iconClass?: string;\n }>(),\n { iconClass: \"size-5\" },\n);\n</script>\n\n<template>\n <Button rounded text severity=\"secondary\" v-bind=\"$attrs\" :aria-label=\"label\">\n <template #icon>\n <CallIcon :name=\"icon\" :class=\"iconClass\" />\n </template>\n </Button>\n</template>\n","<script setup lang=\"ts\">\nimport { useCallStore } from \"~/stores/callStore\";\nimport { useChatStore } from \"~/stores/chatStore\";\nimport { formatDuration } from \"~/utils/format\";\nimport useLocalI18n, { useDirection } from \"~/composables/useLocalI18n\";\nimport { chat } from \"@i18n/locales\";\nimport useCall from \"~/composables/useCall\";\nimport { useSpeaking } from \"~/composables/call/useSpeaking\";\nimport { useDraggable, useEventListener, useWindowSize } from \"@vueuse/core\";\nimport { ref, computed, watch, onMounted, nextTick } from \"vue\";\nimport Avatar from \"primevue/avatar\";\nimport Button from \"primevue/button\";\nimport Menu from \"primevue/menu\";\nimport Tooltip from \"primevue/tooltip\";\nimport type { MenuItem } from \"primevue/menuitem\";\nimport CallButton from \"./CallButton.vue\";\nimport CallIcon from \"./CallIcon.vue\";\n\nconst vTooltip = Tooltip;\n\nconst callStore = useCallStore();\nconst minimizedRef = ref<HTMLElement | null>(null);\nconst bodyRef = ref<HTMLElement | null>(null);\n\nconst { t } = useLocalI18n(chat);\nconst { dir } = useDirection();\n\n// Named after whoever is on the other end of the conversation the call belongs to.\nconst chatStore = useChatStore();\nconst callTitle = computed(() => {\n const contact = callStore.channelId ? chatStore.getContactById(callStore.channelId) : null;\n const name = contact ? `${contact.name} ${contact.lastName ?? \"\"}`.trim() : \"\";\n return name || t(\"chat.call.title\");\n});\n\nconst {\n toggleVideoPause,\n toggleRemote,\n participantCount,\n endCall,\n toggleFullscreen,\n toggleFlashlight,\n toggleScreenShare,\n toggleAudio,\n toggleVideo,\n switchCamera,\n isFlashlightSupported,\n tileCount,\n isAudioOn,\n isVideoOn,\n isFlashlightOn,\n isFullscreen,\n isScreenSharing,\n showControls,\n resetControlsTimeout,\n cameras,\n videoPaused,\n localStream,\n localVideo,\n localScreen,\n remoteParents,\n remoteRefs,\n remoteScreens,\n remoteScreenRefs,\n remoteVideos,\n soundBlocked,\n enableSound,\n} = useCall();\n\n// --- Controls ---\n\n// The call screen is dark whatever the host's colour scheme, so its controls use fixed tokens\n// instead of the theme's: translucent white at rest, white when a feature is on (Meet's \"lit\"),\n// red when the microphone or camera is off.\nconst translucent = {\n background: \"rgb(255 255 255 / 0.12)\",\n hoverBackground: \"rgb(255 255 255 / 0.2)\",\n activeBackground: \"rgb(255 255 255 / 0.28)\",\n borderColor: \"transparent\",\n hoverBorderColor: \"transparent\",\n activeBorderColor: \"transparent\",\n color: \"#ffffff\",\n hoverColor: \"#ffffff\",\n activeColor: \"#ffffff\",\n};\nconst lit = {\n background: \"#ffffff\",\n hoverBackground: \"rgb(255 255 255 / 0.9)\",\n activeBackground: \"rgb(255 255 255 / 0.8)\",\n borderColor: \"#ffffff\",\n hoverBorderColor: \"#ffffff\",\n activeBorderColor: \"#ffffff\",\n color: \"#171717\",\n hoverColor: \"#171717\",\n activeColor: \"#171717\",\n};\n// Tailwind's red-500 to red-700.\nconst off = {\n background: \"#ef4444\",\n hoverBackground: \"#dc2626\",\n activeBackground: \"#b91c1c\",\n borderColor: \"transparent\",\n hoverBorderColor: \"transparent\",\n activeBorderColor: \"transparent\",\n color: \"#ffffff\",\n hoverColor: \"#ffffff\",\n activeColor: \"#ffffff\",\n};\nconst callScheme = { root: { secondary: translucent, contrast: lit, danger: off } };\nconst callButtonDt = { colorScheme: { light: callScheme, dark: callScheme } };\n\n// Its menus are dark too, Tailwind's neutral-800 under white text, in either host scheme.\nconst callMenuDt = {\n root: { background: \"#262626\", borderColor: \"rgb(255 255 255 / 0.1)\", color: \"#f5f5f5\" },\n item: {\n focusBackground: \"rgb(255 255 255 / 0.1)\",\n color: \"#f5f5f5\",\n focusColor: \"#ffffff\",\n icon: { color: \"#a3a3a3\", focusColor: \"#ffffff\" },\n },\n submenuLabel: { background: \"transparent\", color: \"#a3a3a3\" },\n};\n\n// Pills, as in Google Meet: wider than tall, so the bar reads as one row of controls.\nconst barButton = {\n dt: callButtonDt,\n text: false,\n size: \"large\",\n iconClass: \"size-6\",\n class: \"h-12! w-12! sm:w-14!\",\n} as const;\n\n// Tile actions sit on the video: small round buttons, shown on hover or focus where there is a\n// pointer that hovers, always on touch screens.\nconst tileButton = {\n dt: callButtonDt,\n text: false,\n size: \"small\",\n iconClass: \"size-4.5\",\n class: \"size-9!\",\n} as const;\nconst tileActions =\n \"absolute end-2 bottom-2 z-20 flex items-center gap-x-1.5 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none [@media(hover:none)]:opacity-100\";\nconst nameChip =\n \"max-w-[60%] truncate rounded-md bg-black/55 px-2 py-0.5 text-label-sm text-white backdrop-blur-sm select-none\";\n\n// Meet's shortcuts, on the tooltip and in the keyboard: Ctrl+D the microphone, Ctrl+E the camera.\nconst isMac = typeof navigator !== \"undefined\" && /Mac|iPhone|iPad/.test(navigator.platform);\nconst keys = (key: string) => (isMac ? `⌘ ${key}` : `Ctrl + ${key}`);\nconst withKeys = (label: string, key: string) => `${label} (${keys(key)})`;\n// Tooltips are appended to <body>, outside the chat, so they take its font and reset with them.\nconst tip = (value: string) => ({ value, class: \"vue-chat font-chat-family\" });\n\nconst audioLabel = computed(() =>\n isAudioOn.value ? t(\"chat.call.controls.mute\") : t(\"chat.call.controls.unmute\"),\n);\nconst videoLabel = computed(() =>\n isVideoOn.value ? t(\"chat.call.controls.cameraOff\") : t(\"chat.call.controls.cameraOn\"),\n);\nconst shareLabel = computed(() =>\n isScreenSharing.value\n ? t(\"chat.call.controls.stopSharing\")\n : t(\"chat.call.controls.shareScreen\"),\n);\nconst fullscreenLabel = computed(() =>\n isFullscreen.value\n ? t(\"chat.call.controls.exitFullscreen\")\n : t(\"chat.call.controls.fullscreen\"),\n);\n\nuseEventListener(window, \"keydown\", (event: KeyboardEvent) => {\n if (!callStore.isActive || callStore.isMinimized) return;\n if (!(isMac ? event.metaKey : event.ctrlKey) || event.altKey || event.shiftKey) return;\n const key = event.key.toLowerCase();\n if (key !== \"d\" && key !== \"e\") return;\n // Both are browser shortcuts too (bookmark, search), which the call takes over while it's open.\n event.preventDefault();\n if (key === \"d\") toggleAudio();\n else toggleVideo();\n});\n\n// The camera in use: read off the track when the call starts, then whatever was picked.\nconst currentCameraId = ref<string | null>(null);\nwatch(\n localStream,\n (stream) => {\n currentCameraId.value = stream?.getVideoTracks()[0]?.getSettings().deviceId ?? null;\n },\n { immediate: true },\n);\n\nconst cameraMenu = ref<InstanceType<typeof Menu> | null>(null);\nconst cameraItems = computed<MenuItem[]>(() => [\n {\n label: t(\"chat.call.controls.cameras\"),\n items: cameras.value.map((camera, index) => ({\n label: camera.label || `${t(\"chat.call.controls.chooseCamera\")} ${index + 1}`,\n callIcon: camera.deviceId === currentCameraId.value ? \"check\" : undefined,\n command: () => {\n currentCameraId.value = camera.deviceId;\n void switchCamera(camera.deviceId);\n },\n })),\n },\n]);\n\nconst moreMenu = ref<InstanceType<typeof Menu> | null>(null);\nconst moreItems = computed<MenuItem[]>(() => [\n {\n label: fullscreenLabel.value,\n callIcon: isFullscreen.value ? \"fullscreenExit\" : \"fullscreen\",\n command: () => toggleFullscreen(),\n },\n ...(isFlashlightSupported.value\n ? [\n {\n label: isFlashlightOn.value\n ? t(\"chat.call.controls.flashlightOff\")\n : t(\"chat.call.controls.flashlightOn\"),\n callIcon: isFlashlightOn.value ? \"flashlightOff\" : \"flashlightOn\",\n command: () => toggleFlashlight(),\n },\n ]\n : []),\n]);\n\n// --- Speaking ---\n\nconst speaking = useSpeaking(() => ({\n self: isAudioOn.value ? localStream.value : null,\n ...Object.fromEntries(\n Object.entries(remoteVideos.value).map(([id, remote]) => [id, remote.stream]),\n ),\n}));\nconst speakingRing = (on: boolean | undefined) =>\n on ? \"ring-sky-400\" : \"ring-transparent\";\n\n// --- Picture-in-picture ---\n\n// Minimized, the call plays live behind its controls: the remote participant on show, or the\n// user's own camera when nobody else is there.\nconst pipVideoRef = ref<HTMLVideoElement | null>(null);\nconst activeRemoteIndex = ref(0);\n\nconst remoteVideoEntries = computed(() => Object.entries(remoteVideos.value));\nconst hasRemoteVideos = computed(() => remoteVideoEntries.value.length > 0);\nconst activeRemoteUserId = computed<string | null>(() => {\n const entries = remoteVideoEntries.value;\n if (entries.length === 0) return null;\n return entries[activeRemoteIndex.value % entries.length][0];\n});\n\nconst pipStream = computed<MediaStream | null>(() => {\n if (hasRemoteVideos.value) {\n const id = activeRemoteUserId.value;\n return id ? (remoteVideos.value[id]?.stream ?? null) : null;\n }\n return localStream.value ?? null;\n});\n\nfunction cycleRemote() {\n const count = remoteVideoEntries.value.length;\n if (count === 0) return;\n activeRemoteIndex.value = (activeRemoteIndex.value + 1) % count;\n}\n\nwatch(\n [pipStream, () => callStore.isMinimized],\n async () => {\n await nextTick();\n const el = pipVideoRef.value;\n if (!el) return;\n const stream = pipStream.value;\n if (stream && el.srcObject !== stream) {\n el.srcObject = stream;\n el.play().catch(() => {});\n } else if (!stream && el.srcObject) {\n el.srcObject = null;\n }\n },\n { immediate: true },\n);\n\nonMounted(() => {\n bodyRef.value = document.body;\n});\n\n// Dragged anywhere, then snapped to the nearest corner on release.\nconst { width: windowWidth, height: windowHeight } = useWindowSize();\n\nconst PIP_WIDTH = 280; // w-70\nconst PIP_HEIGHT = 160; // h-40\nconst PADDING = 16;\n// Top and bottom corners stay this far from the edges, clear of the chat header and the composer.\nconst PIP_INSET_Y = 96;\n\nconst { x, y, isDragging } = useDraggable(minimizedRef, {\n initialValue: {\n x: typeof window !== \"undefined\" ? window.innerWidth - PIP_WIDTH - PADDING : PADDING,\n y: PIP_INSET_Y,\n },\n disabled: computed(() => !callStore.isMinimized),\n});\n\nwatch(isDragging, (dragging) => {\n if (!dragging && callStore.isMinimized) {\n const maxX = windowWidth.value - PIP_WIDTH - PADDING;\n const maxY = windowHeight.value - PIP_HEIGHT - PIP_INSET_Y;\n x.value = x.value < windowWidth.value / 2 ? PADDING : maxX;\n y.value = y.value < windowHeight.value / 2 ? PIP_INSET_Y : maxY;\n }\n});\n\n// Each time it is minimized it starts in the top corner on the reading end.\nwatch(\n () => callStore.isMinimized,\n (isMinimized) => {\n if (isMinimized) {\n nextTick(() => {\n const isRtl = dir.value === \"rtl\";\n x.value = isRtl ? PADDING : windowWidth.value - PIP_WIDTH - PADDING;\n // The top corner, where it covers older messages rather than the composer.\n y.value = PIP_INSET_Y;\n });\n }\n },\n { immediate: true },\n);\n\n// Kept on screen whatever the window does.\nconst clampedStyle = computed(() => {\n if (!callStore.isMinimized) return {};\n\n const maxX = windowWidth.value - PIP_WIDTH - PADDING;\n const maxY = windowHeight.value - PIP_HEIGHT - PADDING;\n\n return {\n left: `${Math.max(PADDING, Math.min(x.value, maxX))}px`,\n top: `${Math.max(PADDING, Math.min(y.value, maxY))}px`,\n };\n});\n</script>\n\n<template>\n <!-- Picture-in-picture: the call shrunk to a draggable window over the app. -->\n <div\n v-if=\"callStore.isActive && callStore.isMinimized\"\n ref=\"minimizedRef\"\n data-testid=\"call-pip\"\n :style=\"clampedStyle\"\n :dir=\"dir\"\n class=\"vue-chat font-chat-family fixed z-9999 h-40 w-70 cursor-move touch-none overflow-hidden rounded-2xl bg-neutral-900 shadow-2xl ring-1 ring-white/10\"\n :class=\"[!isDragging && 'transition-all duration-300 ease-out motion-reduce:transition-none']\"\n >\n <video\n ref=\"pipVideoRef\"\n muted\n autoplay\n playsinline\n class=\"pointer-events-none absolute inset-0 size-full object-cover\"\n />\n <div\n class=\"pointer-events-none absolute inset-0 bg-linear-to-t from-black/60 via-transparent to-black/30\"\n />\n\n <div class=\"absolute inset-x-3 top-3 flex items-center justify-between\">\n <div\n class=\"flex items-center gap-x-2 rounded-full bg-black/45 px-3 py-1.5 text-label-sm text-white backdrop-blur-sm select-none\"\n >\n <span class=\"relative flex size-2.5\">\n <span class=\"absolute inline-flex size-full animate-ping rounded-full bg-red-500/60 motion-reduce:animate-none\" />\n <span class=\"relative inline-flex size-2.5 rounded-full bg-red-500\" />\n </span>\n <span dir=\"ltr\" class=\"tabular-nums\">{{ formatDuration(callStore.elapsedTime) }}</span>\n </div>\n\n <CallButton\n icon=\"callEnd\"\n :label=\"t('chat.call.controls.endCall')\"\n severity=\"danger\"\n :dt=\"callButtonDt\"\n :text=\"false\"\n icon-class=\"size-5\"\n class=\"h-9! w-12!\"\n data-testid=\"call-pip-end\"\n @pointerdown.stop\n @click.stop=\"endCall\"\n />\n </div>\n\n <div class=\"absolute inset-x-3 bottom-3 flex items-center justify-between\">\n <div class=\"flex items-center gap-1.5\">\n <Button\n :label=\"String(participantCount)\"\n :aria-label=\"t('chat.call.controls.nextParticipant')\"\n :disabled=\"!hasRemoteVideos\"\n :dt=\"callButtonDt\"\n severity=\"secondary\"\n size=\"small\"\n rounded\n class=\"h-8!\"\n @pointerdown.stop\n @click.stop=\"cycleRemote\"\n >\n <template #icon>\n <CallIcon name=\"group\" class=\"size-4\" />\n </template>\n </Button>\n\n <span\n v-if=\"!isAudioOn\"\n class=\"flex size-8 items-center justify-center rounded-full bg-red-500 text-white\"\n >\n <CallIcon name=\"micOff\" class=\"size-4\" />\n </span>\n <span\n v-if=\"!isVideoOn\"\n class=\"flex size-8 items-center justify-center rounded-full bg-red-500 text-white\"\n >\n <CallIcon name=\"videocamOff\" class=\"size-4\" />\n </span>\n </div>\n\n <CallButton\n icon=\"openInFull\"\n :label=\"t('chat.call.controls.maximize')\"\n :dt=\"callButtonDt\"\n :text=\"false\"\n icon-class=\"size-4.5\"\n class=\"size-9!\"\n data-testid=\"call-maximize\"\n @pointerdown.stop\n @click.stop=\"callStore.maximize()\"\n />\n </div>\n </div>\n\n <!-- The full call screen. -->\n <div\n v-show=\"callStore.isActive && !callStore.isMinimized\"\n data-testid=\"call-view\"\n :dir=\"dir\"\n class=\"vue-chat font-chat-family fixed inset-0 z-60 flex size-full flex-col bg-neutral-900 text-white\"\n >\n <!-- Stage -->\n <div\n class=\"relative min-h-0 flex-1 px-3 pt-16 pb-2 md:p-4\"\n @mousemove=\"resetControlsTimeout\"\n >\n <!-- The browser blocked the others' sound until a tap: they play muted until then. -->\n <Button\n v-if=\"soundBlocked\"\n :label=\"t('chat.call.controls.enableSound')\"\n :dt=\"callButtonDt\"\n severity=\"contrast\"\n rounded\n data-testid=\"call-enable-sound\"\n class=\"absolute! top-6 left-1/2 z-30 -translate-x-1/2 shadow-lg\"\n @click=\"enableSound\"\n >\n <template #icon>\n <CallIcon name=\"volumeUp\" class=\"size-5\" />\n </template>\n </Button>\n\n <div\n v-show=\"tileCount\"\n class=\"grid size-full min-h-0 min-w-0 grid-cols-1 gap-3 md:grid-cols-[repeat(auto-fit,minmax(300px,1fr))] md:gap-4\"\n >\n <!-- Own screen share -->\n <div\n v-show=\"isScreenSharing\"\n :ref=\"(el) => (remoteParents['self_screen'] = el as any)\"\n class=\"group relative flex min-h-0 overflow-hidden rounded-2xl bg-neutral-800\"\n >\n <video\n ref=\"localScreen\"\n autoplay\n muted\n playsinline\n class=\"absolute inset-0 size-full object-contain\"\n />\n <div class=\"absolute start-2 bottom-2 z-20 flex max-w-[60%] items-center gap-x-1.5\">\n <span class=\"flex size-7 shrink-0 items-center justify-center rounded-full bg-black/55 backdrop-blur-sm\">\n <CallIcon name=\"presentToAll\" class=\"size-4\" />\n </span>\n <span :class=\"nameChip\">{{ t(\"chat.call.yourPresentation\") }}</span>\n </div>\n <div :class=\"tileActions\">\n <CallButton\n :icon=\"videoPaused['self_screen'] ? 'play' : 'pause'\"\n :label=\"videoPaused['self_screen'] ? t('chat.call.controls.playVideo') : t('chat.call.controls.pauseVideo')\"\n v-bind=\"tileButton\"\n @click=\"toggleVideoPause('self_screen', localScreen as any)\"\n />\n <CallButton\n :icon=\"isFullscreen ? 'fullscreenExit' : 'fullscreen'\"\n :label=\"fullscreenLabel\"\n v-bind=\"tileButton\"\n @click=\"toggleRemote('self_screen')\"\n />\n </div>\n </div>\n\n <!-- Remote cameras -->\n <div\n v-for=\"(remote, remoteUserId) in remoteVideos\"\n :key=\"`remote-${remoteUserId}`\"\n data-testid=\"call-remote-video\"\n :ref=\"(el) => (remoteParents[`remote_video_${remoteUserId}`] = el as any)\"\n class=\"group relative flex min-h-0 overflow-hidden rounded-2xl bg-neutral-800 ring-3 ring-inset transition-shadow motion-reduce:transition-none\"\n :class=\"speakingRing(speaking[remoteUserId])\"\n >\n <video\n :ref=\"(el) => { if (el) remoteRefs[remoteUserId] = el as any; }\"\n autoplay\n playsinline\n class=\"absolute inset-0 size-full object-cover\"\n />\n <span :class=\"[nameChip, 'absolute start-2 bottom-2 z-20']\">\n <bdi>{{ remote.name }}</bdi>\n </span>\n <div :class=\"tileActions\">\n <CallButton\n :icon=\"videoPaused[`remote_video_${remoteUserId}`] ? 'play' : 'pause'\"\n :label=\"videoPaused[`remote_video_${remoteUserId}`] ? t('chat.call.controls.playVideo') : t('chat.call.controls.pauseVideo')\"\n v-bind=\"tileButton\"\n @click=\"toggleVideoPause(`remote_video_${remoteUserId}`, remoteRefs[remoteUserId] as any)\"\n />\n <CallButton\n :icon=\"isFullscreen ? 'fullscreenExit' : 'fullscreen'\"\n :label=\"fullscreenLabel\"\n v-bind=\"tileButton\"\n @click=\"toggleRemote(`remote_video_${remoteUserId}`)\"\n />\n </div>\n </div>\n\n <!-- Remote screen shares -->\n <div\n v-for=\"(remote, remoteUserId) in remoteScreens\"\n :key=\"`remote-screen-${remoteUserId}`\"\n data-testid=\"call-remote-screen\"\n :ref=\"(el) => (remoteParents[`remote_screen_${remoteUserId}`] = el as any)\"\n class=\"group relative flex min-h-0 overflow-hidden rounded-2xl bg-neutral-800\"\n >\n <video\n :ref=\"(el) => { if (el) remoteScreenRefs[remoteUserId] = el as any; }\"\n autoplay\n muted\n playsinline\n class=\"absolute inset-0 size-full object-contain\"\n />\n <div class=\"absolute start-2 bottom-2 z-20 flex max-w-[60%] items-center gap-x-1.5\">\n <span class=\"flex size-7 shrink-0 items-center justify-center rounded-full bg-black/55 backdrop-blur-sm\">\n <CallIcon name=\"presentToAll\" class=\"size-4\" />\n </span>\n <span :class=\"nameChip\">\n {{ t(\"chat.call.presentationOf\", { name: remote.name }) }}\n </span>\n </div>\n <div :class=\"tileActions\">\n <CallButton\n :icon=\"videoPaused[`remote_screen_${remoteUserId}`] ? 'play' : 'pause'\"\n :label=\"videoPaused[`remote_screen_${remoteUserId}`] ? t('chat.call.controls.playVideo') : t('chat.call.controls.pauseVideo')\"\n v-bind=\"tileButton\"\n @click=\"toggleVideoPause(`remote_screen_${remoteUserId}`, remoteScreenRefs[remoteUserId] || null)\"\n />\n <CallButton\n :icon=\"isFullscreen ? 'fullscreenExit' : 'fullscreen'\"\n :label=\"fullscreenLabel\"\n v-bind=\"tileButton\"\n @click=\"toggleRemote(`remote_screen_${remoteUserId}`)\"\n />\n </div>\n </div>\n </div>\n\n <!-- Own camera: the whole stage when alone, a small floating tile once others show. -->\n <div\n :ref=\"(el) => (remoteParents['self_cam'] = el as any)\"\n class=\"group overflow-hidden rounded-2xl bg-neutral-800 ring-3 ring-inset transition-shadow [clip-path:inset(0_round_var(--radius-2xl))] motion-reduce:transition-none\"\n :class=\"[\n tileCount\n ? 'absolute end-5 bottom-4 z-10 aspect-video w-36 sm:w-56 md:end-6 md:bottom-6 md:w-64'\n : 'relative size-full',\n speakingRing(speaking.self),\n ]\"\n >\n <video\n ref=\"localVideo\"\n data-testid=\"call-local-video\"\n autoplay\n muted\n playsinline\n class=\"pointer-events-none absolute inset-0 size-full -scale-x-100 rounded-[inherit] object-cover\"\n />\n\n <div\n v-if=\"!isVideoOn\"\n class=\"absolute inset-0 flex flex-col items-center justify-center gap-y-2 bg-neutral-800\"\n >\n <Avatar\n :label=\"t('chat.call.you').slice(0, 1)\"\n shape=\"circle\"\n :size=\"tileCount ? 'large' : 'xlarge'\"\n class=\"bg-sky-600! text-white! select-none\"\n />\n <p v-if=\"!tileCount\" class=\"text-label-md text-neutral-300 select-none\">\n {{ t(\"chat.call.cameraIsOff\") }}\n </p>\n </div>\n\n <span\n v-if=\"!isAudioOn\"\n class=\"absolute end-2 top-2 z-20 flex size-7 items-center justify-center rounded-full bg-red-500 text-white\"\n :title=\"t('chat.call.controls.unmute')\"\n >\n <CallIcon name=\"micOff\" class=\"size-4\" />\n </span>\n\n <span :class=\"[nameChip, 'absolute start-2 bottom-2 z-20']\">{{ t(\"chat.call.you\") }}</span>\n\n <div v-if=\"!tileCount\" :class=\"tileActions\">\n <CallButton\n :icon=\"videoPaused['self_cam'] ? 'play' : 'pause'\"\n :label=\"videoPaused['self_cam'] ? t('chat.call.controls.playVideo') : t('chat.call.controls.pauseVideo')\"\n v-bind=\"tileButton\"\n @click=\"toggleVideoPause('self_cam', localVideo as any)\"\n />\n </div>\n </div>\n </div>\n\n <!-- Control bar: time and title, the controls, then the people and minimize. On phones the\n two sides move to the top of the screen, leaving the controls a row of their own. -->\n <div\n class=\"grid h-20 shrink-0 grid-cols-1 items-center px-3 transition-opacity duration-300 motion-reduce:transition-none md:relative md:grid-cols-[1fr_auto_1fr] md:px-6\"\n :class=\"showControls ? 'opacity-100' : 'opacity-0'\"\n @mouseenter=\"resetControlsTimeout\"\n @mousemove=\"resetControlsTimeout\"\n >\n <div\n class=\"absolute start-4 top-4 flex min-w-0 items-center gap-x-3 text-body-md select-none md:static\"\n >\n <span dir=\"ltr\" class=\"tabular-nums\">{{ formatDuration(callStore.elapsedTime) }}</span>\n <span class=\"hidden h-4 w-px bg-white/30 md:block\" />\n <span class=\"hidden truncate md:block\">{{ callTitle }}</span>\n </div>\n\n <div class=\"flex items-center justify-center gap-x-2 sm:gap-x-3\">\n <CallButton\n v-tooltip.top=\"tip(withKeys(audioLabel, 'D'))\"\n :icon=\"isAudioOn ? 'mic' : 'micOff'\"\n :label=\"audioLabel\"\n :severity=\"isAudioOn ? 'secondary' : 'danger'\"\n :aria-keyshortcuts=\"isMac ? 'Meta+D' : 'Control+D'\"\n v-bind=\"barButton\"\n data-testid=\"call-toggle-audio\"\n :data-active=\"isAudioOn\"\n @click=\"toggleAudio\"\n />\n\n <!-- The camera, with Meet's caret for picking which one when there are several. -->\n <div class=\"flex items-center rounded-full\" :class=\"cameras.length > 1 && 'bg-white/12'\">\n <CallButton\n v-if=\"cameras.length > 1\"\n v-tooltip.top=\"tip(t('chat.call.controls.chooseCamera'))\"\n icon=\"arrowDropUp\"\n :label=\"t('chat.call.controls.chooseCamera')\"\n :dt=\"callButtonDt\"\n text\n severity=\"secondary\"\n icon-class=\"size-6\"\n class=\"h-12! w-8! rounded-e-none! ps-1!\"\n aria-haspopup=\"true\"\n @click=\"cameraMenu?.toggle($event)\"\n />\n <CallButton\n v-tooltip.top=\"tip(withKeys(videoLabel, 'E'))\"\n :icon=\"isVideoOn ? 'videocam' : 'videocamOff'\"\n :label=\"videoLabel\"\n :severity=\"isVideoOn ? 'secondary' : 'danger'\"\n :aria-keyshortcuts=\"isMac ? 'Meta+E' : 'Control+E'\"\n v-bind=\"barButton\"\n data-testid=\"call-toggle-video\"\n :data-active=\"isVideoOn\"\n @click=\"toggleVideo\"\n />\n </div>\n\n <CallButton\n v-tooltip.top=\"tip(shareLabel)\"\n :icon=\"isScreenSharing ? 'cancelPresentation' : 'presentToAll'\"\n :label=\"shareLabel\"\n :severity=\"isScreenSharing ? 'contrast' : 'secondary'\"\n v-bind=\"barButton\"\n data-testid=\"call-toggle-screen\"\n :data-active=\"isScreenSharing\"\n @click=\"toggleScreenShare\"\n />\n\n <CallButton\n v-tooltip.top=\"tip(t('chat.call.controls.more'))\"\n icon=\"moreVert\"\n :label=\"t('chat.call.controls.more')\"\n v-bind=\"barButton\"\n class=\"h-12! w-10! sm:w-12!\"\n aria-haspopup=\"true\"\n data-testid=\"call-more\"\n @click=\"moreMenu?.toggle($event)\"\n />\n\n <CallButton\n v-tooltip.top=\"tip(t('chat.call.controls.endCall'))\"\n icon=\"callEnd\"\n :label=\"t('chat.call.controls.endCall')\"\n severity=\"danger\"\n :dt=\"callButtonDt\"\n :text=\"false\"\n size=\"large\"\n icon-class=\"size-6\"\n class=\"h-12! w-16! sm:w-18!\"\n data-testid=\"call-end\"\n @click=\"endCall\"\n />\n </div>\n\n <div class=\"absolute end-3 top-2.5 flex items-center justify-end gap-x-2 md:static\">\n <div\n data-testid=\"call-participants\"\n class=\"flex h-10 items-center gap-x-1.5 rounded-full bg-white/12 px-3 text-label-md select-none\"\n :title=\"t('chat.call.participants', participantCount)\"\n >\n <CallIcon name=\"group\" class=\"size-5\" />\n <span aria-hidden=\"true\">{{ participantCount }}</span>\n <span class=\"sr-only\">{{ t(\"chat.call.participants\", participantCount) }}</span>\n </div>\n <CallButton\n v-tooltip.top=\"tip(t('chat.call.controls.minimize'))\"\n icon=\"pictureInPicture\"\n :label=\"t('chat.call.controls.minimize')\"\n :dt=\"callButtonDt\"\n :text=\"false\"\n icon-class=\"size-5\"\n class=\"size-10!\"\n data-testid=\"call-minimize\"\n @click=\"callStore.minimize\"\n />\n </div>\n </div>\n\n <Menu ref=\"cameraMenu\" :model=\"cameraItems\" popup :dir=\"dir\" :dt=\"callMenuDt\" class=\"vue-chat\">\n <template #itemicon=\"{ item }\">\n <CallIcon v-if=\"item.callIcon\" :name=\"item.callIcon\" class=\"size-5 text-sky-400\" />\n <span v-else class=\"size-5\" />\n </template>\n </Menu>\n <Menu ref=\"moreMenu\" :model=\"moreItems\" popup :dir=\"dir\" :dt=\"callMenuDt\" class=\"vue-chat\">\n <template #itemicon=\"{ item }\">\n <CallIcon :name=\"item.callIcon\" class=\"size-5 text-neutral-400\" />\n </template>\n </Menu>\n </div>\n</template>\n"],"names":["_createElementBlock","_openBlock","_createBlock","_unref","_mergeProps","$attrs","_createVNode","CallIcon","_normalizeClass","_createElementVNode","_toDisplayString","CallButton","_withModifiers","_withDirectives","_Fragment","_renderList","_withCtx","_vShow"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const vue = require("vue");
|
|
4
|
-
const index = require("./index-
|
|
4
|
+
const index = require("./index-CynD-QrC.cjs");
|
|
5
5
|
const core = require("@vueuse/core");
|
|
6
6
|
const Avatar = require("primevue/avatar");
|
|
7
7
|
const Button = require("primevue/button");
|
|
@@ -1152,4 +1152,4 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
1152
1152
|
}
|
|
1153
1153
|
});
|
|
1154
1154
|
exports.default = _sfc_main;
|
|
1155
|
-
//# sourceMappingURL=Call-
|
|
1155
|
+
//# sourceMappingURL=Call-RREiDkV_.cjs.map
|