vue-parley 5.2.0 → 5.4.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.
Files changed (39) hide show
  1. package/README.md +2 -1
  2. package/dist/chunks/{Call-DvVJ7IsY.mjs → Call-DfAAePMJ.mjs} +114 -42
  3. package/dist/chunks/Call-DfAAePMJ.mjs.map +1 -0
  4. package/dist/chunks/{Call-h9r4EZ5Y.cjs → Call-w4VQ-iRu.cjs} +114 -42
  5. package/dist/chunks/Call-w4VQ-iRu.cjs.map +1 -0
  6. package/dist/chunks/{index-C5yf_PW0.mjs → index-BdXnFhTL.mjs} +9 -6
  7. package/dist/chunks/index-BdXnFhTL.mjs.map +1 -0
  8. package/dist/chunks/{index-BSzP10Mk.cjs → index-BtxDzcig.cjs} +9 -6
  9. package/dist/chunks/index-BtxDzcig.cjs.map +1 -0
  10. package/dist/chunks/{session-DhajXqvC.cjs → session-BBh6YzVv.cjs} +65 -17
  11. package/dist/chunks/session-BBh6YzVv.cjs.map +1 -0
  12. package/dist/chunks/{session-CKOlYafG.mjs → session-yLg7UVs_.mjs} +65 -17
  13. package/dist/chunks/session-yLg7UVs_.mjs.map +1 -0
  14. package/dist/index.cjs +1 -1
  15. package/dist/index.mjs +1 -1
  16. package/dist/types/app/components/call/Call.vue.d.ts.map +1 -1
  17. package/dist/types/app/components/call/CallTile.vue.d.ts +3 -0
  18. package/dist/types/app/components/call/CallTile.vue.d.ts.map +1 -1
  19. package/dist/types/app/composables/call/media.d.ts +3 -0
  20. package/dist/types/app/composables/call/media.d.ts.map +1 -1
  21. package/dist/types/app/composables/call/session.d.ts +31 -0
  22. package/dist/types/app/composables/call/session.d.ts.map +1 -1
  23. package/dist/types/app/composables/call/useCallUi.d.ts +1 -0
  24. package/dist/types/app/composables/call/useCallUi.d.ts.map +1 -1
  25. package/dist/types/app/composables/useCall.d.ts +4 -0
  26. package/dist/types/app/composables/useCall.d.ts.map +1 -1
  27. package/dist/types/app/plugin.d.ts +2 -0
  28. package/dist/types/app/plugin.d.ts.map +1 -1
  29. package/dist/types/app/stores/callStore.d.ts +190 -1
  30. package/dist/types/app/stores/callStore.d.ts.map +1 -1
  31. package/dist/types/i18n/locales/index.d.ts +4 -0
  32. package/dist/types/i18n/locales/index.d.ts.map +1 -1
  33. package/package.json +1 -1
  34. package/dist/chunks/Call-DvVJ7IsY.mjs.map +0 -1
  35. package/dist/chunks/Call-h9r4EZ5Y.cjs.map +0 -1
  36. package/dist/chunks/index-BSzP10Mk.cjs.map +0 -1
  37. package/dist/chunks/index-C5yf_PW0.mjs.map +0 -1
  38. package/dist/chunks/session-CKOlYafG.mjs.map +0 -1
  39. package/dist/chunks/session-DhajXqvC.cjs.map +0 -1
package/README.md CHANGED
@@ -69,6 +69,7 @@ createApp(App)
69
69
  media: mediaHandlers, // MediaHandlers: download files, file sizes
70
70
  profile: profileHandlers, // optional: profile panel's media and files tabs
71
71
  call: callHandlers, // optional: enables voice/video calls
72
+ screenShare: true, // optional: shows the call's screen-share button (off by default)
72
73
  user: { id: me.id, name: me.fullName },
73
74
  }),
74
75
  )
@@ -216,7 +217,7 @@ What a host has to do for group calls: nothing beyond what one-to-one calls need
216
217
 
