@bcc-code/vue-bcc-chat-ui 3.12.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.
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.12.0",
5
+ "version": "3.13.0",
6
6
  "type": "module",
7
7
  "private": false,
8
8
  "files": [
@@ -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"
@@ -14,7 +14,7 @@ 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,10 +38,11 @@ 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();
45
+ const messageComposerConfiguration = getMessageComposerConfiguration(chatInstance);
43
46
  const messageListConfiguration = getMessageListConfiguration(chatInstance, chatGroup);
44
47
  const threadedMessagesConfiguration = getThreadedMessagesConfiguration(chatGroup);
45
48
 
@@ -47,8 +50,8 @@ 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,6 +89,33 @@ watchEffect(() => {
79
89
  }
80
90
  });
81
91
 
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
+
82
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;
@@ -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(() => {
@@ -122,7 +166,7 @@ onUnmounted(async () => {
122
166
  });
123
167
 
124
168
  function isChannel(): boolean {
125
- return chatGroup.value?.getMetadata()?.isChannel;
169
+ return (chatGroup.value?.getMetadata() as any)?.isChannel;
126
170
  }
127
171
 
128
172
  function isParticipant(): boolean {
@@ -249,6 +293,7 @@ accent900: text in avatar
249
293
 
250
294
  /* 1.1.3 Wrapper for Messages Composer Header View */
251
295
  .cc-messagecomposer-wrapper__headerview {
296
+ max-height: 100%;
252
297
  margin-bottom: 5px;
253
298
  }
254
299
  }
@@ -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>