@bcc-code/vue-bcc-chat-ui 3.11.0 → 3.13.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/dist/App.vue.d.ts +2 -0
  2. package/dist/chat/bccuiExtension.d.ts +0 -1
  3. package/dist/chat/captionedAttachment.d.ts +2 -0
  4. package/dist/chat/captionedAttachmentExtension.d.ts +7 -0
  5. package/dist/chat/cometChatPatches.d.ts +0 -1
  6. package/dist/chat/data.d.ts +1 -2
  7. package/dist/chat/environment.d.ts +0 -1
  8. package/dist/chat/index.d.ts +206 -5
  9. package/dist/chat/login.d.ts +2 -2
  10. package/dist/chat/replyExtension.d.ts +0 -1
  11. package/dist/chat/replyStyle.d.ts +0 -1
  12. package/dist/chat/theme.d.ts +203 -2
  13. package/dist/chat/translations.d.ts +0 -1
  14. package/dist/chat/types.d.ts +5 -1
  15. package/dist/chat/uiKit.d.ts +4 -4
  16. package/dist/components/BccAttachmentBox.vue.d.ts +29 -0
  17. package/dist/components/BccAttachmentPreview.vue.d.ts +23 -0
  18. package/dist/components/BccChatMessageBubble.vue.d.ts +81 -19
  19. package/dist/components/BccChatMessageList.vue.d.ts +3 -3
  20. package/dist/components/BccChatSendButton.vue.d.ts +51 -0
  21. package/dist/components/BccCometChatFullScreenViewer.vue.d.ts +5 -5
  22. package/dist/components/BccFileBubble.vue.d.ts +4 -4
  23. package/dist/components/BccImageBubble.vue.d.ts +4 -5
  24. package/dist/components/BccReplyBox.vue.d.ts +4 -5
  25. package/dist/components/BccReplyPreview.vue.d.ts +4 -5
  26. package/dist/components/CometChatMessageListOverride.vue.d.ts +1 -1
  27. package/dist/index.d.ts +0 -1
  28. package/dist/offline/cometChatAPIInterceptor.d.ts +0 -1
  29. package/dist/offline/cometChatWSInterceptor.d.ts +0 -1
  30. package/dist/offline/connectivity.d.ts +1 -2
  31. package/dist/offline/offlineStoreLocalStorage.d.ts +0 -1
  32. package/dist/style.css +1 -1
  33. package/dist/vue-bcc-chat-ui.js +28304 -27725
  34. package/package.json +14 -13
  35. package/src/components/BccAttachmentBox.vue +132 -0
  36. package/src/components/BccAttachmentPreview.vue +37 -0
  37. package/src/components/BccChatMessageBubble.vue +35 -8
  38. package/src/components/BccChatMessageList.vue +79 -26
  39. package/src/components/BccChatSendButton.vue +42 -0
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.11.0",
5
+ "version": "3.13.0",
6
6
  "type": "module",
7
7
  "private": false,
8
8
  "files": [
@@ -34,22 +34,23 @@
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/dompurify": "^3.0.5",
37
- "@types/markdown-it": "^14.1.1",
37
+ "@types/markdown-it": "^14.1.2",
38
38
  "@types/node": "^20.14.9",
39
- "@vitejs/plugin-vue": "^5.0.5",
39
+ "@vitejs/plugin-vue": "^5.1.3",
40
40
  "path": "^0.12.7",
41
- "sass": "^1.77.6",
42
- "typescript": "^5.5.2",
43
- "vite": "^5.3.2",
44
- "vite-plugin-dts": "^3.9.1",
45
- "vue": "^3.4.31"
41
+ "sass": "^1.77.8",
42
+ "typescript": "^5.5.4",
43
+ "vite": "^5.4.2",
44
+ "vite-plugin-dts": "^4.1.0",
45
+ "vue": "^3.4.38"
46
46
  },