217
218
  **Protocol.** Group calls add optional fields to existing messages and no new message types, so 5.0 clients and the earlier simple-peer builds still call this one: `join.joinedAt` and `join.to` (a reconnect aimed at one participant; older clients take it as aimed at them), `track_type.media` (`{ audio, video }`, sent on every mic or camera change) and `track_type.joinedAt`, and `presence.joinedAt`. Older clients ignore the fields, and a message without them is handled as before: no badges for that participant, and they order last for the cap.
218
219
 
219
- **Test ids** for hosts' own tests, besides the existing `call-remote-video`, `call-remote-screen` and `call-local-video`: `call-top-bar`, `call-participant-count`, `call-people-button`, `call-people-list`, `call-participant` (with `data-participant-id`), `call-tile` (with `data-participant-id` and `data-kind` `camera`, `screen` or `self`), `call-tile-muted`, `call-tile-avatar`, `call-tile-unreachable`, `call-pin`, `call-notice`, `call-waiting` and `call-strip`.
220
+ **Test ids** for hosts' own tests, besides the existing `call-remote-video`, `call-remote-screen` and `call-local-video`: `call-top-bar`, `call-participant-count`, `call-people-button`, `call-people-list`, `call-participant` (with `data-participant-id`), `call-tile` (with `data-participant-id` and `data-kind` `camera`, `screen` or `self`), `call-tile-muted`, `call-tile-avatar`, `call-tile-unreachable`, `call-pin`, `call-notice`, `call-waiting`, `call-strip` and `call-flip-camera` (with `data-facing` `user` or `environment`; phones only).
220
221
 
221
222
  ### Fake backend
222
223
 
@@ -1,5 +1,5 @@
1
1
  import { ref, onMounted, onUnmounted, watch, nextTick, reactive, onBeforeUnmount, computed, defineComponent, openBlock, createElementBlock, createBlock, unref, mergeProps, withCtx, createVNode, normalizeClass, createElementVNode, normalizeStyle, createSlots, toDisplayString, createCommentVNode, withDirectives, Fragment, useModel, renderList, createTextVNode, mergeModels, withModifiers, Transition, vShow } from "vue";
2
- import { u as useCallStore, a as useLocalI18n, c as chat, n as nameInitials, b as avatarToneStyle, _ as _sfc_main$5, d as useDirection, e as useChatStore, f as formatDuration } from "./index-C5yf_PW0.mjs";
2
+ import { u as useCallStore, a as useLocalI18n, c as chat, n as nameInitials, b as avatarToneStyle, _ as _sfc_main$5, d as useDirection, e as useChatStore, f as formatDuration } from "./index-BdXnFhTL.mjs";
3
3
  import { useElementSize, useEventListener, useWindowSize, useDraggable } from "@vueuse/core";
4
4
  import Button from "primevue/button";
5
5
  import Menu from "primevue/menu";
@@ -35,16 +35,15 @@ function useCallUi(opts) {
35
35
  detachAll();
36
36
  });
37
37
  const isFullscreen = ref(false);
38
+ const canFullscreen = typeof document !== "undefined" && !!document.fullscreenEnabled;
39
+ const syncFullscreen = () => isFullscreen.value = !!document.fullscreenElement;
38
40
  function toggleFullscreen(target = document.documentElement) {
39
41
  var _a;
40
- if (!document.fullscreenElement) {
41
- void ((_a = target.requestFullscreen) == null ? void 0 : _a.call(target));
42
- isFullscreen.value = true;
43
- } else {
44
- void document.exitFullscreen();
45
- isFullscreen.value = false;
46
- }
42
+ const change = document.fullscreenElement ? document.exitFullscreen() : (_a = target.requestFullscreen) == null ? void 0 : _a.call(target);
43
+ void (change == null ? void 0 : change.then(syncFullscreen, syncFullscreen));
47
44
  }
