@bcc-code/vue-bcc-chat-ui 3.23.0 → 3.24.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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@bcc-code/vue-bcc-chat-ui",
3
3
  "author": "bcc-code",
4
4
  "license": "Apache-2.0",
5
- "version": "3.23.0",
5
+ "version": "3.24.0",
6
6
  "type": "module",
7
7
  "private": false,
8
8
  "files": [
@@ -33,18 +33,26 @@
33
33
  "vue": "^3.0.0"
34
34
  },
35
35
  "devDependencies": {
36
+ "@tailwindcss/aspect-ratio": "^0.4.2",
37
+ "@tailwindcss/forms": "^0.5.8",
38
+ "@tailwindcss/typography": "^0.5.15",
36
39
  "@types/dompurify": "^3.0.5",
37
40
  "@types/markdown-it": "^14.1.2",
38
41
  "@types/node": "^20.14.9",
39
42
  "@vitejs/plugin-vue": "^5.1.3",
43
+ "autoprefixer": "^10.4.20",
40
44
  "path": "^0.12.7",
45
+ "postcss": "^8.4.44",
41
46
  "sass": "^1.77.8",
47
+ "tailwindcss": "^3.4.10",
42
48
  "typescript": "^5.5.4",
43
49
  "vite": "^5.4.2",
44
50
  "vite-plugin-dts": "^4.1.0",
45
51
  "vue": "^3.4.38"
46
52
  },