47
47
  "dependencies": {
48
- "@cometchat/chat-sdk-javascript": "4.0.7",
49
- "@cometchat/chat-uikit-vue": "4.3.11",
50
- "@cometchat/uikit-resources": "4.3.9",
51
- "@cometchat/uikit-shared": "4.3.12",
52
- "dompurify": "^3.1.5",
48
+ "@cometchat/chat-sdk-javascript": "4.0.10",
49
+ "@cometchat/chat-uikit-vue": "4.3.16",
50
+ "@cometchat/uikit-elements": "4.3.15",
51
+ "@cometchat/uikit-resources": "4.3.11",
52
+ "@cometchat/uikit-shared": "4.3.17",
53
+ "dompurify": "^3.1.6",
53
54
  "jwt-decode": "^4.0.0",
54
55
  "markdown-it": "^14.1.0",
55
56
  "panzoom": "^9.4.3"
@@ -0,0 +1,132 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ CometChatMessageEvents,
4
+ CometChatTheme,
5
+ MessageStatus,
6
+ } from "@cometchat/uikit-resources";
7
+ import { CloseIcon } from "@cometchat/chat-uikit-vue";
8
+ import {
9
+ getCurrentInstance,
10
+ ref,
11
+ inject,
12
+ Ref,
13
+ onBeforeUnmount,
14
+ onBeforeMount,
15
+ onMounted,
16
+ } from "vue";
17
+ import { ChatInstance } from "../chat/types";
18
+ import BccAttachmentPreview from "./BccAttachmentPreview.vue";
19
+
20
+ const props = defineProps({
21
+ captionedAttachment: { type: Object },
22
+ closeButtonIconURL: { type: String, default: CloseIcon },
23
+ previewStyle: { type: Object, default: {} },
24
+ });
25
+
26
+ const chatInstance = inject<Ref<ChatInstance>>("chatInstance");
27
+ const vueInstance: any = getCurrentInstance();
28
+
29
+ const { theme } = inject("theme", { theme: ref(new CometChatTheme({})) });
30
+
31
+ function closePreview(_event?: MouseEvent) {
32
+ if (chatInstance) {
33
+ chatInstance.value.captionedAttachment = null;
34
+ }
35
+ }
36
+
37
+ const onMessageEditStart = CometChatMessageEvents.ccMessageEdited.subscribe(
38
+ ({ status }) => {
39
+ if (status === MessageStatus.inprogress) {
40
+ closePreview();
41
+ }
42
+ }
43
+ );
44
+
45
+ const onMessageSend = CometChatMessageEvents.ccMessageSent.subscribe(
46
+ ({ status }) => {
47
+ if (status === MessageStatus.inprogress) {
48
+ closePreview();
49
+ }
50
+ }
51
+ );
52
+
53
+ onBeforeMount(() => {
54
+ vueInstance?.parent?.setupState?.closePreview();
55
+ });
56
+
57
+ onBeforeUnmount(() => {
58
+ onMessageEditStart.unsubscribe();
59
+ onMessageSend.unsubscribe();
60
+ });
61
+
62
+ onMounted(() => {
63
+ let inputField = document.querySelector(".messageinput-input");
64
+
65
+ if (inputField) {
66
+ inputField.innerHTML = props?.captionedAttachment?.caption ?? "";
67
+ }
68
+ })
69
+
70
+ const closeBtnIconStyle = () => {
71
+ return {
72
+ buttonIconTint: theme.value.palette.getAccent500(),
73
+ height: "14px",
74
+ width: "14px",
75
+ border: "none",
76
+ borderRadius: "0",
77
+ background: "transparent",
78
+ display: "flex",
79
+ justifyContent: "center",
80
+ alignItems: "center",
81
+ };
82
+ };
83
+
84
+ const wrapperStyle = () => {
85
+ return {
86
+ background: theme.value.palette.getBackground(),
87
+ border: `1px solid ${theme.value.palette.getAccent200()}`,
88
+ height: "100%",
89
+ width: "100%",
90
+ borderRadius: "12px",
91
+ };
92
+ };
93
+ </script>
94
+
95
+ <template>
96
+ <div class="bcc__attachment_box" :style="wrapperStyle()">
97
+ <BccAttachmentPreview
98
+ :captionedAttachment="props.captionedAttachment"
99
+ :previewStyle="previewStyle"
100
+ />
101
+ <div class="bcc__attachment_preview__close" @click="closePreview">
102
+ <cometchat-button
103
+ :buttonStyle="closeBtnIconStyle()"
104
+ :iconURL="props.closeButtonIconURL"
105
+ ></cometchat-button>
106
+ </div>
107
+ </div>
108
+ </template>
109
+
110
+ <style>
111
+ .cc-messagecomposer-wrapper__headerview {
112
+ position: static !important;
113
+ }
114
+ </style>
115
+ <style scoped>
116
+ * {
117
+ box-sizing: border-box;
118
+ }
119
+ .bcc__attachment_box {
120
+ padding: 8px;
121
+ display: flex;
122
+ flex-direction: row;
123
+ justify-content: space-between;
124
+ margin: 0;
125
+ min-height: 30px;
126
+ }
127
+ .bcc__attachment_preview__close {
128
+ width: 14px;
129
+ height: 14px;
130
+ display: inline-block;
131
+ }
132
+ </style>
@@ -0,0 +1,37 @@
1
+ <script setup lang="ts">
2
+ const props = defineProps({
3
+ captionedAttachment: { type: Object, default: {} },
4
+ previewStyle: { type: Object, default: {} },
5
+ });
6
+ </script>
7
+
8
+ <template>
9
+ <div class="bcc__attachment_preview__content_wrapper">
10
+ <div class="bcc__attachment_preview__content">
11
+ <img :src="props.captionedAttachment?.image" />
12
+ </div>
13
+ </div>
14
+ </template>
15
+
16
+ <style scoped>
17
+ .bcc__attachment_preview__content_wrapper {
18
+ padding: 0 5px 0 20px;
19
+ position: relative;
20
+ width: 100%;
21
+ }
22
+
23
+ .bcc__attachment_preview__content {
24
+ width: 100%;
25
+ max-height: 350px;
26
+ height: 100%;
27
+ display: flex;
28
+ justify-content: center;
29
+ align-items: center;
30
+ }
31
+
32
+ .bcc__attachment_preview__content>img {
33
+ width: 100%;
34
+ height: 100%;
35
+ object-fit: contain;
36
+ }
37
+ </style>
@@ -1,16 +1,36 @@
1
1
  <script setup lang="ts">
