vue-parley 4.0.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 (202) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +276 -0
  3. package/dist/chat.css +3223 -0
  4. package/dist/chunks/Call-CTIujxDi.cjs +818 -0
  5. package/dist/chunks/Call-CTIujxDi.cjs.map +1 -0
  6. package/dist/chunks/Call-Dwuyd-Ut.mjs +818 -0
  7. package/dist/chunks/Call-Dwuyd-Ut.mjs.map +1 -0
  8. package/dist/chunks/index-D50Yn7q4.cjs +7031 -0
  9. package/dist/chunks/index-D50Yn7q4.cjs.map +1 -0
  10. package/dist/chunks/index-JU_JZkSC.mjs +7010 -0
  11. package/dist/chunks/index-JU_JZkSC.mjs.map +1 -0
  12. package/dist/chunks/session-B3KIrj3_.mjs +711 -0
  13. package/dist/chunks/session-B3KIrj3_.mjs.map +1 -0
  14. package/dist/chunks/session-BOfkV8PJ.cjs +711 -0
  15. package/dist/chunks/session-BOfkV8PJ.cjs.map +1 -0
  16. package/dist/fakes.cjs +335 -0
  17. package/dist/fakes.cjs.map +1 -0
  18. package/dist/fakes.mjs +335 -0
  19. package/dist/fakes.mjs.map +1 -0
  20. package/dist/index.cjs +24 -0
  21. package/dist/index.cjs.map +1 -0
  22. package/dist/index.mjs +24 -0
  23. package/dist/index.mjs.map +1 -0
  24. package/dist/types/app/components/ChatPage.vue.d.ts +60 -0
  25. package/dist/types/app/components/ChatPage.vue.d.ts.map +1 -0
  26. package/dist/types/app/components/call/Call.vue.d.ts +8 -0
  27. package/dist/types/app/components/call/Call.vue.d.ts.map +1 -0
  28. package/dist/types/app/components/chat/ChatBubble.vue.d.ts +64 -0
  29. package/dist/types/app/components/chat/ChatBubble.vue.d.ts.map +1 -0
  30. package/dist/types/app/components/chat/ChatInput.vue.d.ts +60 -0
  31. package/dist/types/app/components/chat/ChatInput.vue.d.ts.map +1 -0
  32. package/dist/types/app/components/chat/ChatMessages.vue.d.ts +45 -0
  33. package/dist/types/app/components/chat/ChatMessages.vue.d.ts.map +1 -0
  34. package/dist/types/app/components/chat/ChatPageBar.vue.d.ts +50 -0
  35. package/dist/types/app/components/chat/ChatPageBar.vue.d.ts.map +1 -0
  36. package/dist/types/app/components/chat/ChatProfileOverview.vue.d.ts +11 -0
  37. package/dist/types/app/components/chat/ChatProfileOverview.vue.d.ts.map +1 -0
  38. package/dist/types/app/components/chat/ChatView.vue.d.ts +244 -0
  39. package/dist/types/app/components/chat/ChatView.vue.d.ts.map +1 -0
  40. package/dist/types/app/components/chat/chat-bubbles/BubbleDivider.vue.d.ts +7 -0
  41. package/dist/types/app/components/chat/chat-bubbles/BubbleDivider.vue.d.ts.map +1 -0
  42. package/dist/types/app/components/chat/chat-bubbles/BubbleImages.vue.d.ts +13 -0
  43. package/dist/types/app/components/chat/chat-bubbles/BubbleImages.vue.d.ts.map +1 -0
  44. package/dist/types/app/components/chat/chat-bubbles/BubbleMeta.vue.d.ts +11 -0
  45. package/dist/types/app/components/chat/chat-bubbles/BubbleMeta.vue.d.ts.map +1 -0
  46. package/dist/types/app/components/chat/chat-bubbles/BubbleOptions.vue.d.ts +16 -0
  47. package/dist/types/app/components/chat/chat-bubbles/BubbleOptions.vue.d.ts.map +1 -0
  48. package/dist/types/app/components/chat/chat-bubbles/BubbleRequest.vue.d.ts +8 -0
  49. package/dist/types/app/components/chat/chat-bubbles/BubbleRequest.vue.d.ts.map +1 -0
  50. package/dist/types/app/components/chat/chat-bubbles/BubbleSelectionMark.vue.d.ts +7 -0
  51. package/dist/types/app/components/chat/chat-bubbles/BubbleSelectionMark.vue.d.ts.map +1 -0
  52. package/dist/types/app/components/chat/chat-bubbles/BubbleStatus.vue.d.ts +7 -0
  53. package/dist/types/app/components/chat/chat-bubbles/BubbleStatus.vue.d.ts.map +1 -0
  54. package/dist/types/app/components/chat/chat-bubbles/BubbleVideo.vue.d.ts +25 -0
  55. package/dist/types/app/components/chat/chat-bubbles/BubbleVideo.vue.d.ts.map +1 -0
  56. package/dist/types/app/components/chat/chat-bubbles/FileDisplay.vue.d.ts +13 -0
  57. package/dist/types/app/components/chat/chat-bubbles/FileDisplay.vue.d.ts.map +1 -0
  58. package/dist/types/app/components/chat/chat-bubbles/ImageGroupDisplay.vue.d.ts +14 -0
  59. package/dist/types/app/components/chat/chat-bubbles/ImageGroupDisplay.vue.d.ts.map +1 -0
  60. package/dist/types/app/components/chat/chat-bubbles/ReplyPreview.vue.d.ts +10 -0
  61. package/dist/types/app/components/chat/chat-bubbles/ReplyPreview.vue.d.ts.map +1 -0
  62. package/dist/types/app/components/chat/chat-bubbles/UploadProgressOverlay.vue.d.ts +10 -0
  63. package/dist/types/app/components/chat/chat-bubbles/UploadProgressOverlay.vue.d.ts.map +1 -0
  64. package/dist/types/app/components/chat/chat-bubbles/VoiceDisplay.vue.d.ts +12 -0
  65. package/dist/types/app/components/chat/chat-bubbles/VoiceDisplay.vue.d.ts.map +1 -0
  66. package/dist/types/app/components/chat/chat-input/AttachementFileDisplay.vue.d.ts +12 -0
  67. package/dist/types/app/components/chat/chat-input/AttachementFileDisplay.vue.d.ts.map +1 -0
  68. package/dist/types/app/components/chat/chat-input/InputActionBar.vue.d.ts +13 -0
  69. package/dist/types/app/components/chat/chat-input/InputActionBar.vue.d.ts.map +1 -0
  70. package/dist/types/app/components/chat/chat-input/InputAttachement.vue.d.ts +18 -0
  71. package/dist/types/app/components/chat/chat-input/InputAttachement.vue.d.ts.map +1 -0
  72. package/dist/types/app/components/chat/chat-input/PermissionPopup.vue.d.ts +8 -0
  73. package/dist/types/app/components/chat/chat-input/PermissionPopup.vue.d.ts.map +1 -0
  74. package/dist/types/app/components/chat/chat-input/RecordButton.vue.d.ts +27 -0
  75. package/dist/types/app/components/chat/chat-input/RecordButton.vue.d.ts.map +1 -0
  76. package/dist/types/app/components/chat/chat-input/RecordingStatus.vue.d.ts +12 -0
  77. package/dist/types/app/components/chat/chat-input/RecordingStatus.vue.d.ts.map +1 -0
  78. package/dist/types/app/components/chat/chat-input/VideoRecordDisplay.vue.d.ts +26 -0
  79. package/dist/types/app/components/chat/chat-input/VideoRecordDisplay.vue.d.ts.map +1 -0
  80. package/dist/types/app/components/chat/contact/ChatContactDisplay.vue.d.ts +8 -0
  81. package/dist/types/app/components/chat/contact/ChatContactDisplay.vue.d.ts.map +1 -0
  82. package/dist/types/app/components/chat/contact/ChatList.vue.d.ts +5 -0
  83. package/dist/types/app/components/chat/contact/ChatList.vue.d.ts.map +1 -0
  84. package/dist/types/app/components/chat/contact/ChatListSearch.vue.d.ts +16 -0
  85. package/dist/types/app/components/chat/contact/ChatListSearch.vue.d.ts.map +1 -0
  86. package/dist/types/app/components/chat/contact/ContactAvatar.vue.d.ts +10 -0
  87. package/dist/types/app/components/chat/contact/ContactAvatar.vue.d.ts.map +1 -0
  88. package/dist/types/app/components/chat/contact/ContactSkeleton.vue.d.ts +3 -0
  89. package/dist/types/app/components/chat/contact/ContactSkeleton.vue.d.ts.map +1 -0
  90. package/dist/types/app/components/chat/messages/FloatingDateHeader.vue.d.ts +9 -0
  91. package/dist/types/app/components/chat/messages/FloatingDateHeader.vue.d.ts.map +1 -0
  92. package/dist/types/app/components/chat/messages/MessagesSkeleton.vue.d.ts +8 -0
  93. package/dist/types/app/components/chat/messages/MessagesSkeleton.vue.d.ts.map +1 -0
  94. package/dist/types/app/components/chat/messages/ScrollToBottomButton.vue.d.ts +11 -0
  95. package/dist/types/app/components/chat/messages/ScrollToBottomButton.vue.d.ts.map +1 -0
  96. package/dist/types/app/components/chat/profile/FileDisplay.vue.d.ts +9 -0
  97. package/dist/types/app/components/chat/profile/FileDisplay.vue.d.ts.map +1 -0
  98. package/dist/types/app/components/general/ConfirmModal.vue.d.ts +21 -0
  99. package/dist/types/app/components/general/ConfirmModal.vue.d.ts.map +1 -0
  100. package/dist/types/app/components/general/FileFormatDisplay.vue.d.ts +16 -0
  101. package/dist/types/app/components/general/FileFormatDisplay.vue.d.ts.map +1 -0
  102. package/dist/types/app/components/general/IconButton.vue.d.ts +13 -0
  103. package/dist/types/app/components/general/IconButton.vue.d.ts.map +1 -0
  104. package/dist/types/app/components/general/LoadingStatus.vue.d.ts +16 -0
  105. package/dist/types/app/components/general/LoadingStatus.vue.d.ts.map +1 -0
  106. package/dist/types/app/components/general/MediaImage.vue.d.ts +30 -0
  107. package/dist/types/app/components/general/MediaImage.vue.d.ts.map +1 -0
  108. package/dist/types/app/components/general/NoDataDisplay.vue.d.ts +7 -0
  109. package/dist/types/app/components/general/NoDataDisplay.vue.d.ts.map +1 -0
  110. package/dist/types/app/components/general/ResponsiveDialog.vue.d.ts +28 -0
  111. package/dist/types/app/components/general/ResponsiveDialog.vue.d.ts.map +1 -0
  112. package/dist/types/app/components/general/SafeEmojiText.vue.d.ts +10 -0
  113. package/dist/types/app/components/general/SafeEmojiText.vue.d.ts.map +1 -0
  114. package/dist/types/app/components/global/BEmojiPicker.vue.d.ts +8 -0
  115. package/dist/types/app/components/global/BEmojiPicker.vue.d.ts.map +1 -0
  116. package/dist/types/app/components/global/BIcon.vue.d.ts +11 -0
  117. package/dist/types/app/components/global/BIcon.vue.d.ts.map +1 -0
  118. package/dist/types/app/components/global/BVirtualVerticalList.vue.d.ts +30 -0
  119. package/dist/types/app/components/global/BVirtualVerticalList.vue.d.ts.map +1 -0
  120. package/dist/types/app/composables/call/media.d.ts +204 -0
  121. package/dist/types/app/composables/call/media.d.ts.map +1 -0
  122. package/dist/types/app/composables/call/peer.d.ts +39 -0
  123. package/dist/types/app/composables/call/peer.d.ts.map +1 -0
  124. package/dist/types/app/composables/call/peers.d.ts +54 -0
  125. package/dist/types/app/composables/call/peers.d.ts.map +1 -0
  126. package/dist/types/app/composables/call/session.d.ts +284 -0
  127. package/dist/types/app/composables/call/session.d.ts.map +1 -0
  128. package/dist/types/app/composables/call/signaling.d.ts +36 -0
  129. package/dist/types/app/composables/call/signaling.d.ts.map +1 -0
  130. package/dist/types/app/composables/call/useCallUi.d.ts +27 -0
  131. package/dist/types/app/composables/call/useCallUi.d.ts.map +1 -0
  132. package/dist/types/app/composables/chat/useChatRecording.d.ts +75 -0
  133. package/dist/types/app/composables/chat/useChatRecording.d.ts.map +1 -0
  134. package/dist/types/app/composables/chat/useInputDraft.d.ts +14 -0
  135. package/dist/types/app/composables/chat/useInputDraft.d.ts.map +1 -0
  136. package/dist/types/app/composables/useAppPermissions.d.ts +25 -0
  137. package/dist/types/app/composables/useAppPermissions.d.ts.map +1 -0
  138. package/dist/types/app/composables/useAppToast.d.ts +13 -0
  139. package/dist/types/app/composables/useAppToast.d.ts.map +1 -0
  140. package/dist/types/app/composables/useAttachmentPicker.d.ts +18 -0
  141. package/dist/types/app/composables/useAttachmentPicker.d.ts.map +1 -0
  142. package/dist/types/app/composables/useCall.d.ts +91 -0
  143. package/dist/types/app/composables/useCall.d.ts.map +1 -0
  144. package/dist/types/app/composables/useChatMessageList.d.ts +18 -0
  145. package/dist/types/app/composables/useChatMessageList.d.ts.map +1 -0
  146. package/dist/types/app/composables/useDate.d.ts +7 -0
  147. package/dist/types/app/composables/useDate.d.ts.map +1 -0
  148. package/dist/types/app/composables/useDevice.d.ts +32 -0
  149. package/dist/types/app/composables/useDevice.d.ts.map +1 -0
  150. package/dist/types/app/composables/useFlippedVirtualScroll.d.ts +22 -0
  151. package/dist/types/app/composables/useFlippedVirtualScroll.d.ts.map +1 -0
  152. package/dist/types/app/composables/useHostI18n.d.ts +15 -0
  153. package/dist/types/app/composables/useHostI18n.d.ts.map +1 -0
  154. package/dist/types/app/composables/useLocalI18n.d.ts +5 -0
  155. package/dist/types/app/composables/useLocalI18n.d.ts.map +1 -0
  156. package/dist/types/app/composables/useLongPress.d.ts +6 -0
  157. package/dist/types/app/composables/useLongPress.d.ts.map +1 -0
  158. package/dist/types/app/composables/useRichTextEditor.d.ts +12 -0
  159. package/dist/types/app/composables/useRichTextEditor.d.ts.map +1 -0
  160. package/dist/types/app/directives/loading.d.ts +6 -0
  161. package/dist/types/app/directives/loading.d.ts.map +1 -0
  162. package/dist/types/app/index.d.ts +31 -0
  163. package/dist/types/app/index.d.ts.map +1 -0
  164. package/dist/types/app/plugin.d.ts +28 -0
  165. package/dist/types/app/plugin.d.ts.map +1 -0
  166. package/dist/types/app/provider/callProvider.d.ts +7 -0
  167. package/dist/types/app/provider/callProvider.d.ts.map +1 -0
  168. package/dist/types/app/stores/callStore.d.ts +1626 -0
  169. package/dist/types/app/stores/callStore.d.ts.map +1 -0
  170. package/dist/types/app/stores/chatStore.d.ts +126 -0
  171. package/dist/types/app/stores/chatStore.d.ts.map +1 -0
  172. package/dist/types/app/stores/mediaStore.d.ts +18 -0
  173. package/dist/types/app/stores/mediaStore.d.ts.map +1 -0
  174. package/dist/types/app/stores/messageStores.d.ts +2460 -0
  175. package/dist/types/app/stores/messageStores.d.ts.map +1 -0
  176. package/dist/types/app/stores/profileStore.d.ts +102 -0
  177. package/dist/types/app/stores/profileStore.d.ts.map +1 -0
  178. package/dist/types/app/types/components/chat-input.d.ts +4 -0
  179. package/dist/types/app/types/components/chat-input.d.ts.map +1 -0
  180. package/dist/types/app/types/components/menu-options.d.ts +7 -0
  181. package/dist/types/app/types/components/menu-options.d.ts.map +1 -0
  182. package/dist/types/app/types/components/modal.d.ts +17 -0
  183. package/dist/types/app/types/components/modal.d.ts.map +1 -0
  184. package/dist/types/app/types/index.d.ts +257 -0
  185. package/dist/types/app/types/index.d.ts.map +1 -0
  186. package/dist/types/app/utils/emojiParser.d.ts +5 -0
  187. package/dist/types/app/utils/emojiParser.d.ts.map +1 -0
  188. package/dist/types/app/utils/format.d.ts +4 -0
  189. package/dist/types/app/utils/format.d.ts.map +1 -0
  190. package/dist/types/fakes/backend.d.ts +25 -0
  191. package/dist/types/fakes/backend.d.ts.map +1 -0
  192. package/dist/types/fakes/call.d.ts +7 -0
  193. package/dist/types/fakes/call.d.ts.map +1 -0
  194. package/dist/types/fakes/data.d.ts +13 -0
  195. package/dist/types/fakes/data.d.ts.map +1 -0
  196. package/dist/types/fakes/index.d.ts +7 -0
  197. package/dist/types/fakes/index.d.ts.map +1 -0
  198. package/dist/types/fakes.d.ts +2 -0
  199. package/dist/types/i18n/locales/index.d.ts +3557 -0
  200. package/dist/types/i18n/locales/index.d.ts.map +1 -0
  201. package/dist/types/index.d.ts +2 -0
  202. package/package.json +98 -0