47
53
  "dependencies": {
54
+ "@bcc-code/design-library-vue": "^2.6.3",
55
+ "@bcc-code/icons-vue": "^1.4.0",
48
56
  "@cometchat/chat-sdk-javascript": "4.0.10",
49
57
  "@cometchat/chat-uikit-vue": "4.3.17",
50
58
  "@cometchat/uikit-elements": "4.3.17",
@@ -8,24 +8,16 @@ import {
8
8
  provide,
9
9
  ref,
10
10
  watch,
11
- watchEffect,
12
11
  } from "vue";
13
12
  import chat from "../chat";
14
13
  import { connect, disconnect } from "../chat/connection";
15
14
  import { loggedIn } from "../chat/login";
16
- import { CometChatMessages } from "../chat/cometChatPatches";
17
15
  import { Group } from "@cometchat/chat-sdk-javascript";
18
16
  import { watchAndApplyStyle } from "../chat/styleFix";
19
- import {
20
- getMessageComposerConfiguration,
21
- getMessageListConfiguration,
22
- getThreadedMessagesConfiguration
23
- } from "../chat/uiKit";
24
17
  import { ChatInstance } from "../chat/types";
25
18
  import { CometChatMessageEvents, MessageStatus } from "@cometchat/uikit-resources";
26
- import BccAttachmentBox from "./BccAttachmentBox.vue";
27
- import BccChatSendButton from "./BccChatSendButton.vue";
28
-
19
+ import BccChatMessages from "./BccChatMessages.vue";
20
+ import BccScheduledMessages from "./BccScheduledMessages.vue";
29
21
  const props = defineProps({
30
22
  chatUid: { type: String, required: true },
31
23
  senderDisplayName: { type: String, required: false },
@@ -39,13 +31,11 @@ const chatGroup = ref<Group>();
39
31
  const chatInstance: Ref<ChatInstance> = ref({
40
32
  componentId: componentId,
41
33
  replyToMessage: null,
42
- captionedAttachment: null
34
+ captionedAttachment: null,
35
+ showScheduledMessagesChat: false,
36
+ showAlert: false
43
37
  });
44
38
 
45
- const messageComposerConfiguration = getMessageComposerConfiguration(chatInstance);
46
- const messageListConfiguration = getMessageListConfiguration(chatInstance, chatGroup);
47
- const threadedMessagesConfiguration = getThreadedMessagesConfiguration(chatGroup);
48
- threadedMessagesConfiguration.messageComposerConfiguration = messageComposerConfiguration.value;
49
39
  provide("chatInstance", chatInstance);
50
40
 
51
41
  const onMessageSend = CometChatMessageEvents.ccMessageSent.subscribe(({ message, status }) => {
@@ -66,33 +56,6 @@ const onMessageSend = CometChatMessageEvents.ccMessageSent.subscribe(({ message,
66
56
  }
67
57
  });
68
58
 
69
- watchEffect(() => {
70
- if (chatInstance.value.captionedAttachment) {
71
- messageComposerConfiguration.value.headerView = {
72
- componentName: BccAttachmentBox,
73
- props: {
74
- captionedAttachment: chatInstance.value.captionedAttachment
75
- }
76
- }
77
-
78
- messageComposerConfiguration.value.sendButtonView = {
79
- componentName: BccChatSendButton
80
- };
81
- } else {
82
- messageComposerConfiguration.value.sendButtonView = undefined;
83
- if (chatInstance.value.replyToMessage) {
84
- messageComposerConfiguration.value.headerView = {
85
- componentName: "bcc-reply-box",
86
- props: {
87
- replyToMessage: chatInstance.value.replyToMessage,
88
- }
89
- };
90
- } else {
91
- messageComposerConfiguration.value.headerView = undefined;
92
- }
93
- }
94
- });
95
-
96
59
  watch([loggedIn, () => props.chatUid, chat.initialized], async ([_loggedIn, _chatUid, _initialized]) => {
97
60
  if (_loggedIn && _chatUid && _initialized) {
98
61
  chatGroup.value = (await chat.getGroup(props.chatUid)) ?? undefined;
@@ -118,6 +81,7 @@ onBeforeMount(() => {
118
81
  connect(componentId.value);
119
82
  });
120
83
 
84
+
121
85
  onMounted(() => {
122
86
  watchAndApplyStyle(".bcc-chat-message-list-wrapper", [
123
87
  {
@@ -147,16 +111,11 @@ onUnmounted(async () => {
147
111
  await disconnect(componentId.value);
148
112
  });
149
113
 
150
- function isChannel(): boolean {
151
- return (chatGroup.value?.getMetadata() as any)?.isChannel;
152
- }
153
-
154
- function isParticipant(): boolean {
155
- //if not part of the group return true anyway since getScope dosen't exist when not in the group
156
- if (!chatGroup.value?.getHasJoined()) {
157
- return true
158
- }
159
- return chatGroup.value?.getScope() == "participant";
114
+ function closeScheduledMessage() {
115
+ chatInstance.value.captionedAttachment = null
116
+ chatInstance.value.replyToMessage = null
117
+ chatInstance.value.scheduledMessageChat = undefined
118
+ chatInstance.value.showScheduledMessagesChat = false;
160
119
  }
161
120
 
162
121
  </script>
@@ -171,19 +130,11 @@ function isParticipant(): boolean {
171
130
  <div>Connecting: {{chat.connecting.value}}</div>
172
131
  <div>CometChat: {{cometChatStatus}} <button @click="getCometChatStatus()">[refresh]</button></div>
173
132
  </div> -->
174
- <div v-if="chatGroup" class="bcc-chat-message-list">
175
- <CometChatMessages :hideMessageHeader="true" :disableSoundForMessages="true"
176
- :messageComposerConfiguration="messageComposerConfiguration"
177
- :messageListConfiguration="messageListConfiguration"
178
- :threadedMessagesConfiguration="threadedMessagesConfiguration"
179
- :hideMessageComposer="isParticipant() && isChannel()" :hideDetails="true" :group="chatGroup" />
180
-
181
- <div v-if="chat.onlineStatus.value === 'offline' || !chat.connected.value"
182
- class="bcc-chat-message-composer-offline">
183
- <span v-if="chat.onlineStatus.value === 'offline'">Waiting for network...</span>
184
- <span v-else>Connecting...</span>
185
- </div>
186
- </div>
133
+ <BccChatMessages v-if="chatGroup && !chatInstance.showScheduledMessagesChat" :chatGroup="chatGroup"
134
+ :chatUid="props.chatUid"></BccChatMessages>
135
+ <BccScheduledMessages v-else-if="chatGroup && chatInstance.showScheduledMessagesChat"
136
+ class="bcc-scheduled-message-list" :chatGroup="chatInstance.scheduledMessageChat!"
137
+ :originalChatUid="props.chatUid" @close="closeScheduledMessage()"></BccScheduledMessages>
187
138
  <div v-else-if="!chat.connected.value" class="bcc-chat-message-list-offline">
188
139
  <span>Connecting...</span>
189
140
  </div>
@@ -198,18 +149,68 @@ function isParticipant(): boolean {
198
149
 
199
150
  <style lang="scss">
200
151
  body {
201
- background: #fff;
202
- color: #000;
152
+ background: #fff;
153
+ color: #000;
203
154
 
204
- @media (prefers-color-scheme: dark) {
205
- background: #000;
206
- color: #fff;
207
- }
155
+ @media (prefers-color-scheme: dark) {
156
+ background: #000;
157
+ color: #fff;
158
+ }
159
+ }
160
+
161
+ .modal {
162
+ background-color: hsl(230, 25%, 15%);
163
+ color: white;
164
+
165
+ .bcc-modal-content {
166
+ display: flex;
167
+ justify-content: space-between;
168
+ width: 100%;
169
+
170
+ .input {
171
+ background-color: #758abc;
172
+ border-radius: 5px;
173
+ color: white;
174
+ height: 40px;
175
+ padding: 5px;
176
+ width: 45%;
177
+ }
178
+
179
+ .at {
180
+ width: 10%;
181
+ text-align: center;
182
+ margin-top: 7px;
183
+ }
184
+ }
185
+
186
+ .bcc-modal-footer {
187
+ background-color: hsl(230, 25%, 15%);
188
+
189
+ .bcc-modal-actions {
190
+ background-color: hsl(230, 25%, 15%);
191
+ display: flex;
192
+ width: 100%;
193
+ justify-content: space-between;
194
+
195
+ .bcc-modal-secondary-action,
196
+ .bcc-modal-primary-action {
197
+ width: 100%;
198
+ background-color: hsl(230, 25%, 15%);
199
+
200
+ button {
201
+ background-color: #2fb5e9d1 !important;
202
+ width: 100%;
203
+ border-radius: 5px;
204
+ margin-top: -10px;
205
+ }
206
+ }
207
+ }
208
+ }
208
209
  }
209
210
 
210
211
  .bcc-chat-message-list-wrapper {
211
- position: relative;
212
- height: 100%;
212
+ position: relative;
213
+ height: 100%;
213
214
  }
214
215
 
215
216
  /*
@@ -224,148 +225,148 @@ accent900: text in avatar
224
225
  */
225
226
 
226
227
  .bcc-chat-message-list {
227
- height: 100%;
228
- --cc__primary: #cfeac8;
229
- --cc__background: #f3faf7;
230
- --cc__secondary: white;
231
- --cc__accent: #004e48;
232
- --cc__accent50: rgba(62, 142, 117, 0.04);
233
- --cc__accent100: #ffffff;
234
- --cc__accent200: rgba(62, 142, 117, 0.15);
235
- --cc__accent300: rgba(62, 142, 117, 0.24);
236
- --cc__accent400: rgba(62, 142, 117, 0.33);
237
- --cc__accent500: rgba(62, 142, 117, 0.46);
238
- --cc__accent600: #004e48;
239
- --cc__accent700: #254a40;
240
- --cc__accent800: rgba(62, 142, 117, 0.82);
241
- --cc__accent900: #f3faf7;
242
- --cc__text-color: #000;
243
- --cc__link-color: #57639e;
244
-
245
- @media (prefers-color-scheme: dark) {
246
- --cc__primary: #57639e;
247
- --cc__background: hsl(230, 25%, 15%);
248
- --cc__secondary: #111827;
249
- --cc__accent: #6274ae;
250
- --cc__accent50: rgba(98, 116, 174, 0.24);
251
- --cc__accent100: linear-gradient(45deg, #05070b 0%, #0c111c 100%);
252
- --cc__accent200: rgba(98, 116, 174, 0.35);
253
- --cc__accent300: rgba(98, 116, 174, 0.44);
254
- --cc__accent400: rgba(98, 116, 174, 0.53);
255
- --cc__accent500: rgba(98, 116, 174, 0.66);
256
- --cc__accent600: #758abc;
257
- --cc__accent700: #6274ae;
258
- --cc__accent800: rgba(98, 116, 174, 0.92);
228
+ height: 100%;
229
+ --cc__primary: #cfeac8;
230
+ --cc__background: #f3faf7;
231
+ --cc__secondary: white;
232
+ --cc__accent: #004e48;
233
+ --cc__accent50: rgba(62, 142, 117, 0.04);
234
+ --cc__accent100: #ffffff;
235
+ --cc__accent200: rgba(62, 142, 117, 0.15);
236
+ --cc__accent300: rgba(62, 142, 117, 0.24);
237
+ --cc__accent400: rgba(62, 142, 117, 0.33);
238
+ --cc__accent500: rgba(62, 142, 117, 0.46);
239
+ --cc__accent600: #004e48;
240
+ --cc__accent700: #254a40;
241
+ --cc__accent800: rgba(62, 142, 117, 0.82);
259
242
  --cc__accent900: #f3faf7;
260
- --cc__text-color: #fff;
261
- --cc__link-color: #cfeac8;
262
- }
243
+ --cc__text-color: #000;
244
+ --cc__link-color: #57639e;
245
+
246
+ @media (prefers-color-scheme: dark) {
247
+ --cc__primary: #57639e;
248
+ --cc__background: hsl(230, 25%, 15%);
249
+ --cc__secondary: #111827;
250
+ --cc__accent: #6274ae;
251
+ --cc__accent50: rgba(98, 116, 174, 0.24);
252
+ --cc__accent100: linear-gradient(45deg, #05070b 0%, #0c111c 100%);
253
+ --cc__accent200: rgba(98, 116, 174, 0.35);
254
+ --cc__accent300: rgba(98, 116, 174, 0.44);
255
+ --cc__accent400: rgba(98, 116, 174, 0.53);
256
+ --cc__accent500: rgba(98, 116, 174, 0.66);
257
+ --cc__accent600: #758abc;
258
+ --cc__accent700: #6274ae;
259
+ --cc__accent800: rgba(98, 116, 174, 0.92);
260
+ --cc__accent900: #f3faf7;
261
+ --cc__text-color: #fff;
262
+ --cc__link-color: #cfeac8;
263
+ }
263
264
 
264
- /* 1. Wrapper for Messages component */
265
- .cc-messages-wrapper {
265
+ /* 1. Wrapper for Messages component */
266
+ .cc-messages-wrapper {
266
267
 
267
- /* 1.1 Messages component */
268
- .cc-messages-wrapper__messages {
268
+ /* 1.1 Messages component */
269
+ .cc-messages-wrapper__messages {
269
270
 
270
- /* 1.1.1 Wrapper for Messages List */
271
- .cc-messages-wrapper__messages-list {
272
- height: 100%;
273
- }
271
+ /* 1.1.1 Wrapper for Messages List */
272
+ .cc-messages-wrapper__messages-list {
273
+ height: 100%;
274
+ }
274
275
 
275
- /* 1.1.2 Wrapper for Messages Composer */
276
- .cc-messagecomposer-wrapper {
277
- //padding: 0; //Use to remove side padding on composer
278
- }
276
+ /* 1.1.2 Wrapper for Messages Composer */
277
+ .cc-messagecomposer-wrapper {
278
+ //padding: 0; //Use to remove side padding on composer
279
+ }
279
280
 
280
- /* 1.1.3 Wrapper for Messages Composer Header View */
281
- .cc-messagecomposer-wrapper__headerview {
282
- max-height: 100%;
283
- margin-bottom: 5px;
284
- }
285
- }
281
+ /* 1.1.3 Wrapper for Messages Composer Header View */
282
+ .cc-messagecomposer-wrapper__headerview {
283
+ max-height: 100%;
284
+ margin-bottom: 5px;
285
+ }
286
+ }
286
287
 
287
- .cc-messagebubble-wrapper__content {
288
- max-width: 100%;
289
- }
288
+ .cc-messagebubble-wrapper__content {
289
+ max-width: 100%;
290
+ }
290
291
 
291
- .cc-messagebubble-wrapper__content > div > .bcc-message-wrapper.has-text.has-image + div > div > div:not([class]) {
292
- justify-content: flex-end !important;
293
- padding: 0px 8px 8px !important;
294
- margin-top: -5px !important;
295
- height: unset !important;
296
- border-radius: unset !important;
297
- line-height: unset !important;
298
- position: unset !important;
299
- margin-right: unset !important;
300
- background: unset !important;
292
+ .cc-messagebubble-wrapper__content>div>.bcc-message-wrapper.has-text.has-image+div>div>div:not([class]) {
293
+ justify-content: flex-end !important;
294
+ padding: 0px 8px 8px !important;
295
+ margin-top: -5px !important;
296
+ height: unset !important;
297
+ border-radius: unset !important;
298
+ line-height: unset !important;
299
+ position: unset !important;
300
+ margin-right: unset !important;
301
+ background: unset !important;
302
+ }
301
303
  }
302
- }
303
304
 
304
- .cc-messagebubble-wrapper__container {
305
- max-width: 80%;
306
- }
305
+ .cc-messagebubble-wrapper__container {
306
+ max-width: 80%;
307
+ }
307
308
 
308
- .cc-messagebubble-wrapper__messageoptions {
309
- border-radius: 8px;
309
+ .cc-messagebubble-wrapper__messageoptions {
310
+ border-radius: 8px;
310
311
 
311
- .cc-context-menu__top-menu {
312
- border: 1px var(--cc__secondary) solid !important;
312
+ .cc-context-menu__top-menu {
313
+ border: 1px var(--cc__secondary) solid !important;
314
+ }
313
315
  }
314
- }
315
316
 
316
- /* 2. Message for Messages Composer when offline */
317
- .bcc-chat-message-composer-offline {
318
- position: relative;
319
- top: -96px;
320
- height: 96px;
321
- width: 100%;
322
- backdrop-filter: blur(4px);
323
- color: var(--cc__text-color);
324
- font: 700 1rem sans-serif;
325
-
326
- /* 2.1 Text of Messages Composer offline view */
327
- span {
328
- width: 100%;
329
- height: 100%;
330
- display: flex;
331
- justify-content: center;
332
- align-items: center;
333
- border-radius: 8px 8px 0 0;
317
+ /* 2. Message for Messages Composer when offline */
318
+ .bcc-chat-message-composer-offline {
319
+ position: relative;
320
+ top: -96px;
321
+ height: 96px;
322
+ width: 100%;
323
+ backdrop-filter: blur(4px);
324
+ color: var(--cc__text-color);
325
+ font: 700 1rem sans-serif;
326
+
327
+ /* 2.1 Text of Messages Composer offline view */
328
+ span {
329
+ width: 100%;
330
+ height: 100%;
331
+ display: flex;
332
+ justify-content: center;
333
+ align-items: center;
334
+ border-radius: 8px 8px 0 0;
335
+ }
334
336
  }
335
- }
336
337
  }
337
338
 
338
339
  .bcc-chat-message-list-offline {
339
- position: absolute;
340
- top: 0;
341
- bottom: 0;
342
- left: 0;
343
- right: 0;
344
- display: flex;
345
- justify-content: center;
346
- align-items: center;
347
- font: 700 22px sans-serif;
348
- color: #bcbcbc;
340
+ position: absolute;
341
+ top: 0;
342
+ bottom: 0;
343
+ left: 0;
344
+ right: 0;
345
+ display: flex;
346
+ justify-content: center;
347
+ align-items: center;
348
+ font: 700 22px sans-serif;
349
+ color: #bcbcbc;
349
350
  }
350
351
 
351
352
  .cc-messagecomposer__emojikeyboard {
352
- display: none;
353
+ display: none;
353
354
  }
354
355
 
355
356
  // Hide emoji keyboard
356
357
  .cc-messagecomposer__emojikeyboard {
357
- display: none;
358
+ display: none;
358
359
  }
359
360
 
360
361
  .cc-threadedmessages-wrapper__bubbleview::-webkit-scrollbar,
361
362
  .cc__message-list::-webkit-scrollbar {
362
- background: transparent;
363
- width: 8px;
363
+ background: transparent;
364
+ width: 8px;
364
365
  }
365
366
 
366
367
  .cc-threadedmessages-wrapper__bubbleview::-webkit-scrollbar-thumb,
367
368
  .cc__message-list::-webkit-scrollbar-thumb {
368
- background: rgb(232, 229, 229);
369
- border-radius: 8px;
369
+ background: rgb(232, 229, 229);
370
+ border-radius: 8px;
370
371
  }
371
- </style>
372
+ </style>
@@ -0,0 +1,182 @@
1
+ <script setup lang="ts">
2
+ import chat from "../chat";
3
+ import { Group } from "@cometchat/chat-sdk-javascript";
4
+ import { inject, onMounted, onUnmounted, Ref, ref, watch, watchEffect } from 'vue';
5
+ import { sendScheduledMessage } from '../chat/scheduledMessage';
6
+ import { ChatInstance } from '../chat/types';
7
+ import BccAttachmentBox from "./BccAttachmentBox.vue";
8
+ import BccChatSendButton from "./BccChatSendButton.vue";
9
+ import { getMessageComposerConfiguration, getMessageListConfiguration, getThreadedMessagesConfiguration } from "../chat/uiKit";
10
+ import { CometChatMessages } from "../chat/cometChatPatches";
11
+ import BccScheduledMessageModal from "./BccScheduledMessageModal.vue";
12
+ import { BccAlert } from "@bcc-code/design-library-vue";
13
+ import { localize } from "@cometchat/uikit-resources";
14
+ import { MessageComposerConfiguration } from "@cometchat/uikit-shared";
15
+
16
+ const props = defineProps({
17
+ chatUid: { type: String, required: true },
18
+ chatGroup: { type: Group, required: true }
19
+ })
20
+
21
+ const chatGroup = ref<Group>();
22
+
23
+ const chatInstance = inject<Ref<ChatInstance>>("chatInstance");
24
+ const messageComposerConfiguration = getMessageComposerConfiguration(chatInstance);
25
+ const messageListConfiguration = getMessageListConfiguration(chatInstance, chatGroup);
26
+ const threadedMessagesConfiguration = getThreadedMessagesConfiguration(chatGroup);
27
+ threadedMessagesConfiguration.messageComposerConfiguration = getThreadedMessageComposerConfig();
28
+
29
+ onMounted(() => {
30
+ chatGroup.value = props.chatGroup
31
+ attachEventlisteners();
32
+ })
33
+
34
+ onUnmounted(() => {
35
+ detachEventlisteners();
36
+ })
37
+
38
+ watch(() => props.chatGroup,
39
+ (group) => {
40
+ chatGroup.value = group;
41
+ }
42
+ );
43
+
44
+ watchEffect(() => {
45
+ if (chatInstance && chatInstance.value.captionedAttachment) {
46
+ messageComposerConfiguration.value.headerView = {
47
+ componentName: BccAttachmentBox,
48
+ props: {
49
+ captionedAttachment: chatInstance.value.captionedAttachment
50
+ }
51
+ }
52
+
53
+ messageComposerConfiguration.value.sendButtonView = {
54
+ componentName: BccChatSendButton,
55
+ props: {
56
+ chatUid: props.chatUid
57
+ }
58
+ };
59
+ detachEventlisteners()
60
+ attachEventlisteners()
61
+ } else {
62
+ if (chatInstance && chatInstance.value.replyToMessage) {
63
+ messageComposerConfiguration.value.headerView = {
64
+ componentName: "bcc-reply-box",
65
+ props: {
66
+ replyToMessage: chatInstance.value.replyToMessage,
67
+ }
68
+ };
69
+ } else {
70
+ messageComposerConfiguration.value.headerView = undefined;
71
+ }
72
+ messageComposerConfiguration.value.sendButtonView = undefined;
73
+ }
74
+ });
75
+
76
+ function getThreadedMessageComposerConfig(): MessageComposerConfiguration {
77
+ let composerConfig = {...messageComposerConfiguration.value}
78
+ composerConfig.auxilaryButtonView = undefined
79
+ return composerConfig;
80
+ }
81
+
82
+ function attachEventlisteners() {
83
+ const interval = setInterval(() => {
84
+ const btns = document.querySelectorAll('.cc-messagecomposer-wrapper__sendbutton');
85
+ const sendButton = btns[btns.length - 1]
86
+
87
+ if (sendButton) {
88
+ sendButton.addEventListener("pointerdown", onMouseDown);
89
+ sendButton.addEventListener("pointerup", clearTimer);
90
+ sendButton.addEventListener("mouseleave", clearTimer);
91
+
92
+ clearInterval(interval)
93
+ }
94
+ }, 500);
95
+ }
96
+
97
+ function detachEventlisteners() {
98
+ const btns = document.querySelectorAll('.cc-messagecomposer-wrapper__sendbutton');
99
+ const sendButton = btns[btns.length - 1]
100
+
101
+ if (sendButton) {
102
+ sendButton.removeEventListener("pointerdown", onMouseDown);
103
+ sendButton.removeEventListener("pointerup", clearTimer);
104
+ sendButton.removeEventListener("mouseleave", clearTimer);
105
+ }
106
+ }
107
+
108
+ function isChannel(): boolean {
109
+ return (props.chatGroup.getMetadata() as any)?.isChannel;
110
+ }
111
+
112
+ function isParticipant(): boolean {
113
+ //if not part of the group return true anyway since getScope dosen't exist when not in the group
114
+ if (!chatGroup.value?.getHasJoined()) {
115
+ return true
116
+ }
117
+ return chatGroup.value?.getScope() == "participant";
118
+ }
119
+
120
+ function closeModal() {
121
+ showModal.value = false;
122
+ }
123
+
124
+ const showAlert = ref<boolean>(false)
125
+
126
+ function scheduleMessage(scheduleDate?: string) {
127
+ if (scheduleDate && chatInstance) {
128
+ sendScheduledMessage(scheduleDate, props.chatUid, chatInstance).then((msgSuccessful) => {
129
+ if (!msgSuccessful) {
130
+ showModal.value = false
131
+ showAlert.value = true
132
+ setTimeout(() => showAlert.value = false, 3000)
133
+ }
134
+ })
135
+ }
136
+ }
137
+ const showModal = ref(false);
138
+ let timerId: string | number | NodeJS.Timeout | null | undefined;
139
+ const duration = 500;
140
+
141
+ const openPopup = () => {
142
+ showModal.value = true;
143
+ }
144
+
145
+ const onMouseDown = () => {
146
+ const userInput = document.querySelector(".messageinput-input")?.innerText;
147
+
148
+ if (userInput) {
149
+ timerId = setTimeout(() => {
150
+ openPopup();
151
+ }, duration)
152
+ }
153
+ }
154
+
155
+ const clearTimer = () => {
156
+ if (timerId !== null) {
157
+ clearTimeout(timerId);
158
+ timerId = null;
159
+ }
160
+ }
161
+
162
+ </script>
163
+
164
+ <template>
165
+ <div class="bcc-chat-message-list">
166
+ <CometChatMessages :hideMessageHeader="true" :disableSoundForMessages="true"
167
+ :messageComposerConfiguration="messageComposerConfiguration"
168
+ :messageListConfiguration="messageListConfiguration"
169
+ :threadedMessagesConfiguration="threadedMessagesConfiguration"
170
+ :hideMessageComposer="isParticipant() && isChannel()" :hideDetails="true" :group="chatGroup" />
171
+ <div v-if="chat.onlineStatus.value === 'offline' || !chat.connected.value"
172
+ class="bcc-chat-message-composer-offline">
173
+ <span v-if="chat.onlineStatus.value === 'offline'">Waiting for network...</span>
174
+ <span v-else>Connecting...</span>
175
+ </div>
176
+ <BccScheduledMessageModal v-if="showModal" @close="closeModal()" @send="scheduleMessage">
177
+ </BccScheduledMessageModal>
178
+ <BccAlert class="absolute top-0 w-[97%] mx-2 mt-1" icon closeButton context="danger" :open="showAlert" @close="showAlert = false">
179
+ {{ localize("ERROR_SENDING_SCHEDULED_MESSAGE") }}
180
+ </BccAlert>
181
+ </div>
182
+ </template>