2
2
  import MarkdownIt from 'markdown-it'
3
- import { BaseMessage, CometChat, User } from '@cometchat/chat-sdk-javascript'
3
+ import { BaseMessage, CometChat, MediaMessage, User } from '@cometchat/chat-sdk-javascript'
4
4
  import DOMPurify from 'dompurify';
5
5
  import { inject, ref } from 'vue';
6
6
  import { CometChatTheme, fontHelper } from '@cometchat/uikit-resources';
7
7
  import BccReplyPreview from "./BccReplyPreview.vue";
8
-
9
- const props = defineProps<{
10
- text: string,
11
- metadata: Record<string, any>,
12
- mentionedUsers: User[],
13
- }>()
8
+ import BccImageBubble from './BccImageBubble.vue';
9
+
10
+ const props = defineProps({
11
+ text: {
12
+ type: String,
13
+ required: true
14
+ },
15
+ metadata: {
16
+ type: Object
17
+ },
18
+ mentionedUsers: {
19
+ type: Array<User>
20
+ },
21
+ message: {
22
+ type: MediaMessage,
23
+ default: null
24
+ },
25
+ placeholderImage: {
26
+ type: String,
27
+ default: null
28
+ },
29
+ src: {
30
+ type: String,
31
+ default: null
32
+ }
33
+ })
14
34
 
