tuikit-atomicx-vue3 4.5.0 → 4.5.2
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/dist/{MessageInput.vue_vue_type_script_setup_true_lang-jPzZ5INK.js → MessageInput.vue_vue_type_script_setup_true_lang-3RVYOdkv.js} +38 -38
- package/dist/{PopoverTrigger-L8abAry7.js → PopoverPortal-DV6zFXcf.js} +91 -136
- package/dist/PopoverTrigger-DIjW4PKa.js +54 -0
- package/dist/{PopperContent-XdhqL8Y2.js → PopperContent-D__dbwpA.js} +6 -6
- package/dist/{Teleport-CSEuZbpM.js → Teleport-98QrIYDI.js} +280 -270
- package/dist/baseComp/Modal/Modal.js +3 -3
- package/dist/components/AudioSettingPanel/index.js +14 -14
- package/dist/components/BarrageInput/EmojiPicker/EmojiPicker.js +10 -9
- package/dist/components/BarrageInput/TextEditor/CharacterCountExtension.js +1 -1
- package/dist/components/BarrageInput/TextEditor/EditorCore.js +16 -15
- package/dist/components/ConversationList/ConversationActions/ConversationActions.js +53 -50
- package/dist/components/ConversationList/ConversationActions/ConversationActions.vue.d.ts +2 -0
- package/dist/components/ConversationList/ConversationCreate/ConversationCreate.js +25 -25
- package/dist/components/ConversationList/ConversationList.vue.d.ts +16 -0
- package/dist/components/ConversationList/ConversationPreview/ConversationPreview.vue.d.ts +16 -0
- package/dist/components/ConversationList/ConversationPreview/ConversationPreviewAbstract.js +62 -40
- package/dist/components/ConversationList/ConversationPreview/ConversationPreviewTimestamp.js +28 -26
- package/dist/components/ConversationList/ConversationPreview/ConversationPreviewTitle.js +27 -23
- package/dist/components/ConversationList/ConversationPreview/ConversationPreviewTitle.vue.d.ts +1 -1
- package/dist/components/ConversationList/ConversationPreview/ConversationPreviewUI.js +81 -70
- package/dist/components/ConversationList/ConversationPreview/ConversationPreviewUI.vue.d.ts +4 -0
- package/dist/components/ConversationList/ConversationPreview/ConversationPreviewUnread.js +33 -31
- package/dist/components/ConversationList/ConversationPreview/utils.d.ts +2 -2
- package/dist/components/ConversationList/ConversationPreview/utils.js +81 -35
- package/dist/components/ConversationList/i18n/en-US.d.ts +11 -1
- package/dist/components/ConversationList/i18n/en-US.js +12 -2
- package/dist/components/ConversationList/i18n/zh-CN.d.ts +11 -1
- package/dist/components/ConversationList/i18n/zh-CN.js +12 -2
- package/dist/components/ConversationList/index.d.ts +48 -0
- package/dist/components/MessageInput/AttachmentPicker/index.js +10 -9
- package/dist/components/MessageInput/EmojiPicker/EmojiPicker.js +17 -16
- package/dist/components/MessageInput/MessageInput.js +1 -1
- package/dist/components/MessageInput/QuotedMessagePreview/index.js +35 -35
- package/dist/components/MessageInput/TextEditor/EditorCore.d.ts +13 -12
- package/dist/components/MessageInput/TextEditor/EditorCore.js +54 -89
- package/dist/components/MessageInput/TextEditor/extensions/MentionSuggestion.js +229 -0
- package/dist/components/MessageInput/TextEditor/extensions/MentionSuggestion.vue.d.ts +15 -0
- package/dist/components/MessageInput/TextEditor/extensions/characterCountExtension.js +1 -1
- package/dist/components/MessageInput/TextEditor/extensions/emojiExtension.d.ts +1 -0
- package/dist/components/MessageInput/TextEditor/extensions/emojiExtension.js +22 -0
- package/dist/components/MessageInput/TextEditor/extensions/enterKeyExtension.d.ts +3 -0
- package/dist/components/MessageInput/TextEditor/extensions/enterKeyExtension.js +15 -0
- package/dist/components/MessageInput/TextEditor/extensions/imageExtension.js +2 -2
- package/dist/components/MessageInput/TextEditor/extensions/index.d.ts +8 -0
- package/dist/components/MessageInput/TextEditor/extensions/index.js +12 -0
- package/dist/components/MessageInput/TextEditor/extensions/mentionExtension.d.ts +5 -0
- package/dist/components/MessageInput/TextEditor/extensions/mentionExtension.js +330 -0
- package/dist/components/MessageInput/TextEditor/index.js +62 -62
- package/dist/components/MessageInput/i18n/en-US.d.ts +3 -0
- package/dist/components/MessageInput/i18n/en-US.js +4 -1
- package/dist/components/MessageInput/i18n/index.d.ts +6 -0
- package/dist/components/MessageInput/i18n/zh-CN.d.ts +3 -0
- package/dist/components/MessageInput/i18n/zh-CN.js +4 -1
- package/dist/components/MessageInput/index.js +1 -1
- package/dist/components/MessageList/Message/ImageMessage/ImageMessage.js +119 -89
- package/dist/components/MessageList/Message/ImageMessage/ImagePreview.js +142 -0
- package/dist/components/MessageList/Message/ImageMessage/ImagePreview.vue.d.ts +20 -0
- package/dist/components/MessageList/Message/Message.vue.d.ts +8 -0
- package/dist/components/MessageList/Message/MessageLayout/MessageActionDropdown/MessageActionDropdown.js +3 -3
- package/dist/components/MessageList/Message/MessageLayout/MessageLayout.js +69 -58
- package/dist/components/MessageList/Message/MessageLayout/MessageLayout.vue.d.ts +8 -0
- package/dist/components/MessageList/Message/MessageLayout/MessageMeta/MessageMeta.js +37 -28
- package/dist/components/MessageList/Message/index.js +8 -4
- package/dist/components/MessageList/MessageList.js +109 -91
- package/dist/components/MessageList/MessageList.vue.d.ts +1 -1
- package/dist/components/MessageList/index.d.ts +21 -3
- package/dist/components/ScheduleRoomPanel/RoomDetail.js +22 -22
- package/dist/components/ScheduleRoomPanel/RoomEdit.js +1 -1
- package/dist/components/ScheduleRoomPanel/RoomShare.js +4 -4
- package/dist/components/ScheduleRoomPanel/ScheduleRoomPanel.js +1 -1
- package/dist/components/ScheduleRoomPanel/ScheduledRoomList.js +1 -1
- package/dist/components/Search/SearchResults/SearchResultsItem/Message/Message.js +6 -6
- package/dist/components/Search/SearchResults/SearchResultsItem/Message/Message.vue.d.ts +1 -1
- package/dist/components/UIKitModal/chatErrorModal/chatErrorModal.d.ts +72 -0
- package/dist/components/UIKitModal/chatErrorModal/chatErrorModal.js +95 -0
- package/dist/components/UIKitModal/chatErrorModal/i18n/en-US/index.d.ts +40 -0
- package/dist/components/UIKitModal/chatErrorModal/i18n/en-US/index.js +51 -0
- package/dist/components/UIKitModal/chatErrorModal/i18n/index.d.ts +4 -0
- package/dist/components/UIKitModal/chatErrorModal/i18n/index.js +6 -0
- package/dist/components/UIKitModal/chatErrorModal/i18n/zh-CN/index.d.ts +40 -0
- package/dist/components/UIKitModal/chatErrorModal/i18n/zh-CN/index.js +51 -0
- package/dist/components/UIKitModal/chatErrorModal/index.d.ts +3 -0
- package/dist/components/UIKitModal/chatErrorModal/index.js +11 -0
- package/dist/components/VideoSettingPanel/index.js +1 -1
- package/dist/hooks/useReadReceipt/useReadReceipt.js +44 -41
- package/dist/index-CTthrJb2.js +1461 -0
- package/dist/index-DXC5bPY4.js +2174 -0
- package/dist/{index-Do-2CngU.js → index-DuAffztD.js} +115 -142
- package/dist/{index-7vNB_Vx8.js → index-hHVD-MG2.js} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +150 -149
- package/dist/states/GroupSettingState/GroupSettingState.js +109 -102
- package/dist/states/LoginState.js +43 -43
- package/dist/states/MessageActionState/MessageActionState.js +83 -223
- package/dist/states/MessageInputState/MessageInputState.js +111 -82
- package/dist/states/MessageInputState/type.d.ts +36 -10
- package/dist/states/MessageInputState/utils.d.ts +1 -5
- package/dist/states/MessageListState/MessageListState.d.ts +1 -1
- package/dist/states/MessageListState/MessageListState.js +26 -23
- package/dist/states/RoomParticipantState/index.js +83 -24
- package/dist/states/RoomParticipantState/participantEventManager.d.ts +2 -2
- package/dist/states/RoomParticipantState/participantEventManager.js +217 -205
- package/dist/states/RoomParticipantState/participantManager.d.ts +4 -0
- package/dist/states/RoomParticipantState/participantManager.js +159 -127
- package/dist/states/RoomState/callManager.d.ts +3 -3
- package/dist/states/RoomState/callManager.js +20 -20
- package/dist/states/RoomState/common.d.ts +3 -2
- package/dist/states/RoomState/common.js +34 -24
- package/dist/states/RoomState/roomManager.d.ts +0 -1
- package/dist/states/RoomState/roomManager.js +21 -27
- package/dist/states/RoomState/scheduleManager.js +2 -2
- package/dist/styles/index.css +1 -1
- package/dist/{chat/index.d.ts → subEntry/chat/chat.d.ts} +2160 -2087
- package/dist/subEntry/chat/chat.js +89 -0
- package/dist/subEntry/chat/index.d.ts +11 -0
- package/dist/subEntry/chat/index.js +81 -0
- package/dist/{chat → subEntry/chat}/server.js +4 -4
- package/dist/subEntry/live/index.js +46 -45
- package/dist/subEntry/room/index.js +39 -38
- package/dist/types/beauty.d.ts +20 -0
- package/dist/types/index.js +37 -36
- package/dist/types/participant.d.ts +2 -0
- package/dist/types/room.d.ts +45 -1
- package/dist/types/room.js +4 -3
- package/dist/{useId-CtirfF0W.js → useId-B1VwPJLm.js} +1 -1
- package/dist/utils/call.js +77 -71
- package/dist/{utils-DaB7eSu5.js → utils-BU8IkP_V.js} +1 -1
- package/package.json +8 -7
- package/src/components/AudioSettingPanel/index.vue +4 -5
- package/src/components/ConversationList/ConversationActions/ConversationActions.vue +7 -1
- package/src/components/ConversationList/ConversationCreate/ConversationCreate.vue +5 -1
- package/src/components/ConversationList/ConversationList.vue +0 -1
- package/src/components/ConversationList/ConversationPreview/ConversationPreview.scss +10 -2
- package/src/components/ConversationList/ConversationPreview/ConversationPreviewAbstract.vue +32 -1
- package/src/components/ConversationList/ConversationPreview/ConversationPreviewTitle.vue +3 -2
- package/src/components/ConversationList/ConversationPreview/ConversationPreviewUI.vue +15 -0
- package/src/components/ConversationList/ConversationPreview/utils.ts +98 -28
- package/src/components/ConversationList/i18n/en-US.ts +11 -1
- package/src/components/ConversationList/i18n/zh-CN.ts +11 -1
- package/src/components/MessageInput/MessageInput.module.scss +1 -0
- package/src/components/MessageInput/QuotedMessagePreview/QuotedMessagePreview.vue +19 -22
- package/src/components/MessageInput/TextEditor/Editor.scss +25 -0
- package/src/components/MessageInput/TextEditor/EditorCore.ts +79 -99
- package/src/components/MessageInput/TextEditor/TextEditor.vue +64 -68
- package/src/components/MessageInput/TextEditor/extensions/MentionSuggestion.vue +449 -0
- package/src/components/MessageInput/TextEditor/extensions/emojiExtension.ts +22 -0
- package/src/components/MessageInput/TextEditor/extensions/enterKeyExtension.ts +22 -0
- package/src/components/MessageInput/TextEditor/extensions/index.ts +8 -0
- package/src/components/MessageInput/TextEditor/extensions/mentionExtension.ts +87 -0
- package/src/components/MessageInput/i18n/en-US.ts +3 -0
- package/src/components/MessageInput/i18n/zh-CN.ts +3 -0
- package/src/components/MessageList/Message/ImageMessage/ImageMessage.vue +49 -0
- package/src/components/MessageList/Message/ImageMessage/ImagePreview.vue +344 -0
- package/src/components/MessageList/Message/Message.vue +6 -0
- package/src/components/MessageList/Message/MessageLayout/MessageLayout.vue +8 -1
- package/src/components/MessageList/Message/MessageLayout/MessageMeta/MessageMeta.vue +12 -3
- package/src/components/MessageList/MessageList.vue +50 -14
- package/src/components/ScheduleRoomPanel/RoomDetail.vue +1 -0
- package/src/components/ScheduleRoomPanel/RoomEdit.vue +2 -1
- package/src/components/ScheduleRoomPanel/RoomShare.vue +1 -0
- package/src/components/ScheduleRoomPanel/ScheduleRoomPanel.vue +1 -0
- package/src/components/ScheduleRoomPanel/ScheduledRoomList.vue +1 -0
- package/src/components/Search/SearchResults/SearchResultsItem/Message/Message.vue +30 -31
- package/src/components/UIKitModal/chatErrorModal/chatErrorModal.ts +205 -0
- package/src/components/UIKitModal/chatErrorModal/i18n/en-US/index.ts +56 -0
- package/src/components/UIKitModal/chatErrorModal/i18n/index.ts +4 -0
- package/src/components/UIKitModal/chatErrorModal/i18n/zh-CN/index.ts +56 -0
- package/src/components/UIKitModal/chatErrorModal/index.ts +16 -0
- package/src/components/VideoSettingPanel/index.vue +1 -0
- package/src/hooks/useReadReceipt/useReadReceipt.ts +5 -4
- package/src/index.ts +1 -1
- package/src/{chat/index.ts → subEntry/chat/chat.ts} +25 -18
- package/src/subEntry/chat/index.ts +13 -0
- package/src/{chat → subEntry/chat}/server.ts +3 -3
- package/src/types/beauty.ts +20 -0
- package/src/types/participant.ts +3 -0
- package/src/types/room.ts +49 -1
- package/src/utils/call.ts +8 -0
- package/dist/chat/index.js +0 -59
- package/dist/index-ZILx4LYk.js +0 -4826
- package/dist/states/SearchState.d.ts +0 -314
- /package/dist/{chat → subEntry/chat}/server.d.ts +0 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :class="$style.conversationPreview__abstract">
|
|
3
3
|
<template v-if="draftTextAbstract">
|
|
4
|
-
<label :class="$style.
|
|
4
|
+
<label :class="$style.conversationPreview__abstract__drafts">[{{ t('TUIConversation.Drafts') }}]</label>
|
|
5
5
|
{{ ' ' }}
|
|
6
6
|
{{ draftTextAbstract }}
|
|
7
7
|
</template>
|
|
8
8
|
<template v-else>
|
|
9
|
+
<label v-if="atInfoPreview" :class="$style['conversationPreview__abstract__at-info']">{{ atInfoPreview }}</label>
|
|
9
10
|
{{ latestMessagePreview }}
|
|
10
11
|
</template>
|
|
11
12
|
</div>
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
<script lang="ts" setup>
|
|
15
16
|
import { computed } from 'vue';
|
|
16
17
|
import { useUIKit } from '@tencentcloud/uikit-base-component-vue3';
|
|
18
|
+
import { ConversationType } from '../../../types';
|
|
17
19
|
import { JSONStringToParse } from '../../../utils';
|
|
18
20
|
import { getLatestMessagePreview } from './utils';
|
|
19
21
|
import type { ConversationModel } from '../../../types';
|
|
@@ -30,6 +32,35 @@ const draftTextAbstract = computed(() => {
|
|
|
30
32
|
});
|
|
31
33
|
|
|
32
34
|
const latestMessagePreview = computed(() => getLatestMessagePreview(props.conversation, t));
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get group @ info preview text.
|
|
38
|
+
* atTypeArray[0] values: 1 = someone @me, 2 = @all, 3 = @all + someone @me
|
|
39
|
+
*/
|
|
40
|
+
const atInfoPreview = computed(() => {
|
|
41
|
+
const { type, groupAtInfoList } = props?.conversation || {};
|
|
42
|
+
|
|
43
|
+
// Only show @ info for group conversations with valid groupAtInfoList
|
|
44
|
+
if (type !== ConversationType.GROUP || !groupAtInfoList?.length) {
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const atInfoTextList: string[] = [
|
|
49
|
+
`[${t('TUIConversation.someone_at_me')}]`,
|
|
50
|
+
`[${t('TUIConversation.at_all')}]`,
|
|
51
|
+
`[${t('TUIConversation.at_all')}][${t('TUIConversation.someone_at_me')}]`,
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
let atInfo = '';
|
|
55
|
+
groupAtInfoList.forEach((item) => {
|
|
56
|
+
const atType = item?.atTypeArray?.[0];
|
|
57
|
+
if (atType && atType >= 1 && atType <= 3) {
|
|
58
|
+
atInfo = atInfoTextList[atType - 1];
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return atInfo;
|
|
63
|
+
});
|
|
33
64
|
</script>
|
|
34
65
|
|
|
35
66
|
<style lang="scss" module>
|
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script lang="ts" setup>
|
|
8
|
-
import
|
|
8
|
+
import { computed } from 'vue';
|
|
9
|
+
import type { ConversationModel } from '../../../types/engine';
|
|
9
10
|
|
|
10
11
|
const props = defineProps<{
|
|
11
12
|
conversation: ConversationModel;
|
|
12
13
|
}>();
|
|
13
14
|
|
|
14
|
-
const title =props?.conversation?.getShowName?.() || '';
|
|
15
|
+
const title = computed(() => props?.conversation?.getShowName?.() || '');
|
|
15
16
|
</script>
|
|
16
17
|
|
|
17
18
|
<style lang="scss" module>
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
:conversation="conversation"
|
|
48
48
|
v-bind="actionsConfig"
|
|
49
49
|
@close="handleCloseActionsModal"
|
|
50
|
+
@dropdown-visible-change="handleDropdownVisibleChange"
|
|
50
51
|
/>
|
|
51
52
|
<component
|
|
52
53
|
:is="LastMessageTimestamp"
|
|
@@ -103,6 +104,7 @@ const { activeConversation, setActiveConversation } = useConversationListState()
|
|
|
103
104
|
|
|
104
105
|
const conversationPreviewRef = ref<HTMLElement>();
|
|
105
106
|
const isActionMenuActive = ref(false);
|
|
107
|
+
const isDropdownOpen = ref(false);
|
|
106
108
|
|
|
107
109
|
const { isHovered } = useMouseHover(conversationPreviewRef);
|
|
108
110
|
const { getEventHandlers } = useLongPress(() => {
|
|
@@ -115,6 +117,10 @@ const longPressEvents = getEventHandlers();
|
|
|
115
117
|
|
|
116
118
|
watch(isHovered, (newValue) => {
|
|
117
119
|
if (!isH5) {
|
|
120
|
+
// Don't hide when dropdown is open
|
|
121
|
+
if (!newValue && isDropdownOpen.value) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
118
124
|
isActionMenuActive.value = newValue;
|
|
119
125
|
}
|
|
120
126
|
});
|
|
@@ -127,6 +133,15 @@ const handleClick = () => {
|
|
|
127
133
|
const handleCloseActionsModal = () => {
|
|
128
134
|
isActionMenuActive.value = false;
|
|
129
135
|
};
|
|
136
|
+
|
|
137
|
+
const handleDropdownVisibleChange = (visible: boolean) => {
|
|
138
|
+
console.log('[ConversationPreview] dropdown visible changed:', visible);
|
|
139
|
+
isDropdownOpen.value = visible;
|
|
140
|
+
// When dropdown closes and mouse is not hovering, hide actions
|
|
141
|
+
if (!visible && !isHovered.value) {
|
|
142
|
+
isActionMenuActive.value = false;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
130
145
|
</script>
|
|
131
146
|
|
|
132
147
|
<style lang="scss" module>
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import TUIChatEngine from '@tencentcloud/chat-uikit-engine';
|
|
2
|
-
import
|
|
2
|
+
import { MessageType, ConversationType } from '../../../types/engine';
|
|
3
|
+
import { transformTextWithEmojiKeyToName, safeJSONParse } from '../../../utils';
|
|
4
|
+
import { parseCallMessageText } from '../../../utils/call';
|
|
5
|
+
import { resolveGroupTipMessage } from '../../MessageList/Message/GroupTipMessage/resolveGroupTipMessage';
|
|
6
|
+
import type { ConversationModel, MessageModel } from '../../../types/engine';
|
|
3
7
|
|
|
4
8
|
export const generateHighlightTitle = (
|
|
5
9
|
conversation: ConversationModel,
|
|
@@ -20,36 +24,102 @@ export const generateHighlightTitle = (
|
|
|
20
24
|
};
|
|
21
25
|
|
|
22
26
|
export const getLatestMessagePreview = (conversation: ConversationModel, t: (key: string) => string) => {
|
|
23
|
-
const {
|
|
27
|
+
const { draftText } = conversation || {};
|
|
28
|
+
|
|
29
|
+
// Handle draft message
|
|
30
|
+
if (draftText) {
|
|
31
|
+
if (typeof draftText === 'string') {
|
|
32
|
+
return draftText;
|
|
33
|
+
}
|
|
34
|
+
const draftInfo = safeJSONParse(draftText, { abstract: '' });
|
|
35
|
+
return draftInfo.abstract;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Handle special operation type messages
|
|
39
|
+
const OPERATION_MESSAGES: Record<number, string> = {
|
|
40
|
+
4: t('TUIConversation.you_have_been_removed_from_the_group'),
|
|
41
|
+
5: t('TUIConversation.the_group_chat_has_been_disbanded'),
|
|
42
|
+
8: t('TUIConversation.you_have_left_the_group_chat'),
|
|
43
|
+
};
|
|
44
|
+
if (conversation.operationType && OPERATION_MESSAGES[conversation.operationType]) {
|
|
45
|
+
return OPERATION_MESSAGES[conversation.operationType];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const { lastMessage } = conversation;
|
|
49
|
+
|
|
24
50
|
if (!lastMessage) {
|
|
25
51
|
return '';
|
|
26
52
|
}
|
|
27
53
|
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
const isGroupConversation = conversation.type === ConversationType.GROUP;
|
|
55
|
+
const typedLastMessage = lastMessage as unknown as MessageModel;
|
|
56
|
+
const { type, payload } = typedLastMessage;
|
|
57
|
+
|
|
58
|
+
let messageContent = '';
|
|
59
|
+
|
|
60
|
+
if (lastMessage?.isRevoked) {
|
|
61
|
+
messageContent = t('TUIConversation.recalled_a_message');
|
|
62
|
+
} else {
|
|
63
|
+
switch (type) {
|
|
64
|
+
case MessageType.TEXT:
|
|
65
|
+
messageContent = transformTextWithEmojiKeyToName(payload.text || '');
|
|
66
|
+
break;
|
|
67
|
+
case MessageType.IMAGE:
|
|
68
|
+
messageContent = `[${t('TUIConversation.Image')}]`;
|
|
69
|
+
break;
|
|
70
|
+
case MessageType.AUDIO:
|
|
71
|
+
messageContent = `[${t('TUIConversation.Audio')}]`;
|
|
72
|
+
break;
|
|
73
|
+
case MessageType.VIDEO:
|
|
74
|
+
messageContent = `[${t('TUIConversation.Video')}]`;
|
|
75
|
+
break;
|
|
76
|
+
case MessageType.FILE:
|
|
77
|
+
messageContent = `[${t('TUIConversation.File')}]`;
|
|
78
|
+
break;
|
|
79
|
+
case MessageType.CUSTOM: {
|
|
80
|
+
const data = safeJSONParse(payload?.data, { businessID: undefined });
|
|
81
|
+
// Handle CallKit signaling message
|
|
82
|
+
if (data?.businessID === 1) {
|
|
83
|
+
try {
|
|
84
|
+
messageContent = parseCallMessageText(typedLastMessage, t);
|
|
85
|
+
} catch {
|
|
86
|
+
messageContent = `[${t('TUIConversation.call_message')}]`;
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
messageContent = `[${t('TUIConversation.Custom')}]`;
|
|
90
|
+
}
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
case MessageType.LOCATION:
|
|
94
|
+
messageContent = `[${t('TUIConversation.Location')}]`;
|
|
95
|
+
break;
|
|
96
|
+
case MessageType.FACE:
|
|
97
|
+
messageContent = `[${t('TUIConversation.Face')}]`;
|
|
98
|
+
break;
|
|
99
|
+
case MessageType.MERGER:
|
|
100
|
+
messageContent = `[${t('TUIConversation.Chat History')}]`;
|
|
101
|
+
break;
|
|
102
|
+
case MessageType.GRP_TIP:
|
|
103
|
+
return resolveGroupTipMessage(typedLastMessage)?.text;
|
|
104
|
+
default:
|
|
105
|
+
messageContent = `[${t('TUIConversation.unknown_message')}]`;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
54
108
|
}
|
|
109
|
+
|
|
110
|
+
if (isGroupConversation) {
|
|
111
|
+
let senderName = '';
|
|
112
|
+
if (lastMessage?.fromAccount === TUIChatEngine.getMyUserID()) {
|
|
113
|
+
senderName = t('TUIConversation.me');
|
|
114
|
+
} else {
|
|
115
|
+
// Priority: friendRemark > nameCard > nick > userID
|
|
116
|
+
senderName = conversation.remark
|
|
117
|
+
|| typedLastMessage?.nameCard
|
|
118
|
+
|| lastMessage?.nick
|
|
119
|
+
|| lastMessage.fromAccount;
|
|
120
|
+
}
|
|
121
|
+
return senderName ? `${senderName}: ${messageContent}` : messageContent;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return messageContent;
|
|
55
125
|
};
|
|
@@ -64,7 +64,17 @@ export default {
|
|
|
64
64
|
'File': 'File',
|
|
65
65
|
'Custom': 'Custom',
|
|
66
66
|
'Location': 'Location',
|
|
67
|
-
'
|
|
67
|
+
'Face': 'Face',
|
|
68
68
|
'Chat History': 'Chat History',
|
|
69
|
+
'call_message': 'Call Message',
|
|
70
|
+
'unknown_message': 'Unknown Message',
|
|
71
|
+
'me': 'Me',
|
|
72
|
+
'recalled_a_message': 'recalled a message',
|
|
73
|
+
'you_have_been_removed_from_the_group': 'You have been removed from the group by the group administrator',
|
|
74
|
+
'the_group_chat_has_been_disbanded': 'The group chat has been disbanded',
|
|
75
|
+
'you_have_left_the_group_chat': 'You have left the group chat',
|
|
76
|
+
'someone_at_me': 'You were mentioned',
|
|
77
|
+
'at_all': '@All',
|
|
78
|
+
'group_id_already_used': 'The group ID for creating the group chat is already in use, please choose a different group ID.',
|
|
69
79
|
},
|
|
70
80
|
};
|
|
@@ -64,7 +64,17 @@ export default {
|
|
|
64
64
|
'File': '文件',
|
|
65
65
|
'Custom': '自定义消息',
|
|
66
66
|
'Location': '位置',
|
|
67
|
-
'
|
|
67
|
+
'Face': '动画表情',
|
|
68
68
|
'Chat History': '聊天记录',
|
|
69
|
+
'call_message': '通话消息',
|
|
70
|
+
'unknown_message': '消息',
|
|
71
|
+
'me': '我',
|
|
72
|
+
'recalled_a_message': '撤回了一条消息',
|
|
73
|
+
'you_have_been_removed_from_the_group': '你已被群管理员移出该群',
|
|
74
|
+
'the_group_chat_has_been_disbanded': '该群聊已解散',
|
|
75
|
+
'you_have_left_the_group_chat': '你已退出该群聊',
|
|
76
|
+
'someone_at_me': '有人@我',
|
|
77
|
+
'at_all': '@所有人',
|
|
78
|
+
'group_id_already_used': '当前创建群聊的群ID已被使用,请选择其他群ID',
|
|
69
79
|
},
|
|
70
80
|
};
|
|
@@ -16,60 +16,57 @@
|
|
|
16
16
|
<IconClose
|
|
17
17
|
:class="styles['quoted__message__preview__close']"
|
|
18
18
|
size="16"
|
|
19
|
-
@click="
|
|
19
|
+
@click="handleCloseQuotedMessage"
|
|
20
20
|
/>
|
|
21
21
|
</div>
|
|
22
22
|
</template>
|
|
23
23
|
|
|
24
24
|
<script setup lang="ts">
|
|
25
|
-
import { watch } from 'vue';
|
|
26
|
-
import TencentCloudChat from '@tencentcloud/chat';
|
|
25
|
+
import { watch, onUnmounted } from 'vue';
|
|
27
26
|
import { useUIKit, IconClose } from '@tencentcloud/uikit-base-component-vue3';
|
|
28
|
-
import { useConversationListState } from '../../../states/ConversationListState';
|
|
29
27
|
import { useMessageActionState } from '../../../states/MessageActionState';
|
|
30
28
|
import { useMessageInputState } from '../../../states/MessageInputState';
|
|
29
|
+
import { MessageType } from '../../../types/engine';
|
|
30
|
+
import { transformTextWithEmojiKeyToName } from '../../../utils';
|
|
31
31
|
import styles from './QuotedMessagePreview.module.scss';
|
|
32
|
-
import type {
|
|
32
|
+
import type { MessageModel } from '../../../types/engine';
|
|
33
33
|
|
|
34
34
|
const { t } = useUIKit();
|
|
35
|
-
const { activeConversation } = useConversationListState();
|
|
36
35
|
const { focusEditor } = useMessageInputState();
|
|
37
36
|
const { quotedMessage, clearQuotedMessage } = useMessageActionState();
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
onUnmounted(() => {
|
|
39
|
+
clearQuotedMessage();
|
|
40
|
+
});
|
|
41
|
+
|
|
40
42
|
watch(quotedMessage, (newVal) => {
|
|
41
43
|
if (newVal) {
|
|
42
44
|
focusEditor();
|
|
43
45
|
}
|
|
44
46
|
});
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
watch(activeConversation, () => {
|
|
48
|
-
clearQuotedMessage();
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
const handleClose = () => {
|
|
48
|
+
const handleCloseQuotedMessage = () => {
|
|
52
49
|
clearQuotedMessage();
|
|
53
50
|
};
|
|
54
51
|
|
|
55
|
-
const calculateReferenceContent = (message:
|
|
52
|
+
const calculateReferenceContent = (message: MessageModel | undefined): string => {
|
|
56
53
|
if (!message) {
|
|
57
54
|
return 'no reference';
|
|
58
55
|
}
|
|
59
56
|
switch (message.type) {
|
|
60
|
-
case
|
|
61
|
-
return message.payload?.text;
|
|
62
|
-
case
|
|
57
|
+
case MessageType.TEXT:
|
|
58
|
+
return transformTextWithEmojiKeyToName(message.payload?.text || '');
|
|
59
|
+
case MessageType.IMAGE:
|
|
63
60
|
return t('MessageInput.image');
|
|
64
|
-
case
|
|
61
|
+
case MessageType.AUDIO:
|
|
65
62
|
return t('MessageInput.audio');
|
|
66
|
-
case
|
|
63
|
+
case MessageType.VIDEO:
|
|
67
64
|
return t('MessageInput.video');
|
|
68
|
-
case
|
|
65
|
+
case MessageType.FILE:
|
|
69
66
|
return t('MessageInput.file');
|
|
70
|
-
case
|
|
67
|
+
case MessageType.LOCATION:
|
|
71
68
|
return t('MessageInput.location');
|
|
72
|
-
case
|
|
69
|
+
case MessageType.CUSTOM:
|
|
73
70
|
return t('MessageInput.custom_message');
|
|
74
71
|
default:
|
|
75
72
|
return t('MessageInput.unknown');
|
|
@@ -39,7 +39,9 @@
|
|
|
39
39
|
height: 20px;
|
|
40
40
|
user-select: text;
|
|
41
41
|
pointer-events: none;
|
|
42
|
+
vertical-align: bottom;
|
|
42
43
|
}
|
|
44
|
+
|
|
43
45
|
.message-image {
|
|
44
46
|
display: inline-block;
|
|
45
47
|
width: 100px;
|
|
@@ -57,3 +59,26 @@
|
|
|
57
59
|
pointer-events: none;
|
|
58
60
|
}
|
|
59
61
|
|
|
62
|
+
// Mention tag styles (Telegram-style)
|
|
63
|
+
.uikit-message-input-mention-tag {
|
|
64
|
+
display: inline;
|
|
65
|
+
padding: 2px 4px;
|
|
66
|
+
margin: 0 2px;
|
|
67
|
+
border-radius: 4px;
|
|
68
|
+
background-color: rgba(0, 122, 255, 0.1);
|
|
69
|
+
color: #007AFF;
|
|
70
|
+
font-weight: 500;
|
|
71
|
+
cursor: pointer;
|
|
72
|
+
user-select: none;
|
|
73
|
+
white-space: nowrap;
|
|
74
|
+
|
|
75
|
+
&:hover {
|
|
76
|
+
background-color: rgba(0, 122, 255, 0.15);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Selected state (when backspacing)
|
|
80
|
+
&.ProseMirror-selectednode {
|
|
81
|
+
background-color: rgba(0, 122, 255, 0.2);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
@@ -1,48 +1,72 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* EditorCore - Pure functional utilities for Tiptap editor
|
|
3
|
+
* Provides extension configuration and content conversion
|
|
4
|
+
*/
|
|
2
5
|
import Placeholder from '@tiptap/extension-placeholder';
|
|
3
6
|
import StarterKit from '@tiptap/starter-kit';
|
|
4
|
-
import { Extension, Editor } from '@tiptap/vue-3';
|
|
5
7
|
import { MessageContentType } from '../../../states/MessageInputState';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
+
import {
|
|
9
|
+
CharacterCount,
|
|
10
|
+
createEmojiExtension,
|
|
11
|
+
createEnterKeyExtension,
|
|
12
|
+
createImageExtension,
|
|
13
|
+
createMentionExtension,
|
|
14
|
+
} from './extensions';
|
|
8
15
|
import type { InputContent } from '../../../states/MessageInputState';
|
|
9
|
-
import type { JSONContent,
|
|
16
|
+
import type { JSONContent, Extensions } from '@tiptap/vue-3';
|
|
10
17
|
import './Editor.scss';
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
HTMLAttributes: {
|
|
22
|
-
class: 'message-emoji',
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
},
|
|
26
|
-
});
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Extension Configuration
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
interface ExtensionOptions {
|
|
24
|
+
placeholder?: string;
|
|
25
|
+
maxLength?: number;
|
|
26
|
+
showPlaceholderOnlyWhenEditable?: boolean;
|
|
27
|
+
onEnter?: () => void;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Create all editor extensions with given options
|
|
32
|
+
*/
|
|
33
|
+
function createExtensions(options: ExtensionOptions = {}): Extensions {
|
|
34
|
+
const {
|
|
35
|
+
placeholder = '',
|
|
36
|
+
maxLength,
|
|
37
|
+
showPlaceholderOnlyWhenEditable = true,
|
|
38
|
+
onEnter,
|
|
39
|
+
} = options;
|
|
40
|
+
|
|
41
|
+
return [
|
|
42
|
+
StarterKit.configure({
|
|
43
|
+
bold: false,
|
|
44
|
+
italic: false,
|
|
45
|
+
strike: false,
|
|
46
|
+
code: false,
|
|
47
|
+
}),
|
|
48
|
+
CharacterCount.configure({
|
|
49
|
+
limit: maxLength,
|
|
50
|
+
}),
|
|
51
|
+
createEnterKeyExtension(onEnter),
|
|
52
|
+
createEmojiExtension(),
|
|
53
|
+
createImageExtension(),
|
|
54
|
+
createMentionExtension(),
|
|
55
|
+
Placeholder.configure({
|
|
56
|
+
placeholder,
|
|
57
|
+
showOnlyWhenEditable: showPlaceholderOnlyWhenEditable,
|
|
58
|
+
}),
|
|
59
|
+
];
|
|
44
60
|
}
|
|
45
61
|
|
|
62
|
+
// ============================================================================
|
|
63
|
+
// Content Conversion
|
|
64
|
+
// ============================================================================
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Convert Tiptap JSON content to business InputContent array
|
|
68
|
+
* Uses simple switch-case for clarity (no over-engineered registry pattern)
|
|
69
|
+
*/
|
|
46
70
|
function convertEditorContent(node: JSONContent): InputContent[] {
|
|
47
71
|
if (!node?.content) {
|
|
48
72
|
return [];
|
|
@@ -57,11 +81,13 @@ function convertEditorContent(node: JSONContent): InputContent[] {
|
|
|
57
81
|
content: child.text,
|
|
58
82
|
}]
|
|
59
83
|
: [];
|
|
84
|
+
|
|
60
85
|
case 'image':
|
|
61
86
|
return [{
|
|
62
87
|
type: MessageContentType.IMAGE,
|
|
63
88
|
content: child.attrs?.fileData,
|
|
64
89
|
}];
|
|
90
|
+
|
|
65
91
|
case 'emoji':
|
|
66
92
|
return [{
|
|
67
93
|
type: MessageContentType.EMOJI,
|
|
@@ -71,81 +97,35 @@ function convertEditorContent(node: JSONContent): InputContent[] {
|
|
|
71
97
|
text: child.attrs?.title,
|
|
72
98
|
},
|
|
73
99
|
}];
|
|
100
|
+
|
|
74
101
|
case 'hardBreak':
|
|
75
102
|
return [{
|
|
76
103
|
type: MessageContentType.TEXT,
|
|
77
104
|
content: '\n',
|
|
78
105
|
}];
|
|
106
|
+
|
|
107
|
+
case 'mention':
|
|
108
|
+
return [{
|
|
109
|
+
type: MessageContentType.MENTION,
|
|
110
|
+
content: {
|
|
111
|
+
id: child.attrs?.id,
|
|
112
|
+
label: child.attrs?.label,
|
|
113
|
+
mentionSuggestionChar: child.attrs?.mentionSuggestionChar,
|
|
114
|
+
},
|
|
115
|
+
}];
|
|
116
|
+
|
|
79
117
|
default:
|
|
118
|
+
// Recursively handle nested content (e.g., paragraph nodes)
|
|
80
119
|
return convertEditorContent(child);
|
|
81
120
|
}
|
|
82
121
|
});
|
|
83
122
|
}
|
|
84
123
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
autoFocus?: boolean;
|
|
89
|
-
disabled?: boolean;
|
|
90
|
-
maxLength?: number;
|
|
91
|
-
isPlaceholderOnlyShowWhenEditable?: boolean;
|
|
92
|
-
onUpdate?: (content: InputContent[]) => void;
|
|
93
|
-
onEnter?: () => void;
|
|
94
|
-
onFocus?: () => void;
|
|
95
|
-
onBlur?: () => void;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function createEditor({
|
|
99
|
-
element,
|
|
100
|
-
placeholder = '',
|
|
101
|
-
autoFocus = false,
|
|
102
|
-
disabled = false,
|
|
103
|
-
isPlaceholderOnlyShowWhenEditable = true,
|
|
104
|
-
maxLength = undefined,
|
|
105
|
-
onUpdate,
|
|
106
|
-
onEnter,
|
|
107
|
-
onFocus,
|
|
108
|
-
onBlur,
|
|
109
|
-
}: EditorOptions) {
|
|
110
|
-
const createBaseExtensions = (enterHandler?: () => void) => [
|
|
111
|
-
StarterKit.configure({
|
|
112
|
-
bold: false,
|
|
113
|
-
italic: false,
|
|
114
|
-
strike: false,
|
|
115
|
-
code: false,
|
|
116
|
-
}),
|
|
117
|
-
CharacterCount.configure({
|
|
118
|
-
limit: maxLength,
|
|
119
|
-
}),
|
|
120
|
-
createEnterKeyExtension(enterHandler ? { onEnter: enterHandler } : undefined),
|
|
121
|
-
createEmojiExtension(),
|
|
122
|
-
createImageExtension(),
|
|
123
|
-
Placeholder.configure({
|
|
124
|
-
placeholder,
|
|
125
|
-
showOnlyWhenEditable: isPlaceholderOnlyShowWhenEditable,
|
|
126
|
-
}),
|
|
127
|
-
];
|
|
128
|
-
|
|
129
|
-
const editorConfig: Partial<TiptapEditorOptions> = {
|
|
130
|
-
element,
|
|
131
|
-
autofocus: autoFocus,
|
|
132
|
-
editable: !disabled,
|
|
133
|
-
extensions: createBaseExtensions(onEnter),
|
|
134
|
-
onUpdate: ({ editor }) => {
|
|
135
|
-
const content = convertEditorContent(editor.getJSON());
|
|
136
|
-
onUpdate?.(content);
|
|
137
|
-
},
|
|
138
|
-
onFocus,
|
|
139
|
-
onBlur,
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
return new Editor(editorConfig);
|
|
143
|
-
}
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// Exports
|
|
126
|
+
// ============================================================================
|
|
144
127
|
|
|
145
128
|
export {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
export type {
|
|
150
|
-
Editor,
|
|
129
|
+
createExtensions,
|
|
130
|
+
convertEditorContent,
|
|
151
131
|
};
|