45
+ onMounted(() => document.addEventListener("fullscreenchange", syncFullscreen));
46
+ onUnmounted(() => document.removeEventListener("fullscreenchange", syncFullscreen));
48
47
  const toggleRemote = (tileId, el) => {
49
48
  const container = el ?? remoteParents.value[tileId];
50
49
  if (container) toggleFullscreen(container);
@@ -124,6 +123,7 @@ function useCallUi(opts) {
124
123
  showControls,
125
124
  resetControlsTimeout,
126
125
  isFullscreen,
126
+ canFullscreen,
127
127
  toggleFullscreen: () => toggleFullscreen(),
128
128
  toggleRemote,
129
129
  videoPaused,
@@ -150,8 +150,19 @@ function useCall({ layoutKey } = {}) {
150
150
  layoutKey
151
151
  });
152
152
  async function switchCamera(deviceId) {
153
- const stream = await session.switchCamera(deviceId);
154
- if (stream && ui.localVideo.value) ui.localVideo.value.srcObject = stream;
153
+ refreshPreview(await session.switchCamera(deviceId));
154
+ }
155
+ async function flipCamera() {
156
+ refreshPreview(await session.flipCamera());
157
+ }
158
+ function refreshPreview(stream) {
159
+ const el = ui.localVideo.value;
160
+ if (stream && el) {
161
+ el.srcObject = null;
162
+ el.srcObject = stream;
163
+ el.play().catch(() => {
164
+ });
165
+ }
155
166
  }
156
167
  return {
157
168
  // Call state
@@ -169,6 +180,8 @@ function useCall({ layoutKey } = {}) {
169
180
  remoteScreens: peers.remoteScreens,
170
181
  // Local media
171
182
  cameras: media.cameras,
183
+ facingMode: media.facingMode,
184
+ canFlipCamera: media.canFlipCamera,
172
185
  isAudioOn: media.isAudioOn,
173
186
  isVideoOn: media.isVideoOn,
174
187
  isScreenSharing: media.isScreenSharing,
@@ -179,12 +192,14 @@ function useCall({ layoutKey } = {}) {
179
192
  toggleFlashlight: media.toggleFlashlight,
180
193
  toggleScreenShare: session.toggleScreenShare,
181
194
  switchCamera,
195
+ flipCamera,
182
196
  endCall: callStore.endCall,
183
197
  // View
184
198
  showCameraModal: ref(false),
185
199
  showControls: ui.showControls,
186
200
  resetControlsTimeout: ui.resetControlsTimeout,
187
201
  isFullscreen: ui.isFullscreen,
202
+ canFullscreen: ui.canFullscreen,
188
203
  toggleFullscreen: ui.toggleFullscreen,
189
204
  toggleRemote: ui.toggleRemote,
190
205
  videoPaused: ui.videoPaused,
@@ -577,6 +592,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
577
592
  compact: { type: Boolean, default: false },
578
593
  paused: { type: Boolean, default: false },
579
594
  isFullscreen: { type: Boolean, default: false },
595
+ mirrored: { type: Boolean, default: false },
580
596
  hint: {}
581
597
  },
582
598
  emits: ["pin", "pause", "fullscreen", "retry", "video"],
@@ -658,7 +674,8 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
658
674
  muted: isSelf.value || isScreen.value,
659
675
  class: normalizeClass(["absolute inset-0 size-full rounded-[inherit]", [
660
676
  isScreen.value ? "object-contain" : "object-cover",
661
- __props.tile.kind === "self" && "pointer-events-none -scale-x-100"
677
+ __props.tile.kind === "self" && "pointer-events-none",
678
+ __props.mirrored && "-scale-x-100"
662
679
  ]])
663
680
  }, null, 10, _hoisted_3$2),
664
681
  showAvatar.value ? (openBlock(), createElementBlock("div", _hoisted_4$2, [
@@ -1008,11 +1025,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1008
1025
  toggleAudio,
1009
1026
  toggleVideo,
1010
1027
  switchCamera,
1028
+ flipCamera,
1029
+ canFlipCamera,
1030
+ facingMode,
1011
1031
  isFlashlightSupported,
1012
1032
  isAudioOn,
1013
1033
  isVideoOn,
1014
1034
  isFlashlightOn,
1015
1035
  isFullscreen,
1036
+ canFullscreen,
1016
1037
  isScreenSharing,
1017
1038
  showControls,
1018
1039
  resetControlsTimeout,
@@ -1092,6 +1113,20 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1092
1113
  const shareLabel = computed(
1093
1114
  () => isScreenSharing.value ? t("chat.call.controls.stopSharing") : t("chat.call.controls.shareScreen")
1094
1115
  );
1116
+ const flipLabel = computed(
1117
+ () => facingMode.value === "environment" ? t("chat.call.controls.frontCamera") : t("chat.call.controls.backCamera")
1118
+ );
1119
+ const showCameraPicker = computed(() => cameras.value.length > 1 && !canFlipCamera.value);
1120
+ const isFlipping = ref(false);
1121
+ const flip = async () => {
1122
+ if (isFlipping.value) return;
1123
+ isFlipping.value = true;
1124
+ try {
1125
+ await flipCamera();
1126
+ } finally {
1127
+ isFlipping.value = false;
1128
+ }
1129
+ };
1095
1130
  const fullscreenLabel = computed(
1096
1131
  () => isFullscreen.value ? t("chat.call.controls.exitFullscreen") : t("chat.call.controls.fullscreen")
1097
1132
  );
@@ -1120,20 +1155,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1120
1155
  items: cameras.value.map((camera, index) => ({
1121
1156
  label: camera.label || `${t("chat.call.controls.chooseCamera")} ${index + 1}`,
1122
1157
  callIcon: camera.deviceId === currentCameraId.value ? "check" : void 0,
1123
- command: () => {
1158
+ command: async () => {
1159
+ var _a, _b;
1124
1160
  currentCameraId.value = camera.deviceId;
1125
- void switchCamera(camera.deviceId);
1161
+ await switchCamera(camera.deviceId);
1162
+ currentCameraId.value = ((_b = (_a = localStream.value) == null ? void 0 : _a.getVideoTracks()[0]) == null ? void 0 : _b.getSettings().deviceId) ?? null;
1126
1163
  }
1127
1164
  }))
1128
1165
  }
1129
1166
  ]);
1130
1167
  const moreMenu = ref(null);
1131
1168
  const moreItems = computed(() => [
1132
- {
1133
- label: fullscreenLabel.value,
1134
- callIcon: isFullscreen.value ? "fullscreenExit" : "fullscreen",
1135
- command: () => toggleFullscreen()
1136
- },
1137
1169
  ...isFlashlightSupported.value ? [
1138
1170
  {
1139
1171
  label: isFlashlightOn.value ? t("chat.call.controls.flashlightOff") : t("chat.call.controls.flashlightOn"),
@@ -1247,7 +1279,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1247
1279
  canPin: canPin.value,
1248
1280
  compact,
1249
1281
  paused: !!videoPaused.value[tile.id],
1250
- isFullscreen: isFullscreen.value
1282
+ isFullscreen: isFullscreen.value,
1283
+ // The user's own camera shows as a mirror, as people expect; the back one shows the world as is.
1284
+ mirrored: tile.kind === "self" && facingMode.value !== "environment"
1251
1285
  });
1252
1286
  return (_ctx, _cache) => {
1253
1287
  return openBlock(), createElementBlock(Fragment, null, [
@@ -1268,10 +1302,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1268
1302
  playsinline: "",
1269
1303
  class: "pointer-events-none absolute inset-0 size-full object-cover"
1270
1304
  }, null, 512),
1271
- _cache[17] || (_cache[17] = createElementVNode("div", { class: "pointer-events-none absolute inset-0 bg-linear-to-t from-black/60 via-transparent to-black/30" }, null, -1)),
1305
+ _cache[18] || (_cache[18] = createElementVNode("div", { class: "pointer-events-none absolute inset-0 bg-linear-to-t from-black/60 via-transparent to-black/30" }, null, -1)),
1272
1306
  createElementVNode("div", _hoisted_2, [
1273
1307
  createElementVNode("div", _hoisted_3, [
1274
- _cache[16] || (_cache[16] = createElementVNode("span", { class: "relative flex size-2.5" }, [
1308
+ _cache[17] || (_cache[17] = createElementVNode("span", { class: "relative flex size-2.5" }, [
1275
1309
  createElementVNode("span", { class: "absolute inline-flex size-full animate-ping rounded-full bg-red-500/60 motion-reduce:animate-none" }),
1276
1310
  createElementVNode("span", { class: "relative inline-flex size-2.5 rounded-full bg-red-500" })
1277
1311
  ], -1)),
@@ -1349,12 +1383,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1349
1383
  createElementVNode("div", {
1350
1384
  "data-testid": "call-top-bar",
1351
1385
  class: normalizeClass(["flex h-14 shrink-0 items-center gap-x-3 px-3 transition-opacity duration-300 motion-reduce:transition-none md:h-16 md:px-6", unref(showControls) ? "opacity-100" : "opacity-0"]),
1352
- onMouseenter: _cache[5] || (_cache[5] = //@ts-ignore
1386
+ onMouseenter: _cache[6] || (_cache[6] = //@ts-ignore
1353
1387
  (...args) => unref(resetControlsTimeout) && unref(resetControlsTimeout)(...args))
1354
1388
  }, [
1355
1389
  createElementVNode("div", _hoisted_10, [
1356
1390
  createElementVNode("h1", _hoisted_11, toDisplayString(callTitle.value), 1),
1357
- _cache[18] || (_cache[18] = createElementVNode("span", {
1391
+ _cache[19] || (_cache[19] = createElementVNode("span", {
1358
1392
  "aria-hidden": "true",
1359
1393
  class: "h-4 w-px shrink-0 bg-white/30"
1360
1394
  }, null, -1)),
@@ -1388,6 +1422,25 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1388
1422
  { bottom: true }
1389
1423
  ]
1390
1424
  ]),
1425
+ unref(canFullscreen) ? withDirectives((openBlock(), createBlock(_sfc_main$3, {
1426
+ key: 0,
1427
+ icon: unref(isFullscreen) ? "fullscreenExit" : "fullscreen",
1428
+ label: fullscreenLabel.value,
1429
+ dt: unref(callButtonDt),
1430
+ text: false,
1431
+ "icon-class": "size-5",
1432
+ class: normalizeClass(["size-11!", unref(focusRing)]),
1433
+ "data-testid": "call-fullscreen",
1434
+ "data-active": unref(isFullscreen),
1435
+ onClick: _cache[5] || (_cache[5] = ($event) => unref(toggleFullscreen)())
1436
+ }, null, 8, ["icon", "label", "dt", "class", "data-active"])), [
1437
+ [
1438
+ unref(vTooltip),
1439
+ unref(tip)(fullscreenLabel.value),
1440
+ void 0,
1441
+ { bottom: true }
1442
+ ]
1443
+ ]) : createCommentVNode("", true),
1391
1444
  withDirectives(createVNode(_sfc_main$3, {
1392
1445
  icon: "pictureInPicture",
1393
1446
  label: unref(t)("chat.call.controls.minimize"),
@@ -1412,7 +1465,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1412
1465
  ref: stageRef,
1413
1466
  class: "relative min-h-0 flex-1 px-2 pb-2 md:px-4 md:pb-4",
1414
1467
  style: { "--call-gap": "0.5rem" },
1415
- onMousemove: _cache[10] || (_cache[10] = //@ts-ignore
1468
+ onMousemove: _cache[11] || (_cache[11] = //@ts-ignore
1416
1469
  (...args) => unref(resetControlsTimeout) && unref(resetControlsTimeout)(...args))
1417
1470
  }, [
1418
1471
  unref(soundBlocked) ? (openBlock(), createBlock(unref(Button), {
@@ -1459,9 +1512,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1459
1512
  }, tileProps(selfTile.value), {
1460
1513
  hint: unref(t)("chat.call.cameraIsOff"),
1461
1514
  class: "size-full",
1462
- onVideo: _cache[6] || (_cache[6] = (el, prev) => bindVideo(selfTile.value, el, prev)),
1463
- onPause: _cache[7] || (_cache[7] = (el) => togglePause(selfTile.value, el)),
1464
- onFullscreen: _cache[8] || (_cache[8] = (el) => toggleTileFullscreen(selfTile.value, el))
1515
+ onVideo: _cache[7] || (_cache[7] = (el, prev) => bindVideo(selfTile.value, el, prev)),
1516
+ onPause: _cache[8] || (_cache[8] = (el) => togglePause(selfTile.value, el)),
1517
+ onFullscreen: _cache[9] || (_cache[9] = (el) => toggleTileFullscreen(selfTile.value, el))
1465
1518
  }), null, 16, ["hint"])),
1466
1519
  showWaiting.value ? (openBlock(), createElementBlock("div", _hoisted_17, [
1467
1520
  createElementVNode("div", _hoisted_18, [
@@ -1487,7 +1540,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1487
1540
  }, tileProps(selfTile.value, true), {
1488
1541
  "can-pin": false,
1489
1542
  class: "absolute! end-5 bottom-4 z-10 aspect-video w-36 shadow-xl outline outline-white/25 sm:w-56 md:end-6 md:bottom-6 md:w-64",
1490
- onVideo: _cache[9] || (_cache[9] = (el, prev) => bindVideo(selfTile.value, el, prev))
1543
+ onVideo: _cache[10] || (_cache[10] = (el, prev) => bindVideo(selfTile.value, el, prev))
1491
1544
  }), null, 16))
1492
1545
  ], 64)) : unref(layout).mode.value === "grid" ? (openBlock(), createElementBlock("div", {
1493
1546
  key: 3,
@@ -1542,9 +1595,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1542
1595
  ], 544),
1543
1596
  createElementVNode("div", {
1544
1597
  class: normalizeClass(["flex h-20 shrink-0 items-center justify-center px-3 transition-opacity duration-300 motion-reduce:transition-none md:px-6", unref(showControls) ? "opacity-100" : "opacity-0"]),
1545
- onMouseenter: _cache[13] || (_cache[13] = //@ts-ignore
1598
+ onMouseenter: _cache[14] || (_cache[14] = //@ts-ignore
1546
1599
  (...args) => unref(resetControlsTimeout) && unref(resetControlsTimeout)(...args)),
1547
- onMousemove: _cache[14] || (_cache[14] = //@ts-ignore
1600
+ onMousemove: _cache[15] || (_cache[15] = //@ts-ignore
1548
1601
  (...args) => unref(resetControlsTimeout) && unref(resetControlsTimeout)(...args))
1549
1602
  }, [
1550
1603
  createElementVNode("div", _hoisted_21, [
@@ -1566,9 +1619,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1566
1619
  ]
1567
1620
  ]),
1568
1621
  createElementVNode("div", {
1569
- class: normalizeClass(["flex items-center rounded-full", unref(cameras).length > 1 && "bg-white/12"])
1622
+ class: normalizeClass(["flex items-center rounded-full", showCameraPicker.value && "bg-white/12"])
1570
1623
  }, [
1571
- unref(cameras).length > 1 ? withDirectives((openBlock(), createBlock(_sfc_main$3, {
1624
+ showCameraPicker.value ? withDirectives((openBlock(), createBlock(_sfc_main$3, {
1572
1625
  key: 0,
1573
1626
  icon: "arrowDropUp",
1574
1627
  label: unref(t)("chat.call.controls.chooseCamera"),
@@ -1578,7 +1631,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1578
1631
  "icon-class": "size-6",
1579
1632
  class: normalizeClass(["h-12! w-8! rounded-e-none! ps-1!", unref(focusRing)]),
1580
1633
  "aria-haspopup": "true",
1581
- onClick: _cache[11] || (_cache[11] = ($event) => {
1634
+ onClick: _cache[12] || (_cache[12] = ($event) => {
1582
1635
  var _a;
1583
1636
  return (_a = cameraMenu.value) == null ? void 0 : _a.toggle($event);
1584
1637
  })
@@ -1608,7 +1661,25 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1608
1661
  ]
1609
1662
  ])
1610
1663
  ], 2),
1611
- withDirectives(createVNode(_sfc_main$3, mergeProps({
1664
+ unref(canFlipCamera) ? withDirectives((openBlock(), createBlock(_sfc_main$3, mergeProps({
1665
+ key: 0,
1666
+ icon: "cameraSwitch",
1667
+ label: flipLabel.value,
1668
+ disabled: !unref(isVideoOn) || isFlipping.value
1669
+ }, barButton, {
1670
+ "data-testid": "call-flip-camera",
1671
+ "data-facing": unref(facingMode) ?? void 0,
1672
+ onClick: flip
1673
+ }), null, 16, ["label", "disabled", "data-facing"])), [
1674
+ [
1675
+ unref(vTooltip),
1676
+ unref(tip)(flipLabel.value),
1677
+ void 0,
1678
+ { top: true }
1679
+ ]
1680
+ ]) : createCommentVNode("", true),
1681
+ unref(callStore).canShareScreen ? withDirectives((openBlock(), createBlock(_sfc_main$3, mergeProps({
1682
+ key: 1,
1612
1683
  icon: unref(isScreenSharing) ? "cancelPresentation" : "presentToAll",
1613
1684
  label: shareLabel.value,
1614
1685
  severity: unref(isScreenSharing) ? "contrast" : "secondary"
@@ -1616,33 +1687,34 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1616
1687
  "data-testid": "call-toggle-screen",
1617
1688
  "data-active": unref(isScreenSharing),
1618
1689
  onClick: unref(toggleScreenShare)
1619
- }), null, 16, ["icon", "label", "severity", "data-active", "onClick"]), [
1690
+ }), null, 16, ["icon", "label", "severity", "data-active", "onClick"])), [
1620
1691
  [
1621
1692
  unref(vTooltip),
1622
1693
  unref(tip)(shareLabel.value),
1623
1694
  void 0,
1624
1695
  { top: true }
1625
1696
  ]
1626
- ]),
1627
- withDirectives(createVNode(_sfc_main$3, mergeProps({
1697
+ ]) : createCommentVNode("", true),
1698
+ moreItems.value.length ? withDirectives((openBlock(), createBlock(_sfc_main$3, mergeProps({
1699
+ key: 2,
1628
1700
  icon: "moreVert",
1629
1701
  label: unref(t)("chat.call.controls.more")
1630
1702
  }, barButton, {
1631
1703
  class: "h-12! w-10! sm:w-12!",
1632
1704
  "aria-haspopup": "true",
1633
1705
  "data-testid": "call-more",
1634
- onClick: _cache[12] || (_cache[12] = ($event) => {
1706
+ onClick: _cache[13] || (_cache[13] = ($event) => {
1635
1707
  var _a;
1636
1708
  return (_a = moreMenu.value) == null ? void 0 : _a.toggle($event);
1637
1709
  })
1638
- }), null, 16, ["label"]), [
1710
+ }), null, 16, ["label"])), [
1639
1711
  [
1640
1712
  unref(vTooltip),
1641
1713
  unref(tip)(unref(t)("chat.call.controls.more")),
1642
1714
  void 0,
1643
1715
  { top: true }
1644
1716
  ]
1645
- ]),
1717
+ ]) : createCommentVNode("", true),
1646
1718
  withDirectives(createVNode(_sfc_main$3, {
1647
1719
  icon: "callEnd",
1648
1720
  label: unref(t)("chat.call.controls.endCall"),
@@ -1666,7 +1738,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1666
1738
  ], 34),
1667
1739
  createVNode(_sfc_main$1, {
1668
1740
  visible: peopleOpen.value,
1669
- "onUpdate:visible": _cache[15] || (_cache[15] = ($event) => peopleOpen.value = $event),
1741
+ "onUpdate:visible": _cache[16] || (_cache[16] = ($event) => peopleOpen.value = $event),
1670
1742
  participants: unref(participants)
1671
1743
  }, null, 8, ["visible", "participants"]),
1672
1744
  createVNode(unref(Menu), {
@@ -1714,4 +1786,4 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1714
1786
  export {
1715
1787
  _sfc_main as default
1716
1788
  };
1717
- //# sourceMappingURL=Call-DvVJ7IsY.mjs.map
1789
+ //# sourceMappingURL=Call-DfAAePMJ.mjs.map