15
35
  function toMarkdownHtml(str: string) {
16
36
  str = formatMentionsInText(str);
@@ -73,7 +93,7 @@ const replyPreviewStyle = {
73
93
  </script>
74
94
 
75
95
  <template>
76
- <div>
96
+ <div :style="{'display': src != null ? 'table-caption' : 'block'}">
77
97
  <div v-if="metadata?.replyToMessageId" class="bcc-chat-msg-bubble">
78
98
  <div class="bcc-chat-msg-bubble--reply">
79
99
  <BccReplyPreview
@@ -82,6 +102,13 @@ const replyPreviewStyle = {
82
102
  />
83
103
  </div>
84
104
  </div>
105
+ <div v-if="src != null" style="display: block; width: max-content;">
106
+ <BccImageBubble
107
+ :message="message"
108
+ :placeholderImage="placeholderImage"
109
+ :src="src"
110
+ />
111
+ </div>
85
112
  <div v-if="metadata && metadata.translated_message" v-html="toMarkdownHtml(metadata.translated_message)"
86
113
  class="bcc-chat-msg-bubble bcc-chat-msg-bubble--translation" />
87
114
  <div v-html="toMarkdownHtml(text)" class="bcc-chat-msg-bubble"
@@ -8,13 +8,13 @@ import {
8
8
  provide,
9
9
  ref,
10
10
  watch,
11
- watchEffect,
11
+ watchEffect,
12
12
  } from "vue";
13
13
  import chat from "../chat";
14
14
  import { connect, disconnect } from "../chat/connection";
15
15
  import { loggedIn } from "../chat/login";
16
16
  import { CometChatMessages } from "../chat/cometChatPatches";
17
- import { Group } from "@cometchat/chat-sdk-javascript";
17
+ import { BaseMessage, Group, CometChat } from "@cometchat/chat-sdk-javascript";
18
18
  import { watchAndApplyStyle } from "../chat/styleFix";
19
19
  import {
20
20
  getMessageComposerConfiguration,
@@ -23,10 +23,12 @@ import {
23
23
  } from "../chat/uiKit";
24
24
  import { ChatInstance } from "../chat/types";
25
25
  import { CometChatMessageEvents, MessageStatus } from "@cometchat/uikit-resources";
26
+ import BccAttachmentBox from "./BccAttachmentBox.vue";
27
+ import BccChatSendButton from "./BccChatSendButton.vue";
26
28
 
27
29
  const props = defineProps({
28
30
  chatUid: { type: String, required: true },
29
- senderDisplayName: { type: String, required: false}
31
+ senderDisplayName: { type: String, required: false }
30
32
  });
31
33
 
32
34
  const componentId = ref(
@@ -36,19 +38,20 @@ const chatGroup = ref<Group>();
36
38
 
37
39
  const chatInstance: Ref<ChatInstance> = ref({
38
40
  componentId: componentId,
39
- replyToMessage: null
41
+ replyToMessage: null,
42
+ captionedAttachment: null
40
43
  });
41
44
 
42
- const messageComposerConfiguration = getMessageComposerConfiguration();
43
- const messageListConfiguration = getMessageListConfiguration(chatInstance);
44
- const threadedMessagesConfiguration = getThreadedMessagesConfiguration();
45
+ const messageComposerConfiguration = getMessageComposerConfiguration(chatInstance);
46
+ const messageListConfiguration = getMessageListConfiguration(chatInstance, chatGroup);
47
+ const threadedMessagesConfiguration = getThreadedMessagesConfiguration(chatGroup);
45
48
 
46
49
  provide("chatInstance", chatInstance);
47
50
 
48
51
  const onMessageSend = CometChatMessageEvents.ccMessageSent.subscribe(({ message, status }) => {
49
52
  if (status === MessageStatus.inprogress) {
50
- let metadata: any = {};
51
- let scope: string | undefined = chatGroup.value?.getScope()
53
+ let metadata: any = (message as any)?.getMetadata() || {};
54
+ let scope: string | undefined = chatGroup.value?.getScope();
52
55
 
53
56
  if (chatInstance.value.replyToMessage) {
54
57
  metadata.replyToMessageId = chatInstance.value.replyToMessage?.getId()
@@ -58,11 +61,18 @@ const onMessageSend = CometChatMessageEvents.ccMessageSent.subscribe(({ message,
58
61
  metadata.senderDisplayName = props.senderDisplayName
59
62
  }
60
63
 
61
- if (Object.keys(metadata).length === 0) {
62
- return
63
- }
64
+ (message as any)?.setMetadata(metadata);
65
+
66
+ if (chatInstance.value?.captionedAttachment?.caption && message instanceof CometChat.MediaMessage) {
67
+ message.setCaption(chatInstance.value.captionedAttachment.caption);
68
+ let inputField = document.querySelector(".messageinput-input");
64
69
 
65
- (message as any).setMetadata(metadata);
70
+ if (inputField) {
71
+ inputField.innerHTML = "";
72
+ }
73
+ chatInstance.value.captionedAttachment = null;
74
+ messageComposerConfiguration.value.text = '';
75
+ }
66
76
  }
67
77
  });
68
78
 
@@ -79,10 +89,37 @@ watchEffect(() => {
79
89
  }
80
90
  });
81
91
 
82
- watch([loggedIn, ()=> props.chatUid, chat.initialized], async ([_loggedIn, _chatUid, _initialized]) => {
92
+ watchEffect(() => {
93
+ if (!chatInstance.value.captionedAttachment) {
94
+ messageComposerConfiguration.value.headerView = undefined;
95
+ messageComposerConfiguration.value.sendButtonView = undefined;
96
+ } else {
97
+ chatInstance.value.captionedAttachment.caption = messageComposerConfiguration.value.text;
98
+
99
+ messageComposerConfiguration.value.headerView = {
100
+ componentName: BccAttachmentBox,
101
+ props: {
102
+ captionedAttachment: chatInstance.value.captionedAttachment
103
+ }
104
+ }
105
+
106
+ messageComposerConfiguration.value.sendButtonView = {
107
+ componentName: BccChatSendButton,
108
+ props: {
109
+ msgComposerConfig: messageComposerConfiguration.value,
110
+ fileObject: chatInstance.value.captionedAttachment.fileObject,
111
+ receiverId: chatGroup.value?.getGuid(),
112
+ receiverType: "group",
113
+ messageType: "image"
114
+ }
115
+ };
116
+ }
117
+ });
118
+
119
+ watch([loggedIn, () => props.chatUid, chat.initialized], async ([_loggedIn, _chatUid, _initialized]) => {
83
120
  if (_loggedIn && _chatUid && _initialized) {
84
121
  chatGroup.value = (await chat.getGroup(props.chatUid)) ?? undefined;
85
- await chat.clearGroupChatCount(props.chatUid);
122
+ await chat.clearGroupChatCount(props.chatUid);
86
123
  } else if (chatGroup.value) {
87
124
  chatGroup.value = undefined;
88
125
  }
@@ -101,7 +138,7 @@ onMounted(() => {
101
138
  },
102
139
  {
103
140
  selector: ".cc__preview__subtitle",
104
- style: {
141
+ style: {
105
142
  "overflow": "hidden",
106
143
  "display": "-webkit-box",
107
144
  "-webkit-box-orient": "vertical",
@@ -111,6 +148,13 @@ onMounted(() => {
111
148
  shadowDomSelector: "cometchat-preview",
112
149
  }
113
150
  ]);
151
+
152
+ messageComposerConfiguration.value.onTextChange = (text: any) => {
153
+ messageComposerConfiguration.value.text = text;
154
+ if (chatInstance.value.captionedAttachment?.caption) {
155
+ chatInstance.value.captionedAttachment.caption = text;
156
+ }
157
+ }
114
158
  });
115
159
 
116
160
  onBeforeUnmount(() => {
@@ -121,6 +165,14 @@ onUnmounted(async () => {
121
165
  await disconnect(componentId.value);
122
166
  });
123
167
 
168
+ function isChannel(): boolean {
169
+ return (chatGroup.value?.getMetadata() as any)?.isChannel;
170
+ }
171
+
172
+ function isParticipant(): boolean {
173
+ return chatGroup.value?.getScope() == "participant";
174
+ }
175
+
124
176
  </script>
125
177
 
126
178
  <template>
@@ -134,18 +186,14 @@ onUnmounted(async () => {
134
186
  <div>CometChat: {{cometChatStatus}} <button @click="getCometChatStatus()">[refresh]</button></div>
135
187
  </div> -->
136
188
  <div v-if="chatGroup" class="bcc-chat-message-list">
137
- <CometChatMessages
138
- :hideMessageHeader="true"
139
- :disableSoundForMessages="true"
189
+ <CometChatMessages :hideMessageHeader="true" :disableSoundForMessages="true"
140
190
  :messageComposerConfiguration="messageComposerConfiguration"
141
191
  :messageListConfiguration="messageListConfiguration"
142
192
  :threadedMessagesConfiguration="threadedMessagesConfiguration"
143
- :hideMessageComposer="false"
144
- :hideDetails="true"
145
- :group="chatGroup"
146
- />
147
-
148
- <div v-if="chat.onlineStatus.value === 'offline' || !chat.connected.value" class="bcc-chat-message-composer-offline">
193
+ :hideMessageComposer="isParticipant() && isChannel()" :hideDetails="true" :group="chatGroup" />
194
+
195
+ <div v-if="chat.onlineStatus.value === 'offline' || !chat.connected.value"
196
+ class="bcc-chat-message-composer-offline">
149
197
  <span v-if="chat.onlineStatus.value === 'offline'">Waiting for network...</span>
150
198
  <span v-else>Connecting...</span>
151
199
  </div>
@@ -229,11 +277,13 @@ accent900: text in avatar
229
277
 
230
278
  /* 1. Wrapper for Messages component */
231
279
  .cc-messages-wrapper {
280
+
232
281
  /* 1.1 Messages component */
233
282
  .cc-messages-wrapper__messages {
283
+
234
284
  /* 1.1.1 Wrapper for Messages List */
235
285
  .cc-messages-wrapper__messages-list {
236
- height: calc(100% - 96px);
286
+ height: 100%;
237
287
  }
238
288
 
239
289
  /* 1.1.2 Wrapper for Messages Composer */
@@ -243,6 +293,7 @@ accent900: text in avatar
243
293
 
244
294
  /* 1.1.3 Wrapper for Messages Composer Header View */
245
295
  .cc-messagecomposer-wrapper__headerview {
296
+ max-height: 100%;
246
297
  margin-bottom: 5px;
247
298
  }
248
299
  }
@@ -254,10 +305,12 @@ accent900: text in avatar
254
305
 
255
306
  .cc-messagebubble-wrapper__messageoptions {
256
307
  border-radius: 8px;
308
+
257
309
  .cc-context-menu__top-menu {
258
310
  border: 1px var(--cc__secondary) solid !important;
259
311
  }
260
312
  }
313
+
261
314
  /* 2. Message for Messages Composer when offline */
262
315
  .bcc-chat-message-composer-offline {
263
316
  position: relative;
@@ -0,0 +1,42 @@
1
+ <script setup lang="ts">
2
+ import { localize } from "@cometchat/uikit-resources";
3
+ import { SendIcon } from "@cometchat/chat-uikit-vue";
4
+ import { MessageComposerConfiguration } from "@cometchat/uikit-shared";
5
+ import { sendMediaMessage } from "../chat/captionedAttachment";
6
+
7
+ const props = defineProps({
8
+ msgComposerConfig: { type: MessageComposerConfiguration, required: true },
9
+ fileObject: { type: File, required: true },
10
+ receiverId: { type: String, required: true },
11
+ receiverType: { type: String, required: true },
12
+ messageType: { type: String, required: true }
13
+ });
14
+
15
+ const sendButtonIconURL = SendIcon;
16
+ const sendButtonStyle = {
17
+ height: "24px",
18
+ width: "24px",
19
+ border: "none",
20
+ borderRadius: "0",
21
+ buttonIconTint: "#2fb5e9d1",
22
+ background: "transparent"
23
+ }
24
+
25
+ function sendMessageWithoutCaption() {
26
+ sendMediaMessage(props.msgComposerConfig, props.fileObject, props.receiverId, props.receiverType, props.messageType);
27
+ }
28
+
29
+ </script>
30
+
31
+ <template>
32
+ <div class="cc-messagecomposer-wrapper__sendbutton" ref="sendButton">
33
+ <cometchat-button :iconURL="sendButtonIconURL" :buttonStyle="sendButtonStyle"
34
+ :hoverText="localize('SEND_MESSAGE')" @click=sendMessageWithoutCaption() />
35
+ </div>
36
+ </template>
37
+
38
+ <style scoped>
39
+ .cc-messagecomposer-wrapper__sendbutton {
40
+ margin: 0 5px
41
+ }
42
+ </style>