@@ -0,0 +1,818 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const index = require("./index-D50Yn7q4.cjs");
4
+ const vue = require("vue");
5
+ const core = require("@vueuse/core");
6
+ const Button = require("primevue/button");
7
+ const Listbox = require("primevue/listbox");
8
+ const CONTROLS_HIDE_AFTER_MS = 3e3;
9
+ function useCallUi(opts) {
10
+ const { localStream, screenStream, remoteVideos, remoteScreens } = opts;
11
+ const localVideo = vue.ref(null);
12
+ const localScreen = vue.ref(null);
13
+ const remoteRefs = vue.ref({});
14
+ const remoteScreenRefs = vue.ref({});
15
+ const remoteParents = vue.ref({});
16
+ const showControls = vue.ref(true);
17
+ let controlsTimeout;
18
+ function resetControlsTimeout() {
19
+ showControls.value = true;
20
+ clearTimeout(controlsTimeout);
21
+ controlsTimeout = setTimeout(
22
+ () => showControls.value = false,
23
+ CONTROLS_HIDE_AFTER_MS
24
+ );
25
+ }
26
+ const inputEvents = ["mousemove", "click", "keydown"];
27
+ vue.onMounted(() => {
28
+ resetControlsTimeout();
29
+ inputEvents.forEach((e) => document.addEventListener(e, resetControlsTimeout));
30
+ });
31
+ vue.onUnmounted(() => {
32
+ inputEvents.forEach((e) => document.removeEventListener(e, resetControlsTimeout));
33
+ clearTimeout(controlsTimeout);
34
+ detachAll();
35
+ });
36
+ const isFullscreen = vue.ref(false);
37
+ function toggleFullscreen(target = document.documentElement) {
38
+ var _a;
39
+ if (!document.fullscreenElement) {
40
+ void ((_a = target.requestFullscreen) == null ? void 0 : _a.call(target));
41
+ isFullscreen.value = true;
42
+ } else {
43
+ void document.exitFullscreen();
44
+ isFullscreen.value = false;
45
+ }
46
+ }
47
+ const toggleRemote = (tileId, el) => {
48
+ const container = el ?? remoteParents.value[tileId];
49
+ if (container) toggleFullscreen(container);
50
+ };
51
+ const videoPaused = vue.ref({});
52
+ function toggleVideoPause(tileId, el) {
53
+ if (!(el instanceof HTMLVideoElement)) return;
54
+ if (videoPaused.value[tileId]) void el.play();
55
+ else el.pause();
56
+ videoPaused.value[tileId] = !videoPaused.value[tileId];
57
+ }
58
+ const attach = (el, stream) => {
59
+ if (!el) return;
60
+ if (el.srcObject !== stream) el.srcObject = stream;
61
+ el.play().catch(() => {
62
+ });
63
+ };
64
+ vue.watch(
65
+ [localStream, opts.isMinimized],
66
+ async () => {
67
+ await vue.nextTick();
68
+ if (localStream.value && localVideo.value)
69
+ localVideo.value.srcObject = localStream.value;
70
+ },
71
+ { immediate: true }
72
+ );
73
+ vue.watch(
74
+ [screenStream, opts.isMinimized],
75
+ async () => {
76
+ await vue.nextTick();
77
+ if (localScreen.value) localScreen.value.srcObject = screenStream.value;
78
+ },
79
+ { immediate: true }
80
+ );
81
+ vue.watch(
82
+ [() => ({ ...remoteVideos.value }), opts.isMinimized],
83
+ async () => {
84
+ await vue.nextTick();
85
+ for (const [id, { stream }] of Object.entries(remoteVideos.value))
86
+ attach(remoteRefs.value[id], stream);
87
+ },
88
+ { immediate: true }
89
+ );
90
+ vue.watch(
91
+ [() => ({ ...remoteScreens.value }), opts.isMinimized],
92
+ async () => {
93
+ await vue.nextTick();
94
+ for (const [id, { stream }] of Object.entries(remoteScreens.value))
95
+ attach(remoteScreenRefs.value[id], stream);
96
+ },
97
+ { immediate: true }
98
+ );
99
+ function detachAll() {
100
+ const all = [
101
+ localVideo.value,
102
+ localScreen.value,
103
+ ...Object.values(remoteRefs.value),
104
+ ...Object.values(remoteScreenRefs.value)
105
+ ];
106
+ for (const el of all) if (el) el.srcObject = null;
107
+ }
108
+ return {
109
+ localVideo,
110
+ localScreen,
111
+ remoteRefs,
112
+ remoteScreenRefs,
113
+ remoteParents,
114
+ showControls,
115
+ resetControlsTimeout,
116
+ isFullscreen,
117
+ toggleFullscreen: () => toggleFullscreen(),
118
+ toggleRemote,
119
+ videoPaused,
120
+ toggleVideoPause,
121
+ detachAll
122
+ };
123
+ }
124
+ function useCall() {
125
+ const callStore = index.useCallStore();
126
+ const session = callStore.session;
127
+ if (!session) {
128
+ throw new Error("[vue-chat] useCall() needs a running call: callStore.startCall() first");
129
+ }
130
+ const { media, peers } = session;
131
+ const ui = useCallUi({
132
+ localStream: media.localStream,
133
+ screenStream: media.screenStream,
134
+ remoteVideos: peers.remoteVideos,
135
+ remoteScreens: peers.remoteScreens,
136
+ isMinimized: () => callStore.isMinimized
137
+ });
138
+ async function switchCamera(deviceId) {
139
+ const stream = await session.switchCamera(deviceId);
140
+ if (stream && ui.localVideo.value) ui.localVideo.value.srcObject = stream;
141
+ }
142
+ return {
143
+ // Call state
144
+ participantCount: session.participantCount,
145
+ tileCount: session.tileCount,
146
+ localStream: media.localStream,
147
+ remoteVideos: peers.remoteVideos,
148
+ remoteScreens: peers.remoteScreens,
149
+ // Local media
150
+ cameras: media.cameras,
151
+ isAudioOn: media.isAudioOn,
152
+ isVideoOn: media.isVideoOn,
153
+ isScreenSharing: media.isScreenSharing,
154
+ isFlashlightOn: media.isFlashlightOn,
155
+ isFlashlightSupported: media.isFlashlightSupported,
156
+ toggleAudio: media.toggleAudio,
157
+ toggleVideo: media.toggleVideo,
158
+ toggleFlashlight: media.toggleFlashlight,
159
+ toggleScreenShare: session.toggleScreenShare,
160
+ switchCamera,
161
+ endCall: callStore.endCall,
162
+ // View
163
+ showCameraModal: vue.ref(false),
164
+ showControls: ui.showControls,
165
+ resetControlsTimeout: ui.resetControlsTimeout,
166
+ isFullscreen: ui.isFullscreen,
167
+ toggleFullscreen: ui.toggleFullscreen,
168
+ toggleRemote: ui.toggleRemote,
169
+ videoPaused: ui.videoPaused,
170
+ toggleVideoPause: ui.toggleVideoPause,
171
+ localVideo: ui.localVideo,
172
+ localScreen: ui.localScreen,
173
+ remoteRefs: ui.remoteRefs,
174
+ remoteScreenRefs: ui.remoteScreenRefs,
175
+ remoteParents: ui.remoteParents
176
+ };
177
+ }
178
+ const _hoisted_1 = { class: "relative h-full w-full" };
179
+ const _hoisted_2 = { class: "absolute top-3 right-3 left-3 z-10 flex items-center justify-between" };
180
+ const _hoisted_3 = { class: "flex items-center gap-x-2 rounded-full bg-black/40 px-3 py-1.5 backdrop-blur-sm" };
181
+ const _hoisted_4 = { class: "text-label-sm text-white/90 select-none" };
182
+ const _hoisted_5 = { class: "absolute right-3 bottom-3 left-3 z-10 flex items-center justify-between" };
183
+ const _hoisted_6 = { class: "flex items-center gap-2" };
184
+ const _hoisted_7 = {
185
+ key: 0,
186
+ class: "flex gap-1"
187
+ };
188
+ const _hoisted_8 = {
189
+ key: 0,
190
+ class: "flex h-7 w-7 items-center justify-center rounded-full bg-diamond-error"
191
+ };
192
+ const _hoisted_9 = {
193
+ key: 1,
194
+ class: "flex h-7 w-7 items-center justify-center rounded-full bg-diamond-error"
195
+ };
196
+ const _hoisted_10 = {
197
+ "data-testid": "call-view",
198
+ class: "vue-chat fixed inset-0 z-[60] flex h-full w-full flex-col bg-diamond-black"
199
+ };
200
+ const _hoisted_11 = { class: "flex items-center gap-x-4" };
201
+ const _hoisted_12 = { class: "hidden select-none text-label-lg text-white md:block" };
202
+ const _hoisted_13 = { class: "flex items-center gap-x-2 text-white text-body-sm" };
203
+ const _hoisted_14 = { "data-testid": "call-participants" };
204
+ const _hoisted_15 = { class: "flex items-center gap-x-4.5" };
205
+ const _hoisted_16 = { class: "flex h-6 items-center justify-center rounded-full bg-diamond-error px-2 text-white select-none" };
206
+ const _hoisted_17 = { class: "text-body-sm" };
207
+ const _hoisted_18 = { class: "grid h-full min-h-0 w-full min-w-0 grid-cols-1 gap-4 md:grid-cols-[repeat(auto-fit,minmax(300px,1fr))]" };
208
+ const _hoisted_19 = { class: "absolute bottom-3 left-3 z-20 flex items-center gap-x-2" };
209
+ const _hoisted_20 = { class: "rounded bg-black-500 px-2 py-1 text-label-sm text-white select-none" };
210
+ const _hoisted_21 = { class: "flex h-10 w-10 items-center justify-center rounded-full bg-black-500" };
211
+ const _hoisted_22 = { class: "absolute bottom-2 left-2 z-20 flex items-center gap-x-1" };
212
+ const _hoisted_23 = { class: "rounded bg-black-500 px-1.5 py-0.5 text-label-sm text-white select-none" };
213
+ const _hoisted_24 = { class: "absolute bottom-3 left-3 z-20 flex items-center gap-x-2" };
214
+ const _hoisted_25 = { class: "rounded bg-black-500 px-2 py-1 text-label-sm text-white select-none" };
215
+ const _hoisted_26 = { class: "flex h-10 w-10 items-center justify-center rounded-full bg-black-500" };
216
+ const _hoisted_27 = { class: "absolute bottom-3 left-3 z-20 flex items-center gap-x-2" };
217
+ const _hoisted_28 = { class: "rounded bg-black-500 px-2 py-1 text-label-sm text-white select-none" };
218
+ const _hoisted_29 = {
219
+ key: 0,
220
+ class: "flex h-7 w-7 items-center justify-center rounded-full bg-diamond-error"
221
+ };
222
+ const _hoisted_30 = {
223
+ key: 0,
224
+ class: "absolute inset-0 flex items-center justify-center bg-black-600"
225
+ };
226
+ const _hoisted_31 = { class: "text-center text-white" };
227
+ const _hoisted_32 = { class: "mx-auto mb-2 flex h-16 w-16 items-center justify-center rounded-full bg-chat-primary" };
228
+ const _hoisted_33 = { class: "text-title-lg font-semibold" };
229
+ const _hoisted_34 = { class: "text-label-md" };
230
+ const PIP_WIDTH = 280;
231
+ const PIP_HEIGHT = 160;
232
+ const PADDING = 16;
233
+ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
234
+ __name: "Call",
235
+ setup(__props) {
236
+ const callStore = index.useCallStore();
237
+ const minimizedRef = vue.ref(null);
238
+ const bodyRef = vue.ref(null);
239
+ const cameraPickerOpen = vue.ref(false);
240
+ const { t, locale } = index.useLocalI18n(index.chat);
241
+ const { dir } = index.useDirection();
242
+ const {
243
+ toggleVideoPause,
244
+ toggleRemote,
245
+ participantCount,
246
+ endCall,
247
+ toggleFullscreen,
248
+ toggleFlashlight,
249
+ toggleScreenShare,
250
+ toggleAudio,
251
+ toggleVideo,
252
+ switchCamera,
253
+ isFlashlightSupported,
254
+ tileCount,
255
+ isAudioOn,
256
+ isVideoOn,
257
+ isFlashlightOn,
258
+ isFullscreen,
259
+ isScreenSharing,
260
+ showControls,
261
+ resetControlsTimeout,
262
+ cameras,
263
+ videoPaused,
264
+ localStream,
265
+ localVideo,
266
+ localScreen,
267
+ remoteParents,
268
+ remoteRefs,
269
+ remoteScreens,
270
+ remoteScreenRefs,
271
+ remoteVideos
272
+ } = useCall();
273
+ const pickCamera = (deviceId) => {
274
+ cameraPickerOpen.value = false;
275
+ switchCamera(deviceId);
276
+ };
277
+ const translucent = {
278
+ background: "rgb(255 255 255 / 0.12)",
279
+ hoverBackground: "rgb(255 255 255 / 0.2)",
280
+ activeBackground: "rgb(255 255 255 / 0.28)",
281
+ borderColor: "transparent",
282
+ hoverBorderColor: "transparent",
283
+ activeBorderColor: "transparent",
284
+ color: "#ffffff",
285
+ hoverColor: "#ffffff",
286
+ activeColor: "#ffffff"
287
+ };
288
+ const lit = {
289
+ background: "#ffffff",
290
+ hoverBackground: "rgb(255 255 255 / 0.9)",
291
+ activeBackground: "rgb(255 255 255 / 0.8)",
292
+ borderColor: "#ffffff",
293
+ hoverBorderColor: "#ffffff",
294
+ activeBorderColor: "#ffffff",
295
+ color: "#151823",
296
+ hoverColor: "#151823",
297
+ activeColor: "#151823"
298
+ };
299
+ const callScheme = { root: { secondary: translucent, contrast: lit } };
300
+ const callButtonDt = { colorScheme: { light: callScheme, dark: callScheme } };
301
+ const footerButton = {
302
+ dt: callButtonDt,
303
+ text: false,
304
+ size: "large",
305
+ iconClass: "size-6"
306
+ };
307
+ const pipVideoRef = vue.ref(null);
308
+ const activeRemoteIndex = vue.ref(0);
309
+ const remoteVideoEntries = vue.computed(() => Object.entries(remoteVideos.value));
310
+ const hasRemoteVideos = vue.computed(() => remoteVideoEntries.value.length > 0);
311
+ const activeRemoteUserId = vue.computed(() => {
312
+ const entries = remoteVideoEntries.value;
313
+ if (entries.length === 0) return null;
314
+ return entries[activeRemoteIndex.value % entries.length][0];
315
+ });
316
+ const pipStream = vue.computed(() => {
317
+ var _a;
318
+ if (hasRemoteVideos.value) {
319
+ const id = activeRemoteUserId.value;
320
+ return id ? ((_a = remoteVideos.value[id]) == null ? void 0 : _a.stream) ?? null : null;
321
+ }
322
+ return localStream.value ?? null;
323
+ });
324
+ function cycleRemote() {
325
+ const count = remoteVideoEntries.value.length;
326
+ if (count === 0) return;
327
+ activeRemoteIndex.value = (activeRemoteIndex.value + 1) % count;
328
+ }
329
+ vue.watch(
330
+ [pipStream, () => callStore.isMinimized],
331
+ async () => {
332
+ await vue.nextTick();
333
+ const el = pipVideoRef.value;
334
+ if (!el) return;
335
+ const stream = pipStream.value;
336
+ if (stream && el.srcObject !== stream) {
337
+ el.srcObject = stream;
338
+ el.play().catch(() => {
339
+ });
340
+ } else if (!stream && el.srcObject) {
341
+ el.srcObject = null;
342
+ }
343
+ },
344
+ { immediate: true }
345
+ );
346
+ vue.onMounted(() => {
347
+ bodyRef.value = document.body;
348
+ });
349
+ const { width: windowWidth, height: windowHeight } = core.useWindowSize();
350
+ const { x, y, isDragging } = core.useDraggable(minimizedRef, {
351
+ initialValue: {
352
+ x: typeof window !== "undefined" ? window.innerWidth - PIP_WIDTH - PADDING : PADDING,
353
+ y: typeof window !== "undefined" ? window.innerHeight - PIP_HEIGHT - PADDING : PADDING
354
+ },
355
+ // غیرفعال کردن درگ در صورتی که کامپوننت مینیمایز نباشد
356
+ disabled: vue.computed(() => !callStore.isMinimized)
357
+ });
358
+ vue.watch(isDragging, (dragging) => {
359
+ if (!dragging && callStore.isMinimized) {
360
+ const maxX = windowWidth.value - PIP_WIDTH - PADDING;
361
+ const maxY = windowHeight.value - PIP_HEIGHT - PADDING;
362
+ dir.value === "rtl";
363
+ const targetX = x.value < windowWidth.value / 2 ? PADDING : maxX;
364
+ const targetY = y.value < windowHeight.value / 2 ? PADDING : maxY;
365
+ x.value = targetX;
366
+ y.value = targetY;
367
+ }
368
+ });
369
+ vue.watch(
370
+ () => callStore.isMinimized,
371
+ (isMinimized) => {
372
+ if (isMinimized) {
373
+ vue.nextTick(() => {
374
+ const isRtl = dir.value === "rtl";
375
+ x.value = isRtl ? PADDING : windowWidth.value - PIP_WIDTH - PADDING;
376
+ y.value = windowHeight.value - PIP_HEIGHT - PADDING;
377
+ });
378
+ }
379
+ },
380
+ { immediate: true }
381
+ );
382
+ const clampedStyle = vue.computed(() => {
383
+ if (!callStore.isMinimized) return {};
384
+ const maxX = windowWidth.value - PIP_WIDTH - PADDING;
385
+ const maxY = windowHeight.value - PIP_HEIGHT - PADDING;
386
+ const safeX = Math.max(PADDING, Math.min(x.value, maxX));
387
+ const safeY = Math.max(PADDING, Math.min(y.value, maxY));
388
+ return {
389
+ left: `${safeX}px`,
390
+ top: `${safeY}px`
391
+ };
392
+ });
393
+ return (_ctx, _cache) => {
394
+ const _component_BIcon = index._sfc_main$1;
395
+ return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
396
+ vue.unref(callStore).isActive && vue.unref(callStore).isMinimized ? (vue.openBlock(), vue.createElementBlock("div", {
397
+ key: 0,
398
+ ref_key: "minimizedRef",
399
+ ref: minimizedRef,
400
+ "data-testid": "call-pip",
401
+ style: vue.normalizeStyle(clampedStyle.value),
402
+ class: vue.normalizeClass(["vue-chat fixed w-70 h-40 bg-black-600 rounded-2xl shadow-floating z-9999 overflow-hidden border border-white/10 flex flex-col items-center justify-center cursor-move touch-none", [!vue.unref(isDragging) ? "transition-all duration-300 ease-out" : ""]])
403
+ }, [
404
+ vue.createElementVNode("video", {
405
+ ref_key: "pipVideoRef",
406
+ ref: pipVideoRef,
407
+ muted: "",
408
+ autoplay: "",
409
+ playsinline: "",
410
+ class: "pointer-events-none absolute inset-0 z-0 h-full w-full object-cover"
411
+ }, null, 512),
412
+ _cache[18] || (_cache[18] = vue.createElementVNode("div", { class: "pointer-events-none absolute inset-0 bg-gradient-to-br from-blue-500/5 via-purple-500/5 to-pink-500/5 opacity-0 transition-opacity duration-500 group-hover:opacity-100" }, null, -1)),
413
+ _cache[19] || (_cache[19] = vue.createElementVNode("div", { class: "pointer-events-none absolute inset-0 bg-gradient-to-t from-black/50 via-transparent to-black/20" }, null, -1)),
414
+ vue.createElementVNode("div", _hoisted_1, [
415
+ vue.createElementVNode("div", _hoisted_2, [
416
+ vue.createElementVNode("div", _hoisted_3, [
417
+ _cache[16] || (_cache[16] = vue.createElementVNode("div", { class: "relative" }, [
418
+ vue.createElementVNode("div", { class: "h-2.5 w-2.5 animate-pulse rounded-full bg-diamond-error" }),
419
+ vue.createElementVNode("div", { class: "absolute inset-0 h-2.5 w-2.5 animate-ping rounded-full bg-diamond-error/30" })
420
+ ], -1)),
421
+ vue.createElementVNode("span", _hoisted_4, vue.toDisplayString(vue.unref(t)("Call active")), 1),
422
+ _cache[17] || (_cache[17] = vue.createElementVNode("div", { class: "flex -space-x-1" }, [
423
+ vue.createElementVNode("div", {
424
+ class: "h-1.5 w-1.5 animate-pulse rounded-full bg-green-400",
425
+ style: { "animation-delay": "0s" }
426
+ }),
427
+ vue.createElementVNode("div", {
428
+ class: "h-1.5 w-1.5 animate-pulse rounded-full bg-green-400",
429
+ style: { "animation-delay": "0.2s" }
430
+ }),
431
+ vue.createElementVNode("div", {
432
+ class: "h-1.5 w-1.5 animate-pulse rounded-full bg-green-400",
433
+ style: { "animation-delay": "0.4s" }
434
+ })
435
+ ], -1))
436
+ ]),
437
+ vue.createVNode(index._sfc_main, {
438
+ icon: "PhPhoneX",
439
+ label: vue.unref(t)("chat.call.controls.endCall"),
440
+ severity: "danger",
441
+ text: false,
442
+ "icon-class": "size-4",
443
+ "data-testid": "call-pip-end",
444
+ onPointerdown: _cache[0] || (_cache[0] = vue.withModifiers(() => {
445
+ }, ["stop"])),
446
+ onClick: vue.withModifiers(vue.unref(endCall), ["stop"])
447
+ }, null, 8, ["label", "onClick"])
448
+ ]),
449
+ vue.createElementVNode("div", _hoisted_5, [
450
+ vue.createElementVNode("div", _hoisted_6, [
451
+ vue.createVNode(vue.unref(Button), {
452
+ label: String(vue.unref(participantCount)),
453
+ "aria-label": vue.unref(t)("chat.call.controls.nextParticipant"),
454
+ disabled: !hasRemoteVideos.value,
455
+ dt: callButtonDt,
456
+ severity: "secondary",
457
+ size: "small",
458
+ rounded: "",
459
+ onPointerdown: _cache[1] || (_cache[1] = vue.withModifiers(() => {
460
+ }, ["stop"])),
461
+ onClick: vue.withModifiers(cycleRemote, ["stop"])
462
+ }, {
463
+ icon: vue.withCtx(() => [
464
+ vue.createVNode(_component_BIcon, {
465
+ icon: "PhUsers",
466
+ class: "size-3"
467
+ })
468
+ ]),
469
+ _: 1
470
+ }, 8, ["label", "aria-label", "disabled"]),
471
+ !vue.unref(isAudioOn) || !vue.unref(isVideoOn) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_7, [
472
+ !vue.unref(isAudioOn) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_8, [
473
+ vue.createVNode(_component_BIcon, {
474
+ icon: "PhMicrophoneSlash",
475
+ class: "h-3 w-3 fill-white"
476
+ })
477
+ ])) : vue.createCommentVNode("", true),
478
+ !vue.unref(isVideoOn) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_9, [
479
+ vue.createVNode(_component_BIcon, {
480
+ icon: "PhVideoCameraSlash",
481
+ class: "h-3 w-3 fill-white"
482
+ })
483
+ ])) : vue.createCommentVNode("", true)
484
+ ])) : vue.createCommentVNode("", true)
485
+ ]),
486
+ vue.createVNode(index._sfc_main, {
487
+ icon: "PhResize",
488
+ label: vue.unref(t)("chat.call.controls.maximize"),
489
+ dt: callButtonDt,
490
+ text: false,
491
+ "icon-class": "size-4",
492
+ "data-testid": "call-maximize",
493
+ onPointerdown: _cache[2] || (_cache[2] = vue.withModifiers(() => {
494
+ }, ["stop"])),
495
+ onClick: _cache[3] || (_cache[3] = vue.withModifiers(($event) => vue.unref(callStore).maximize(), ["stop"]))
496
+ }, null, 8, ["label"])
497
+ ])
498
+ ])
499
+ ], 6)) : vue.createCommentVNode("", true),
500
+ vue.withDirectives(vue.createElementVNode("div", _hoisted_10, [
501
+ !vue.unref(callStore).isMinimized ? (vue.openBlock(), vue.createElementBlock("div", {
502
+ key: 0,
503
+ class: vue.normalizeClass(["flex h-16 items-center justify-between px-4 transition-all duration-300 sm:h-20", vue.unref(showControls) ? "opacity-100" : "opacity-0"]),
504
+ onMouseenter: _cache[4] || (_cache[4] = //@ts-ignore
505
+ (...args) => vue.unref(resetControlsTimeout) && vue.unref(resetControlsTimeout)(...args)),
506
+ onMousemove: _cache[5] || (_cache[5] = //@ts-ignore
507
+ (...args) => vue.unref(resetControlsTimeout) && vue.unref(resetControlsTimeout)(...args))
508
+ }, [
509
+ vue.createElementVNode("div", _hoisted_11, [
510
+ vue.createElementVNode("div", _hoisted_12, vue.toDisplayString(vue.unref(t)("Behayand Meeting")), 1),
511
+ vue.createElementVNode("div", _hoisted_13, [
512
+ vue.createVNode(_component_BIcon, {
513
+ icon: "PhUsers",
514
+ class: "h-4 w-4 fill-white"
515
+ }),
516
+ vue.createElementVNode("span", _hoisted_14, vue.toDisplayString(vue.unref(participantCount)) + " " + vue.toDisplayString(vue.unref(participantCount) > 1 ? vue.unref(t)("participants") : vue.unref(t)("participant")), 1)
517
+ ])
518
+ ]),
519
+ vue.createElementVNode("div", _hoisted_15, [
520
+ vue.createElementVNode("div", _hoisted_16, [
521
+ vue.createElementVNode("div", _hoisted_17, vue.toDisplayString((/* @__PURE__ */ new Date()).toLocaleTimeString(vue.unref(locale), {
522
+ hour: "2-digit",
523
+ minute: "2-digit",
524
+ hour12: true
525
+ })), 1)
526
+ ]),
527
+ vue.createVNode(index._sfc_main, vue.mergeProps({
528
+ icon: "PhCaretDown",
529
+ label: vue.unref(t)("chat.call.controls.minimize")
530
+ }, footerButton, {
531
+ "data-testid": "call-minimize",
532
+ onClick: vue.unref(callStore).minimize
533
+ }), null, 16, ["label", "onClick"])
534
+ ])
535
+ ], 34)) : vue.createCommentVNode("", true),
536
+ vue.createElementVNode("div", {
537
+ class: vue.normalizeClass(["relative grid w-full overflow-hidden", vue.unref(callStore).isMinimized ? "h-full p-0" : "h-full p-4"]),
538
+ onMousemove: _cache[10] || (_cache[10] = //@ts-ignore
539
+ (...args) => vue.unref(resetControlsTimeout) && vue.unref(resetControlsTimeout)(...args))
540
+ }, [
541
+ vue.withDirectives(vue.createElementVNode("div", _hoisted_18, [
542
+ vue.withDirectives(vue.createElementVNode("div", {
543
+ ref: (el) => vue.unref(remoteParents)[`self_screen`] = el,
544
+ class: "group relative flex aspect-video h-full w-full flex-col items-center justify-center overflow-hidden rounded-2xl border-2 border-chat-primary/0 bg-black-600 p-2"
545
+ }, [
546
+ vue.createElementVNode("video", {
547
+ ref_key: "localScreen",
548
+ ref: localScreen,
549
+ autoplay: "",
550
+ muted: "",
551
+ playsinline: "",
552
+ class: "absolute inset-0 z-0 h-full w-full object-cover"
553
+ }, null, 512),
554
+ vue.createElementVNode("div", _hoisted_19, [
555
+ vue.createElementVNode("div", _hoisted_20, vue.toDisplayString(vue.unref(t)("Your Presentation")), 1),
556
+ vue.createElementVNode("div", _hoisted_21, [
557
+ vue.createVNode(_component_BIcon, {
558
+ icon: "PhMonitor",
559
+ class: "h-4 w-4 fill-white"
560
+ })
561
+ ]),
562
+ vue.createVNode(index._sfc_main, {
563
+ icon: vue.unref(videoPaused)["self_screen"] ? "PhPlay" : "PhPause",
564
+ label: vue.unref(videoPaused)["self_screen"] ? vue.unref(t)("chat.call.controls.playVideo") : vue.unref(t)("chat.call.controls.pauseVideo"),
565
+ dt: callButtonDt,
566
+ text: false,
567
+ "icon-class": "size-4",
568
+ onClick: _cache[6] || (_cache[6] = ($event) => vue.unref(toggleVideoPause)("self_screen", vue.unref(localScreen)))
569
+ }, null, 8, ["icon", "label"]),
570
+ vue.createVNode(index._sfc_main, {
571
+ icon: vue.unref(isFullscreen) ? "PhCornersIn" : "PhFrameCorners",
572
+ label: vue.unref(isFullscreen) ? vue.unref(t)("chat.call.controls.exitFullscreen") : vue.unref(t)("chat.call.controls.fullscreen"),
573
+ dt: callButtonDt,
574
+ text: false,
575
+ "icon-class": "size-4",
576
+ onClick: _cache[7] || (_cache[7] = ($event) => vue.unref(toggleRemote)(`self_screen`))
577
+ }, null, 8, ["icon", "label"])
578
+ ])
579
+ ], 512), [
580
+ [vue.vShow, vue.unref(isScreenSharing)]
581
+ ]),
582
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(remoteVideos), (stream, remoteUserId) => {
583
+ return vue.openBlock(), vue.createElementBlock("div", {
584
+ key: `remote-${remoteUserId}`,
585
+ "data-testid": "call-remote-video",
586
+ ref_for: true,
587
+ ref: (el) => vue.unref(remoteParents)[`remote_video_${remoteUserId}`] = el,
588
+ class: "group relative flex aspect-video h-full w-full flex-col items-center justify-center overflow-hidden rounded-2xl border-2 border-chat-primary/0 bg-black-600 p-2"
589
+ }, [
590
+ vue.createElementVNode("video", {
591
+ ref_for: true,
592
+ ref: (el) => {
593
+ if (el) vue.unref(remoteRefs)[remoteUserId] = el;
594
+ },
595
+ autoplay: "",
596
+ playsinline: "",
597
+ class: "absolute inset-0 z-0 h-full w-full object-cover"
598
+ }, null, 512),
599
+ vue.createElementVNode("div", _hoisted_22, [
600
+ vue.createElementVNode("div", _hoisted_23, vue.toDisplayString(stream.name.slice(0, 15)), 1),
601
+ vue.createVNode(index._sfc_main, {
602
+ icon: vue.unref(videoPaused)[`remote_video_${remoteUserId}`] ? "PhPlay" : "PhPause",
603
+ label: vue.unref(videoPaused)[`remote_video_${remoteUserId}`] ? vue.unref(t)("chat.call.controls.playVideo") : vue.unref(t)("chat.call.controls.pauseVideo"),
604
+ dt: callButtonDt,
605
+ text: false,
606
+ "icon-class": "size-4",
607
+ onClick: ($event) => vue.unref(toggleVideoPause)(
608
+ `remote_video_${remoteUserId}`,
609
+ vue.unref(remoteRefs)[remoteUserId]
610
+ )
611
+ }, null, 8, ["icon", "label", "onClick"]),
612
+ vue.createVNode(index._sfc_main, {
613
+ icon: vue.unref(isFullscreen) ? "PhCornersIn" : "PhFrameCorners",
614
+ label: vue.unref(isFullscreen) ? vue.unref(t)("chat.call.controls.exitFullscreen") : vue.unref(t)("chat.call.controls.fullscreen"),
615
+ dt: callButtonDt,
616
+ text: false,
617
+ "icon-class": "size-4",
618
+ onClick: ($event) => vue.unref(toggleRemote)(`remote_video_${remoteUserId}`)
619
+ }, null, 8, ["icon", "label", "onClick"])
620
+ ])
621
+ ]);
622
+ }), 128)),
623
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(remoteScreens), (stream, remoteUserId) => {
624
+ return vue.openBlock(), vue.createElementBlock("div", {
625
+ key: `remote-screen-${remoteUserId}`,
626
+ "data-testid": "call-remote-screen",
627
+ ref_for: true,
628
+ ref: (el) => vue.unref(remoteParents)[`remote_screen_${remoteUserId}`] = el,
629
+ class: "group relative flex aspect-video h-full w-full flex-col items-center justify-center overflow-hidden rounded-2xl border-2 border-chat-primary/0 bg-black-600 p-2"
630
+ }, [
631
+ vue.createElementVNode("video", {
632
+ ref_for: true,
633
+ ref: (el) => {
634
+ if (el) vue.unref(remoteScreenRefs)[remoteUserId] = el;
635
+ },
636
+ autoplay: "",
637
+ muted: "",
638
+ playsinline: "",
639
+ class: "absolute inset-0 z-0 h-full w-full object-cover"
640
+ }, null, 512),
641
+ vue.createElementVNode("div", _hoisted_24, [
642
+ vue.createElementVNode("div", _hoisted_25, vue.toDisplayString(vue.unref(t)("Presentation of")) + " " + vue.toDisplayString(stream.name.slice(0, 15)), 1),
643
+ vue.createElementVNode("div", _hoisted_26, [
644
+ vue.createVNode(_component_BIcon, {
645
+ icon: "PhMonitor",
646
+ class: "h-4 w-4 fill-white"
647
+ })
648
+ ]),
649
+ vue.createVNode(index._sfc_main, {
650
+ icon: vue.unref(videoPaused)[`remote_screen_${remoteUserId}`] ? "PhPlay" : "PhPause",
651
+ label: vue.unref(videoPaused)[`remote_screen_${remoteUserId}`] ? vue.unref(t)("chat.call.controls.playVideo") : vue.unref(t)("chat.call.controls.pauseVideo"),
652
+ dt: callButtonDt,
653
+ text: false,
654
+ "icon-class": "size-4",
655
+ onClick: ($event) => vue.unref(toggleVideoPause)(
656
+ `remote_screen_${remoteUserId}`,
657
+ vue.unref(remoteScreenRefs)[remoteUserId] || null
658
+ )
659
+ }, null, 8, ["icon", "label", "onClick"]),
660
+ vue.createVNode(index._sfc_main, {
661
+ icon: vue.unref(isFullscreen) ? "PhCornersIn" : "PhFrameCorners",
662
+ label: vue.unref(isFullscreen) ? vue.unref(t)("chat.call.controls.exitFullscreen") : vue.unref(t)("chat.call.controls.fullscreen"),
663
+ dt: callButtonDt,
664
+ text: false,
665
+ "icon-class": "size-4",
666
+ onClick: ($event) => vue.unref(toggleRemote)(`remote_screen_${remoteUserId}`)
667
+ }, null, 8, ["icon", "label", "onClick"])
668
+ ])
669
+ ]);
670
+ }), 128))
671
+ ], 512), [
672
+ [vue.vShow, vue.unref(tileCount)]
673
+ ]),
674
+ vue.createElementVNode("div", {
675
+ class: vue.normalizeClass(["flex min-h-0", [vue.unref(tileCount) && "absolute inset-0 m-4"]])
676
+ }, [
677
+ !vue.unref(callStore).isMinimized ? (vue.openBlock(), vue.createElementBlock("div", {
678
+ key: 0,
679
+ class: vue.normalizeClass(["relative flex flex-col items-center justify-center overflow-hidden rounded-2xl border-2 border-chat-primary/0 bg-black-600 p-2", [
680
+ vue.unref(tileCount) ? "absolute z-10 h-[132px] w-[236px]" : "h-full w-full"
681
+ ]])
682
+ }, [
683
+ vue.createElementVNode("video", {
684
+ ref_key: "localVideo",
685
+ ref: localVideo,
686
+ "data-testid": "call-local-video",
687
+ autoplay: "",
688
+ muted: "",
689
+ playsinline: "",
690
+ class: "pointer-events-none absolute inset-0 z-0 h-full w-full object-cover"
691
+ }, null, 512),
692
+ _cache[20] || (_cache[20] = vue.createElementVNode("div", { class: "pointer-events-none absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent" }, null, -1)),
693
+ vue.createElementVNode("div", _hoisted_27, [
694
+ vue.createElementVNode("div", _hoisted_28, vue.toDisplayString(vue.unref(t)("You")), 1),
695
+ !vue.unref(isAudioOn) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_29, [
696
+ vue.createVNode(_component_BIcon, {
697
+ icon: "PhMicrophoneSlash",
698
+ class: "h-3 w-3 fill-white"
699
+ })
700
+ ])) : vue.createCommentVNode("", true),
701
+ vue.createVNode(index._sfc_main, {
702
+ icon: vue.unref(videoPaused)["self_cam"] ? "PhPlay" : "PhPause",
703
+ label: vue.unref(videoPaused)["self_cam"] ? vue.unref(t)("chat.call.controls.playVideo") : vue.unref(t)("chat.call.controls.pauseVideo"),
704
+ dt: callButtonDt,
705
+ text: false,
706
+ "icon-class": "size-4",
707
+ onClick: _cache[8] || (_cache[8] = ($event) => vue.unref(toggleVideoPause)("self_cam", vue.unref(localVideo)))
708
+ }, null, 8, ["icon", "label"]),
709
+ vue.createVNode(index._sfc_main, {
710
+ icon: vue.unref(isFullscreen) ? "PhCornersIn" : "PhFrameCorners",
711
+ label: vue.unref(isFullscreen) ? vue.unref(t)("chat.call.controls.exitFullscreen") : vue.unref(t)("chat.call.controls.fullscreen"),
712
+ dt: callButtonDt,
713
+ text: false,
714
+ "icon-class": "size-4",
715
+ onClick: _cache[9] || (_cache[9] = ($event) => vue.unref(toggleRemote)("self_cam"))
716
+ }, null, 8, ["icon", "label"])
717
+ ]),
718
+ !vue.unref(isVideoOn) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_30, [
719
+ vue.createElementVNode("div", _hoisted_31, [
720
+ vue.createElementVNode("div", _hoisted_32, [
721
+ vue.createElementVNode("span", _hoisted_33, vue.toDisplayString(vue.unref(t)("You")), 1)
722
+ ]),
723
+ vue.createElementVNode("p", _hoisted_34, vue.toDisplayString(vue.unref(t)("Camera is off")), 1)
724
+ ])
725
+ ])) : vue.createCommentVNode("", true)
726
+ ], 2)) : vue.createCommentVNode("", true)
727
+ ], 2)
728
+ ], 34),
729
+ !vue.unref(callStore).isMinimized ? (vue.openBlock(), vue.createElementBlock("div", {
730
+ key: 1,
731
+ class: vue.normalizeClass(["flex h-21 w-full items-center justify-center gap-x-1.5 border-t border-t-[#2C2C2E] bg-black-600 transition-all duration-300 sm:gap-x-3", vue.unref(showControls) ? "opacity-100" : "opacity-0"]),
732
+ onMouseenter: _cache[14] || (_cache[14] = //@ts-ignore
733
+ (...args) => vue.unref(resetControlsTimeout) && vue.unref(resetControlsTimeout)(...args)),
734
+ onMousemove: _cache[15] || (_cache[15] = //@ts-ignore
735
+ (...args) => vue.unref(resetControlsTimeout) && vue.unref(resetControlsTimeout)(...args))
736
+ }, [
737
+ vue.createVNode(index._sfc_main, vue.mergeProps({
738
+ icon: vue.unref(isAudioOn) ? "PhMicrophone" : "PhMicrophoneSlash",
739
+ label: vue.unref(isAudioOn) ? vue.unref(t)("chat.call.controls.mute") : vue.unref(t)("chat.call.controls.unmute"),
740
+ severity: vue.unref(isAudioOn) ? "secondary" : "contrast"
741
+ }, footerButton, {
742
+ "data-testid": "call-toggle-audio",
743
+ "data-active": vue.unref(isAudioOn),
744
+ onClick: vue.unref(toggleAudio)
745
+ }), null, 16, ["icon", "label", "severity", "data-active", "onClick"]),
746
+ vue.createVNode(index._sfc_main, vue.mergeProps({
747
+ icon: vue.unref(isVideoOn) ? "PhVideo" : "PhVideoCameraSlash",
748
+ label: vue.unref(isVideoOn) ? vue.unref(t)("chat.call.controls.cameraOff") : vue.unref(t)("chat.call.controls.cameraOn"),
749
+ severity: vue.unref(isVideoOn) ? "secondary" : "contrast"
750
+ }, footerButton, {
751
+ "data-testid": "call-toggle-video",
752
+ "data-active": vue.unref(isVideoOn),
753
+ onClick: vue.unref(toggleVideo)
754
+ }), null, 16, ["icon", "label", "severity", "data-active", "onClick"]),
755
+ vue.unref(cameras).length > 1 ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
756
+ vue.createVNode(index._sfc_main, vue.mergeProps({
757
+ icon: "PhCaretUp",
758
+ label: vue.unref(t)("chat.call.controls.chooseCamera")
759
+ }, footerButton, {
760
+ onClick: _cache[11] || (_cache[11] = ($event) => cameraPickerOpen.value = true)
761
+ }), null, 16, ["label"]),
762
+ vue.createVNode(index._sfc_main$2, {
763
+ visible: cameraPickerOpen.value,
764
+ "onUpdate:visible": _cache[13] || (_cache[13] = ($event) => cameraPickerOpen.value = $event),
765
+ header: vue.unref(t)("chat.call.controls.cameras"),
766
+ width: "24rem"
767
+ }, {
768
+ default: vue.withCtx(() => [
769
+ vue.createVNode(vue.unref(Listbox), {
770
+ options: vue.unref(cameras),
771
+ "option-value": "deviceId",
772
+ "option-label": (camera) => camera.label || `Camera ${camera.deviceId}`,
773
+ class: "w-full",
774
+ onChange: _cache[12] || (_cache[12] = (event) => pickCamera(event.value))
775
+ }, null, 8, ["options", "option-label"])
776
+ ]),
777
+ _: 1
778
+ }, 8, ["visible", "header"])
779
+ ], 64)) : vue.createCommentVNode("", true),
780
+ vue.createVNode(index._sfc_main, vue.mergeProps({
781
+ icon: "PhMonitorArrowUp",
782
+ label: vue.unref(isScreenSharing) ? vue.unref(t)("chat.call.controls.stopSharing") : vue.unref(t)("chat.call.controls.shareScreen"),
783
+ severity: vue.unref(isScreenSharing) ? "contrast" : "secondary"
784
+ }, footerButton, {
785
+ "data-testid": "call-toggle-screen",
786
+ "data-active": vue.unref(isScreenSharing),
787
+ onClick: vue.unref(toggleScreenShare)
788
+ }), null, 16, ["label", "severity", "data-active", "onClick"]),
789
+ vue.createVNode(index._sfc_main, vue.mergeProps({
790
+ icon: vue.unref(isFullscreen) ? "PhCornersIn" : "PhFrameCorners",
791
+ label: vue.unref(isFullscreen) ? vue.unref(t)("chat.call.controls.exitFullscreen") : vue.unref(t)("chat.call.controls.fullscreen")
792
+ }, footerButton, { onClick: vue.unref(toggleFullscreen) }), null, 16, ["icon", "label", "onClick"]),
793
+ vue.unref(isFlashlightSupported) ? (vue.openBlock(), vue.createBlock(index._sfc_main, vue.mergeProps({
794
+ key: 1,
795
+ icon: vue.unref(isFlashlightOn) ? "PhLightning" : "PhLightningSlash",
796
+ label: vue.unref(t)("chat.call.controls.flashlight"),
797
+ severity: vue.unref(isFlashlightOn) ? "contrast" : "secondary"
798
+ }, footerButton, { onClick: vue.unref(toggleFlashlight) }), null, 16, ["icon", "label", "severity", "onClick"])) : vue.createCommentVNode("", true),
799
+ vue.createVNode(index._sfc_main, {
800
+ icon: "PhPhoneX",
801
+ label: vue.unref(t)("chat.call.controls.endCall"),
802
+ severity: "danger",
803
+ text: false,
804
+ size: "large",
805
+ "icon-class": "size-6",
806
+ "data-testid": "call-end",
807
+ onClick: vue.unref(endCall)
808
+ }, null, 8, ["label", "onClick"])
809
+ ], 34)) : vue.createCommentVNode("", true)
810
+ ], 512), [
811
+ [vue.vShow, vue.unref(callStore).isActive && !vue.unref(callStore).isMinimized]
812
+ ])
813
+ ], 64);
814
+ };
815
+ }
816
+ });
817
+ exports.default = _sfc_main;
818
+ //# sourceMappingURL=Call-CTIujxDi.cjs.map