diff --git a/src/TUIKit/CHANGELOG.md b/src/TUIKit/CHANGELOG.md new file mode 100644 index 0000000..29031f6 --- /dev/null +++ b/src/TUIKit/CHANGELOG.md @@ -0,0 +1,208 @@ +## [2.4.0] (2025-01-16) + +### Fix +- 修复 sendMessage 时携带的默认信息,支持用户自定义配置。 + +## [2.3.8] (2025-01-10) + +### Features +- 支持文本消息 url 高亮跳转 + +## Fix +- 修复自定义大表情失效问题 +- 修复 login 时好友列表数据未重置问题 + +## [2.3.6] (2024-12-06) + +### Fix +- 修复 marked 依赖丢失 ts 类型声明 + +## [2.3.5] (2024-12-06) + +### Features +- 支持消息 markdown 展示 +- 支持消息流式输出效果 + +## Fix +- 修复 Toast 失效问题 + +## [2.3.3] (2024-10-28) + +### Features +- 支持群组禁言后发送消息错误提示国际化 + +## Fix +- 修复集成 CallKit 点击通话按钮偶现无响应问题 + +## [2.3.2] (2024-10-28) + +## Fix +- 修复群聊中群管理入口偶现的丢失问题 + +## [2.3.1] (2024-10-25) + +## Fix +- 修复 H5 安全区遮挡问题 +- 修复 H5 键盘遮挡输入框问题 +- 修复撤回消息中撤回人为空问题 +- 修复 TUIContact 修改好友备注后列表显示未更新问题 + +## [2.2.9] (2024-10-17) + +## Fix +- 修复 Callkit 融合被叫超时无应答英文词条翻译错误问题 + +## [2.2.8] (2024-09-24) + +### Features +- 支持繁体中文语言 +- 支持新增自定义语言类型 + +## Fix +- 修复 MessageInput 内容中间回车发送消息引入换行问题 + +## [2.2.7] (2024-09-13) + +### Features +- 优化 C2C 会话音视频通话信令上屏(对齐微信体验) + +## [2.2.6] (2024-09-06) + +### Features +- Work 类型群组支持普通群成员修改群名称、群公告信息 + +## [2.2.3] (2024-07-05) + +### Features +- 支持会话草稿 +- 支持富文本复制 +- 支持文本部分复制 +- 语音消息使用红点提示是否播放 + +## Fix +- 修复邀请加入群聊选人组件未过滤已有群成员问题 +- 修复 TUISearch 搜索文本消息出现 [系统消息] 前缀问题 +- 修复消息引用语音但展示为"聊天记录"的问题 +- 修复 Callkit 在 H5 环境下布局只有半屏的问题 + +## [2.2.0] (2024-06-17) + +### Features +- 支持消息多选、消息逐条转发、消息合并转发 +- 支持表情包自定义 +- 支持中英文 github readme +- 被引用消息撤回时隐藏原始消息内容并提醒已撤回 + +## [2.1.4] (2024-05-20) + +### Fix +- 修复头像组件因加载图片失败导致的循环加载问题 + +## [2.1.3] (2024-05-17) + +### Features +- 点击空白区域时收起小表情面板和工具栏 +- callkit 提供音视频通话中途加人能力 +- 更新 roomkit 引用方式 + +### Fix + +- 修复视频一定概率无法播放的问题 +- 修复消息引用的视觉左侧未对齐的问题 + +## [2.1.1] (2024-04-26) + +### Features +- 支持语音转文字 +- 文本消息转翻译兼容小表情上屏,兼容提及所有人 + +### Fix +- 优化已读回执详情列表超长昵称的显示效果 +- 解决转发消息已读回执失效的问题 +- 解决加没有群申请时额外请求用户信息的问题 + +## [2.1.0] (2024-04-12) + +### Features +- 新增消息翻译功能 + +## [2.0.9] (2024-03-29) + +### Features +- ScrollButton 支持未读新消息提示 +- 群未决申请展示优化 +- 兼容支持 H5 IOS longPress 事件 + +### Update +- 下线本地审核相关入口 + +### Fix +- 修复 nick 过长样式溢出问题 + +## [2.0.8] (2024-03-15) + +### Fix +- 修复已知问题,提升稳定性 + +## [2.0.7] (2024-03-15) + +### Fix +- TUIConversation network 断网显示优化 +- 修复消息列表滚动到顶部后"回到底部"按钮消失的问题 +- 修复一定概率下消息列表为空的问题 + +## [2.0.6] (2024-03-01) + +### Features + +- 升级 universal api 引入方式 + +## [2.0.5] (2024-02-04) + +### Features + +- 新增表情回复功能(需购买旗舰版) +- 聊天界面更新黄脸小表情 +- 添加音频播放动画 + +### Fix + +- 语音场景优化 修复了语音播放相关的体验问题 + +## [2.0.4] (2024-01-19) + +### Features + +- 支持文本消息复制 + +## [2.0.3] (2024-01-12) + +### Features + +- TUIContact 关系链支持用户在线状态。 +- TUIContact 中获取客服列表的时机调整为 Engine 设置商业化能力位之后。 + +### Fix + +- 修复已知问题,提升稳定性 + +## [2.0.2] (2024-01-05) + +### Fix + +- 修复 IOS13 消息无法发送问题 +- 修复已知问题,提升稳定性 + +## [2.0.0] (2023-12-21) + +### Features + +- 全面支持 Vue2 & Vue3,包括以下主体功能: + - TUIChat: 负责消息界面展示,包括多类型消息收发,消息引用/删除/撤回/转发、查询消息已读回执详情等功能。 + - TUIConversation: 负责会话列表的展示和编辑,包括会话置顶、会话消息免打扰、会话删除等功能. + - TUISearch: 负责消息云端搜索,包括全局搜索与会话内搜索,支持文本、图片、文件等多类型消息混合搜索,支持搜索时间范围选择与搜索结果定位,免费试用请点击 https://cloud.tencent.com/document/product/269/92648#ae4e3f5c-94db-4df3-8a49-65d23ce417b8 开通。 + - TUIGroup: 负责群聊的创建以及群资料、群成员、群组权限、群公告、群禁言的管理。 + - TUIContact: 负责联系人与群组展示,添加好友,移入黑名单,好友备注,信息展示等功能。 +- 同时,我们还提供了功能丰富的插件系统: + - TUICustomerService: 在线客服插件,支持灵活的路由排队、客服接待、智能机器人功能,配合功能丰富的管理端与数据分析能力,支持客服多终端办公,免费试用请点击 https://cloud.tencent.com/document/product/269/92648#ae4e3f5c-94db-4df3-8a49-65d23ce417b8 开通。 + - TUICallKit: 音视频通话 UI 组件,支持两人或多人进行音视频通话,覆盖游戏社交、在线客服、视频客服、在线问诊、保险咨询等场景,免费试用请点击 https://cloud.tencent.com/document/product/269/79861#step1 开通。 diff --git a/src/TUIKit/README.md b/src/TUIKit/README.md new file mode 100644 index 0000000..febcbf9 --- /dev/null +++ b/src/TUIKit/README.md @@ -0,0 +1,94 @@ +

chat-uikit-vue

+

+ Globally interconnected In-App Chat, user profile and relationship chains and online/offline push. +

+

+ English / + 简体中文 +

+ +![image](https://github.com/TencentCloud/chat-uikit-vue/assets/57951148/7bd24604-1e5e-4541-8992-245dccbbc810) +![image](https://github.com/TencentCloud/chat-uikit-vue/assets/57951148/40ae2f49-39ae-432d-8d1b-5b46414bc3b4) + +## About chat-uikit-vue + +[chat-uikit-vue](https://www.npmjs.com/package/@tencentcloud/chat-uikit-vue) is a Vue UI component library based on Tencent Cloud Chat SDK. It provides universally used UI components that include Conversation, Chat, and Group components. Leveraging these meticulously crafted UI components, you can quickly construct an elegant, reliable, and scalable Chat application. + +> In respect for the copyright of the emoji design, the Chat Demo/TUIKit project does not include the cutouts of large emoji elements. Please replace them with your own designed or copyrighted emoji packs before the official launch for commercial use. The default small yellow face emoji pack is copyrighted by Tencent Cloud and can be authorized for a fee. If you wish to obtain authorization, please [submit a ticket](https://console.tencentcloud.com/workorder/category?level1_id=29&level2_id=40&source=14&data_title=Chat&step=1) to contact us. + + +## Core Capabilities + +- UIKit: Build a fully-featured chat app in just ten minutes using UIKit components +- Various Message Types: Support multiple message types, such as text, images, audio, and video messages +- Notifications: Timely notify users of app messages and drive higher conversion rates +- Group Management: Create groups, manage group members, and customize profiles +- Conversation Management: View information about unread messages, recent, pinned, or deleted chats + +## Demo + +👉🏻 [Free Demo](https://web.sdk.qcloud.com/im/demo/intl/index.html?scene=social) + +## Send Your First Message + +### Vue3 +- [Integration TUIKit](https://trtc.io/document/58644?platform=web&product=chat) +- [Quick Run Demo](https://github.com/TencentCloud/chat-uikit-vue/blob/main/Vue3/Demo/README.md) + +### Vue2 +- [Integration TUIKit](https://trtc.io/document/58644?platform=web&product=chat) +- [Quick Run Demo](https://github.com/TencentCloud/chat-uikit-vue/blob/main/Vue2/Demo/README.md) + + +## TUILogin + +``` javascript +import { TUILogin } from '@tencentcloud/tui-core'; +``` +The options parameter is of the Object type. It contains the following attribute values: +| Name | Type | Description | +| --- | --- | --- | +| SDKAppID | number | Required, SDKAppID of the chat app | +| userID | string | Required, user ID| +| userSig |string | Required, the password with which the user logs in to the Chat console. It is essentially the ciphertext generated by encrypting information such as the UserID.For the detailed generation method, see [Generating UserSig](https://trtc.io/document/34385) | +| TIMPush | any | Optional, TIMPush plugin instance when uniapp build app packages | +| pushConfig | object | Optional, TIMPush plugin's config | +| useUploadPlugin | boolean | Optional, whether to use the upload plugin, the default is false | +| proxyServer | string | Optional, WebSocket server proxy address | +| fileUploadProxy | string | Optional, image, video, file upload proxy address | +| fileDownloadProxy | string | Optional, image, video, file download proxy address| +| framework | string \| undefined | Required, UI framework type, optional values: vue2、vue3、undefined | + +``` javascript +// Login +TUILogin.login(options); +``` + +``` javascript +// Logout +TUILogin.logout(); +``` + +``` javascript +// Set the SDK log level. +// 0: Common level. You are advised to use this level during access as it covers more logs. +// 1: Release level. You are advised to use this level for key information in a production environment. +TUILogin.setLogLevel(0); +``` + +``` javascript +// Get Chat SDK instance +const { chat } = TUILogin.getContext(); +``` + +## Documentation +- [Home page](https://trtc.io/document/50061?platform=web&product=chat) +- [@tencentcloud/chat-uikit-vue npm](https://www.npmjs.com/package/@tencentcloud/chat-uikit-vue) +- [Chat SDK](https://trtc.io/document/34309?platform=web&product=chat) + +## Contact Us +Join a Tencent Cloud Chat developer group for Reliable technical support & Product details & Constant exchange of ideas. +- Telegram group (EN): [join](https://t.me/+1doS9AUBmndhNGNl) +- WhatsApp group (EN): [join](https://chat.whatsapp.com/Gfbxk7rQBqc8Rz4pzzP27A) +- Telegram group (ZH): [join](https://t.me/tencent_imsdk) +- WhatsApp group (ZH): [join](https://chat.whatsapp.com/IVa11ZkVmKTEwSWsAzSyik) diff --git a/src/TUIKit/adapter-vue.ts b/src/TUIKit/adapter-vue.ts new file mode 100644 index 0000000..222b95e --- /dev/null +++ b/src/TUIKit/adapter-vue.ts @@ -0,0 +1,51 @@ +import * as Vue from 'vue'; +import { TUIGlobal } from '@tencentcloud/universal-api'; + +let vueVersion: number; +let framework = 'vue2'; +let createVNode = ( + arg1: any, + arg2: any, +): { component: any; props: any; data: any } => { + return {} as { component: any; props: any; data: any }; +}; +let render = (arg1: any, arg2: any) => { + return; +}; + +try { + if ( + (Vue as any)?.default?.version + && (Vue as any)?.default?.version?.startsWith('2.7.') + ) { + // >= Vue 2.7.0 + vueVersion = 2.7; + TUIGlobal.Vue = (Vue as any)?.getCurrentInstance()?.appContext?.app; + } else if ( + (Vue as any)?.default?.version + && (Vue as any)?.default?.version?.startsWith('2.') + ) { + // < Vue 2.7.0 + vueVersion = 2; + TUIGlobal.Vue = (Vue as any).default; + } else { + // >= Vue 3.0.0 + vueVersion = 3; + framework = 'vue3'; + createVNode = (Vue as any)?.createVNode; + render = (Vue as any)?.render; + TUIGlobal.Vue = (Vue as any)?.getCurrentInstance()?.appContext?.app; + // exportedAPIOrigin = Vue; + } +} catch (error: any) { + // >= Vue 3.0.0 + vueVersion = 3; + framework = 'vue3'; + createVNode = (Vue as any)?.createVNode; + render = (Vue as any)?.render; + TUIGlobal.Vue = (Vue as any)?.getCurrentInstance()?.appContext?.app; +} +console.warn(`[adapter-vue]: vue version is ${vueVersion}`); +export { vueVersion, framework, render, createVNode }; + +export * from 'vue'; diff --git a/src/TUIKit/assets/icon/add-circle.svg b/src/TUIKit/assets/icon/add-circle.svg new file mode 100644 index 0000000..aa90800 --- /dev/null +++ b/src/TUIKit/assets/icon/add-circle.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/TUIKit/assets/icon/add.svg b/src/TUIKit/assets/icon/add.svg new file mode 100644 index 0000000..f154f34 --- /dev/null +++ b/src/TUIKit/assets/icon/add.svg @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/at.svg b/src/TUIKit/assets/icon/at.svg new file mode 100644 index 0000000..e26825a --- /dev/null +++ b/src/TUIKit/assets/icon/at.svg @@ -0,0 +1,12 @@ + + + 画板 + + + + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/audio.svg b/src/TUIKit/assets/icon/audio.svg new file mode 100644 index 0000000..deacede --- /dev/null +++ b/src/TUIKit/assets/icon/audio.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/TUIKit/assets/icon/back.svg b/src/TUIKit/assets/icon/back.svg new file mode 100644 index 0000000..0af55aa --- /dev/null +++ b/src/TUIKit/assets/icon/back.svg @@ -0,0 +1,16 @@ + + + ic_back_white + + + + + + + + + + + + + diff --git a/src/TUIKit/assets/icon/call-video.svg b/src/TUIKit/assets/icon/call-video.svg new file mode 100644 index 0000000..dc76641 --- /dev/null +++ b/src/TUIKit/assets/icon/call-video.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/call-voice.svg b/src/TUIKit/assets/icon/call-voice.svg new file mode 100644 index 0000000..4793fcf --- /dev/null +++ b/src/TUIKit/assets/icon/call-voice.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/call.png b/src/TUIKit/assets/icon/call.png new file mode 100644 index 0000000..d8d86fe Binary files /dev/null and b/src/TUIKit/assets/icon/call.png differ diff --git a/src/TUIKit/assets/icon/camera-uni.png b/src/TUIKit/assets/icon/camera-uni.png new file mode 100644 index 0000000..5596ae2 Binary files /dev/null and b/src/TUIKit/assets/icon/camera-uni.png differ diff --git a/src/TUIKit/assets/icon/cancel.svg b/src/TUIKit/assets/icon/cancel.svg new file mode 100644 index 0000000..1cf848b --- /dev/null +++ b/src/TUIKit/assets/icon/cancel.svg @@ -0,0 +1,23 @@ + + + 清除 + + + + + + + + + + + + + + + + + + + + diff --git a/src/TUIKit/assets/icon/check-sm.svg b/src/TUIKit/assets/icon/check-sm.svg new file mode 100644 index 0000000..69a5e1c --- /dev/null +++ b/src/TUIKit/assets/icon/check-sm.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/TUIKit/assets/icon/close-dark.svg b/src/TUIKit/assets/icon/close-dark.svg new file mode 100644 index 0000000..cfc8bc0 --- /dev/null +++ b/src/TUIKit/assets/icon/close-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/TUIKit/assets/icon/close-image.png b/src/TUIKit/assets/icon/close-image.png new file mode 100644 index 0000000..d6cc434 Binary files /dev/null and b/src/TUIKit/assets/icon/close-image.png differ diff --git a/src/TUIKit/assets/icon/convertText_en.svg b/src/TUIKit/assets/icon/convertText_en.svg new file mode 100644 index 0000000..6a8dd65 --- /dev/null +++ b/src/TUIKit/assets/icon/convertText_en.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/TUIKit/assets/icon/convertText_zh.svg b/src/TUIKit/assets/icon/convertText_zh.svg new file mode 100644 index 0000000..ef2c643 --- /dev/null +++ b/src/TUIKit/assets/icon/convertText_zh.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/TUIKit/assets/icon/d-left-arrow.svg b/src/TUIKit/assets/icon/d-left-arrow.svg new file mode 100644 index 0000000..24d5759 --- /dev/null +++ b/src/TUIKit/assets/icon/d-left-arrow.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/d-right-arrow.svg b/src/TUIKit/assets/icon/d-right-arrow.svg new file mode 100644 index 0000000..6fca7c5 --- /dev/null +++ b/src/TUIKit/assets/icon/d-right-arrow.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/del-icon.svg b/src/TUIKit/assets/icon/del-icon.svg new file mode 100644 index 0000000..b2832c0 --- /dev/null +++ b/src/TUIKit/assets/icon/del-icon.svg @@ -0,0 +1,25 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/double-arrow.svg b/src/TUIKit/assets/icon/double-arrow.svg new file mode 100644 index 0000000..0496fda --- /dev/null +++ b/src/TUIKit/assets/icon/double-arrow.svg @@ -0,0 +1 @@ + diff --git a/src/TUIKit/assets/icon/down-icon.svg b/src/TUIKit/assets/icon/down-icon.svg new file mode 100644 index 0000000..a921e8e --- /dev/null +++ b/src/TUIKit/assets/icon/down-icon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/downaload-image.png b/src/TUIKit/assets/icon/downaload-image.png new file mode 100644 index 0000000..498d63a Binary files /dev/null and b/src/TUIKit/assets/icon/downaload-image.png differ diff --git a/src/TUIKit/assets/icon/download.svg b/src/TUIKit/assets/icon/download.svg new file mode 100644 index 0000000..9d49c85 --- /dev/null +++ b/src/TUIKit/assets/icon/download.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/edit.svg b/src/TUIKit/assets/icon/edit.svg new file mode 100644 index 0000000..2ad307e --- /dev/null +++ b/src/TUIKit/assets/icon/edit.svg @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/evalute-dark.svg b/src/TUIKit/assets/icon/evalute-dark.svg new file mode 100644 index 0000000..b9833be --- /dev/null +++ b/src/TUIKit/assets/icon/evalute-dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/TUIKit/assets/icon/evalute-light.svg b/src/TUIKit/assets/icon/evalute-light.svg new file mode 100644 index 0000000..7cd651b --- /dev/null +++ b/src/TUIKit/assets/icon/evalute-light.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/face-dark.svg b/src/TUIKit/assets/icon/face-dark.svg new file mode 100644 index 0000000..fcbe3ad --- /dev/null +++ b/src/TUIKit/assets/icon/face-dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/TUIKit/assets/icon/face-light.svg b/src/TUIKit/assets/icon/face-light.svg new file mode 100644 index 0000000..98bf563 --- /dev/null +++ b/src/TUIKit/assets/icon/face-light.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/face-uni.png b/src/TUIKit/assets/icon/face-uni.png new file mode 100644 index 0000000..9321487 Binary files /dev/null and b/src/TUIKit/assets/icon/face-uni.png differ diff --git a/src/TUIKit/assets/icon/file-dark.svg b/src/TUIKit/assets/icon/file-dark.svg new file mode 100644 index 0000000..c5d0773 --- /dev/null +++ b/src/TUIKit/assets/icon/file-dark.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/src/TUIKit/assets/icon/file-light.svg b/src/TUIKit/assets/icon/file-light.svg new file mode 100644 index 0000000..a3acf0c --- /dev/null +++ b/src/TUIKit/assets/icon/file-light.svg @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/forward-each.svg b/src/TUIKit/assets/icon/forward-each.svg new file mode 100644 index 0000000..41599b4 --- /dev/null +++ b/src/TUIKit/assets/icon/forward-each.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/TUIKit/assets/icon/forward-merge.svg b/src/TUIKit/assets/icon/forward-merge.svg new file mode 100644 index 0000000..7a8588a --- /dev/null +++ b/src/TUIKit/assets/icon/forward-merge.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/TUIKit/assets/icon/icon-arrow-left.svg b/src/TUIKit/assets/icon/icon-arrow-left.svg new file mode 100644 index 0000000..97d4c98 --- /dev/null +++ b/src/TUIKit/assets/icon/icon-arrow-left.svg @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/icon-c2c.svg b/src/TUIKit/assets/icon/icon-c2c.svg new file mode 100644 index 0000000..e33ef15 --- /dev/null +++ b/src/TUIKit/assets/icon/icon-c2c.svg @@ -0,0 +1,36 @@ + + + 编组 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TUIKit/assets/icon/icon-close.svg b/src/TUIKit/assets/icon/icon-close.svg new file mode 100644 index 0000000..f5f3e04 --- /dev/null +++ b/src/TUIKit/assets/icon/icon-close.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/image-dark.svg b/src/TUIKit/assets/icon/image-dark.svg new file mode 100644 index 0000000..6a122ae --- /dev/null +++ b/src/TUIKit/assets/icon/image-dark.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/TUIKit/assets/icon/image-light.svg b/src/TUIKit/assets/icon/image-light.svg new file mode 100644 index 0000000..1088ed6 --- /dev/null +++ b/src/TUIKit/assets/icon/image-light.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/image-uni.png b/src/TUIKit/assets/icon/image-uni.png new file mode 100644 index 0000000..7d12d84 Binary files /dev/null and b/src/TUIKit/assets/icon/image-uni.png differ diff --git a/src/TUIKit/assets/icon/input-close.svg b/src/TUIKit/assets/icon/input-close.svg new file mode 100644 index 0000000..b224ddd --- /dev/null +++ b/src/TUIKit/assets/icon/input-close.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/TUIKit/assets/icon/left-arrow.svg b/src/TUIKit/assets/icon/left-arrow.svg new file mode 100644 index 0000000..2be419f --- /dev/null +++ b/src/TUIKit/assets/icon/left-arrow.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/loading.gif b/src/TUIKit/assets/icon/loading.gif new file mode 100644 index 0000000..be7c806 Binary files /dev/null and b/src/TUIKit/assets/icon/loading.gif differ diff --git a/src/TUIKit/assets/icon/loading.png b/src/TUIKit/assets/icon/loading.png new file mode 100644 index 0000000..6adfca7 Binary files /dev/null and b/src/TUIKit/assets/icon/loading.png differ diff --git a/src/TUIKit/assets/icon/minus.svg b/src/TUIKit/assets/icon/minus.svg new file mode 100644 index 0000000..b92ab01 --- /dev/null +++ b/src/TUIKit/assets/icon/minus.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/more-uni.png b/src/TUIKit/assets/icon/more-uni.png new file mode 100644 index 0000000..8376db2 Binary files /dev/null and b/src/TUIKit/assets/icon/more-uni.png differ diff --git a/src/TUIKit/assets/icon/more.png b/src/TUIKit/assets/icon/more.png new file mode 100644 index 0000000..d91bb0a Binary files /dev/null and b/src/TUIKit/assets/icon/more.png differ diff --git a/src/TUIKit/assets/icon/msg-audio.svg b/src/TUIKit/assets/icon/msg-audio.svg new file mode 100644 index 0000000..f2315fd --- /dev/null +++ b/src/TUIKit/assets/icon/msg-audio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/msg-copy.svg b/src/TUIKit/assets/icon/msg-copy.svg new file mode 100644 index 0000000..a5ed589 --- /dev/null +++ b/src/TUIKit/assets/icon/msg-copy.svg @@ -0,0 +1,30 @@ + + + 编组 14 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TUIKit/assets/icon/msg-del.svg b/src/TUIKit/assets/icon/msg-del.svg new file mode 100644 index 0000000..2d01337 --- /dev/null +++ b/src/TUIKit/assets/icon/msg-del.svg @@ -0,0 +1,33 @@ + + + 矩形 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TUIKit/assets/icon/msg-forward.svg b/src/TUIKit/assets/icon/msg-forward.svg new file mode 100644 index 0000000..172bfb5 --- /dev/null +++ b/src/TUIKit/assets/icon/msg-forward.svg @@ -0,0 +1,31 @@ + + + 编组 + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TUIKit/assets/icon/msg-quote.svg b/src/TUIKit/assets/icon/msg-quote.svg new file mode 100644 index 0000000..d533271 --- /dev/null +++ b/src/TUIKit/assets/icon/msg-quote.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/TUIKit/assets/icon/msg-revoke.svg b/src/TUIKit/assets/icon/msg-revoke.svg new file mode 100644 index 0000000..d3494f7 --- /dev/null +++ b/src/TUIKit/assets/icon/msg-revoke.svg @@ -0,0 +1,29 @@ + + + 矩形 + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TUIKit/assets/icon/multiple-select.svg b/src/TUIKit/assets/icon/multiple-select.svg new file mode 100644 index 0000000..d4da3c5 --- /dev/null +++ b/src/TUIKit/assets/icon/multiple-select.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/TUIKit/assets/icon/mute.svg b/src/TUIKit/assets/icon/mute.svg new file mode 100644 index 0000000..59a5f07 --- /dev/null +++ b/src/TUIKit/assets/icon/mute.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/TUIKit/assets/icon/plus.svg b/src/TUIKit/assets/icon/plus.svg new file mode 100644 index 0000000..2ccfad2 --- /dev/null +++ b/src/TUIKit/assets/icon/plus.svg @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/radio.svg b/src/TUIKit/assets/icon/radio.svg new file mode 100644 index 0000000..bb4f31b --- /dev/null +++ b/src/TUIKit/assets/icon/radio.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/TUIKit/assets/icon/right-arrow.svg b/src/TUIKit/assets/icon/right-arrow.svg new file mode 100644 index 0000000..3dc5700 --- /dev/null +++ b/src/TUIKit/assets/icon/right-arrow.svg @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/right-icon.svg b/src/TUIKit/assets/icon/right-icon.svg new file mode 100644 index 0000000..c90c2fd --- /dev/null +++ b/src/TUIKit/assets/icon/right-icon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/rotate-left.svg b/src/TUIKit/assets/icon/rotate-left.svg new file mode 100644 index 0000000..1a3c875 --- /dev/null +++ b/src/TUIKit/assets/icon/rotate-left.svg @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/rotate-right.svg b/src/TUIKit/assets/icon/rotate-right.svg new file mode 100644 index 0000000..7ab04ab --- /dev/null +++ b/src/TUIKit/assets/icon/rotate-right.svg @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/search-default.svg b/src/TUIKit/assets/icon/search-default.svg new file mode 100644 index 0000000..16607cb --- /dev/null +++ b/src/TUIKit/assets/icon/search-default.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TUIKit/assets/icon/search-more.svg b/src/TUIKit/assets/icon/search-more.svg new file mode 100644 index 0000000..af3e11c --- /dev/null +++ b/src/TUIKit/assets/icon/search-more.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/TUIKit/assets/icon/search.svg b/src/TUIKit/assets/icon/search.svg new file mode 100644 index 0000000..d64b94f --- /dev/null +++ b/src/TUIKit/assets/icon/search.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/TUIKit/assets/icon/selected.svg b/src/TUIKit/assets/icon/selected.svg new file mode 100644 index 0000000..7fd5bd3 --- /dev/null +++ b/src/TUIKit/assets/icon/selected.svg @@ -0,0 +1,27 @@ + + + 编组 14 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TUIKit/assets/icon/setting.svg b/src/TUIKit/assets/icon/setting.svg new file mode 100644 index 0000000..ebda9dc --- /dev/null +++ b/src/TUIKit/assets/icon/setting.svg @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/star-light.png b/src/TUIKit/assets/icon/star-light.png new file mode 100644 index 0000000..77c9e32 Binary files /dev/null and b/src/TUIKit/assets/icon/star-light.png differ diff --git a/src/TUIKit/assets/icon/star.png b/src/TUIKit/assets/icon/star.png new file mode 100644 index 0000000..821c83f Binary files /dev/null and b/src/TUIKit/assets/icon/star.png differ diff --git a/src/TUIKit/assets/icon/start-group.svg b/src/TUIKit/assets/icon/start-group.svg new file mode 100644 index 0000000..6fd02f8 --- /dev/null +++ b/src/TUIKit/assets/icon/start-group.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/translate.svg b/src/TUIKit/assets/icon/translate.svg new file mode 100644 index 0000000..8b7ae24 --- /dev/null +++ b/src/TUIKit/assets/icon/translate.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/TUIKit/assets/icon/video-dark.svg b/src/TUIKit/assets/icon/video-dark.svg new file mode 100644 index 0000000..1828560 --- /dev/null +++ b/src/TUIKit/assets/icon/video-dark.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/src/TUIKit/assets/icon/video-light.svg b/src/TUIKit/assets/icon/video-light.svg new file mode 100644 index 0000000..d991510 --- /dev/null +++ b/src/TUIKit/assets/icon/video-light.svg @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/video-play.png b/src/TUIKit/assets/icon/video-play.png new file mode 100644 index 0000000..15957a9 Binary files /dev/null and b/src/TUIKit/assets/icon/video-play.png differ diff --git a/src/TUIKit/assets/icon/video-uni.png b/src/TUIKit/assets/icon/video-uni.png new file mode 100644 index 0000000..2cfe433 Binary files /dev/null and b/src/TUIKit/assets/icon/video-uni.png differ diff --git a/src/TUIKit/assets/icon/words-dark.svg b/src/TUIKit/assets/icon/words-dark.svg new file mode 100644 index 0000000..c8f6c89 --- /dev/null +++ b/src/TUIKit/assets/icon/words-dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/TUIKit/assets/icon/words-light.svg b/src/TUIKit/assets/icon/words-light.svg new file mode 100644 index 0000000..934bcda --- /dev/null +++ b/src/TUIKit/assets/icon/words-light.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/zoom-in.svg b/src/TUIKit/assets/icon/zoom-in.svg new file mode 100644 index 0000000..d861ab7 --- /dev/null +++ b/src/TUIKit/assets/icon/zoom-in.svg @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/icon/zoom-out.svg b/src/TUIKit/assets/icon/zoom-out.svg new file mode 100644 index 0000000..890cf9f --- /dev/null +++ b/src/TUIKit/assets/icon/zoom-out.svg @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/src/TUIKit/assets/styles/common.scss b/src/TUIKit/assets/styles/common.scss new file mode 100644 index 0000000..da48298 --- /dev/null +++ b/src/TUIKit/assets/styles/common.scss @@ -0,0 +1,59 @@ +body, div, ul, ol, dt, dd, li, dl, h1, h2, h3, h4, p { + margin:0; + padding:0; + font-style:normal; + + /* font:12px/22px"\5B8B\4F53",Arial,Helvetica,sans-serif; */ +} + +ol, ul, li { + list-style:none; +} + +img { + border:0; + vertical-align:middle; + pointer-events:none; +} + +body { + color:#000; + background:#FFF; +} + +.clear { + clear:both; + height:1px; + width:100%; + overflow:hidden; + margin-top:-1px; +} + +a { + color:#000; + text-decoration:none; + cursor: pointer; +} + +a:hover { + text-decoration:none; +} + +input, textarea { + user-select: auto; +} + +input:focus, input:active, textarea:focus, textarea:active { + outline: none; +} + +.chat-aside { + position: absolute; + top: 50px; + right: 0; + box-sizing: border-box; + width: 360px !important; + border-radius: 8px 0 0 8px; + z-index: 9999; + max-height: calc(100% - 50px); +} diff --git a/src/TUIKit/assets/styles/sample.scss b/src/TUIKit/assets/styles/sample.scss new file mode 100644 index 0000000..8a110b0 --- /dev/null +++ b/src/TUIKit/assets/styles/sample.scss @@ -0,0 +1,99 @@ +/* stylelint-disable */ +.TUIKit { + display: flex; + width: 100vw; + height: 100vh; + overflow: hidden; + text-align: left; + .TUIKit-navbar { + background: #e8e8e9; + overflow: hidden; + .TUIKit-navbar-item { + padding: 10px; + color: #147aff; + font-weight: 500; + cursor: pointer; + } + .TUIKit-navbar-item-active { + background: #dddddd; + } + } + .TUIKit-main-container { + flex: 1; + display: flex; + overflow: hidden; + .TUIKit-main { + flex: 1; + display: flex; + .TUIKit-main-aside { + min-width: 285px; + flex: 0 0 24%; + border-right: 1px solid #f4f5f9; + } + .TUIKit-main-main { + flex: 1; + display: flex; + .chat{ + flex: 1; + } + .chat-aside { + position: absolute; + top: 50px; + right: 0; + box-sizing: border-box; + max-width: 360px; + max-height: calc(100% - 50px); + border-radius: 8px 0 0 8px; + z-index: 9999; + } + } + } + .callkit-container { + position: fixed; + left: calc(50% - 25rem); + top: calc(50% - 18rem); + width: 50rem; + height: 36rem; + } + .callkit-container.miniMized { + left: auto; + right: 10px; + top: 70px; + background: transparent; + } + } +} +.TUIKit-h5 { + display: flex; + flex-direction: column-reverse; + .TUIKit-navbar { + display: flex; + flex-direction: row; + .TUIKit-navbar-item { + flex: 1; + text-align: center; + cursor: none; + } + } + .TUIKit-main-container { + flex: 1; + .TUIKit-main { + .TUIKit-main-aside { + flex: 1; + } + .TUIKit-main-main { + .chat-popup { + position: absolute; + max-width: 100%; + max-height: 100%; + } + } + } + .callkit-container { + left: 0; + top: 0; + width: 100%; + height: 100%; + } + } +} diff --git a/src/TUIKit/components/TUIChat/chat-header/index.vue b/src/TUIKit/components/TUIChat/chat-header/index.vue new file mode 100644 index 0000000..6e11902 --- /dev/null +++ b/src/TUIKit/components/TUIChat/chat-header/index.vue @@ -0,0 +1,160 @@ + + + diff --git a/src/TUIKit/components/TUIChat/config.ts b/src/TUIKit/components/TUIChat/config.ts new file mode 100644 index 0000000..ed99f3d --- /dev/null +++ b/src/TUIKit/components/TUIChat/config.ts @@ -0,0 +1,83 @@ +class TUIChatConfig { + static instance: TUIChatConfig; + private chatType: string; + private features: Record; + private theme: string; + constructor() { + this.chatType = ''; + this.features = { + DownloadFile: true, + CopyMessage: true, + DeleteMessage: true, + RevokeMessage: true, + QuoteMessage: true, + ForwardMessage: true, + TranslateMessage: true, + VoiceToText: true, + MultiSelection: true, + EmojiReaction: true, + InputEmoji: true, + InputStickers: true, + InputImage: true, + InputVoice: true, + InputVideo: true, + InputFile: true, + InputEvaluation: true, + InputQuickReplies: true, + InputMention: true, + MessageSearch: true, + ReadStatus: true, + }; + this.theme = 'light'; + } + + static getInstance(): TUIChatConfig { + if (!TUIChatConfig.instance) { + TUIChatConfig.instance = new TUIChatConfig(); + } + return TUIChatConfig.instance; + } + + setChatType(chatType: string) { + this.chatType = chatType; + } + + getChatType() { + return this.chatType; + } + + hideTUIChatFeatures(features: string[]) { + if (!features) { + return; + } + features.forEach((feature: string) => { + if (this.features[feature]) { + this.features[feature] = false; + } + }); + } + + getFeatureConfig(key?: string) { + if (key) { + return this.features[key]; + } + return this.features; + } + + setTheme(theme: string) { + this.theme = theme; + } + + getTheme() { + return this.theme; + } +} + +const ChatConfig = TUIChatConfig.getInstance(); +const hideTUIChatFeatures = ChatConfig.hideTUIChatFeatures.bind(ChatConfig); + +export { + hideTUIChatFeatures, +}; + +export default ChatConfig; diff --git a/src/TUIKit/components/TUIChat/emoji-config/custom-emoji.ts b/src/TUIKit/components/TUIChat/emoji-config/custom-emoji.ts new file mode 100644 index 0000000..d6501df --- /dev/null +++ b/src/TUIKit/components/TUIChat/emoji-config/custom-emoji.ts @@ -0,0 +1,15 @@ +import { IEmojiGroupList } from '../../../interface'; + +/** +* Custom big emoji +*/ +export const CUSTOM_BIG_EMOJI_URL: string = ''; + +export const CUSTOM_BIG_EMOJI_GROUP_LIST: IEmojiGroupList = []; + +/** +* Custom basic emoji +*/ +export const CUSTOM_BASIC_EMOJI_URL: string = ''; + +export const CUSTOM_BASIC_EMOJI_URL_MAPPING: Record = {}; diff --git a/src/TUIKit/components/TUIChat/emoji-config/default-emoji.ts b/src/TUIKit/components/TUIChat/emoji-config/default-emoji.ts new file mode 100644 index 0000000..e90d1af --- /dev/null +++ b/src/TUIKit/components/TUIChat/emoji-config/default-emoji.ts @@ -0,0 +1,114 @@ +/** + * Emoji input interface in the chat screen. + * In respect for the copyright of the emoji design, the Chat Demo/TUIKit project does not include the cutouts of large emoji elements. + * Please replace them with your own designed or copyrighted emoji packs before the official launch for commercial use. + * The default small yellow face emoji pack is copyrighted by Tencent Cloud and can be authorized for a fee. + * If you wish to obtain authorization, please submit a ticket to contact us. + * + * submit a ticket url:https://console.tencentcloud.com/workorder/category?level1_id=29&level2_id=40&source=14&data_title=Chat&step=1 + */ +import { default as emojiCNLocales } from './locales/zh_cn'; +import { default as emojiENLocales } from './locales/en'; +import { EMOJI_TYPE } from '../../../constant'; +import { IEmojiGroupList } from '../../../interface'; + +export const DEFAULT_BASIC_EMOJI_URL = 'https://web.sdk.qcloud.com/im/assets/emoji-plugin/'; +export const DEFAULT_BIG_EMOJI_URL = 'https://web.sdk.qcloud.com/im/assets/face-elem/'; + +export const DEFAULT_BASIC_EMOJI_URL_MAPPING: Record = { + '[TUIEmoji_Expect]': 'emoji_0@2x.png', + '[TUIEmoji_Blink]': 'emoji_1@2x.png', + '[TUIEmoji_Guffaw]': 'emoji_2@2x.png', + '[TUIEmoji_KindSmile]': 'emoji_3@2x.png', + '[TUIEmoji_Haha]': 'emoji_4@2x.png', + '[TUIEmoji_Cheerful]': 'emoji_5@2x.png', + '[TUIEmoji_Smile]': 'emoji_6@2x.png', + '[TUIEmoji_Sorrow]': 'emoji_7@2x.png', + '[TUIEmoji_Speechless]': 'emoji_8@2x.png', + '[TUIEmoji_Amazed]': 'emoji_9@2x.png', + '[TUIEmoji_Complacent]': 'emoji_10@2x.png', + '[TUIEmoji_Lustful]': 'emoji_11@2x.png', + '[TUIEmoji_Stareyes]': 'emoji_12@2x.png', + '[TUIEmoji_Giggle]': 'emoji_13@2x.png', + '[TUIEmoji_Daemon]': 'emoji_14@2x.png', + '[TUIEmoji_Rage]': 'emoji_15@2x.png', + '[TUIEmoji_Yawn]': 'emoji_16@2x.png', + '[TUIEmoji_TearsLaugh]': 'emoji_17@2x.png', + '[TUIEmoji_Silly]': 'emoji_18@2x.png', + '[TUIEmoji_Wail]': 'emoji_19@2x.png', + '[TUIEmoji_Kiss]': 'emoji_20@2x.png', + '[TUIEmoji_Trapped]': 'emoji_21@2x.png', + '[TUIEmoji_Fear]': 'emoji_22@2x.png', + '[TUIEmoji_BareTeeth]': 'emoji_23@2x.png', + '[TUIEmoji_FlareUp]': 'emoji_24@2x.png', + '[TUIEmoji_Tact]': 'emoji_25@2x.png', + '[TUIEmoji_Shit]': 'emoji_26@2x.png', + '[TUIEmoji_ShutUp]': 'emoji_27@2x.png', + '[TUIEmoji_Sigh]': 'emoji_28@2x.png', + '[TUIEmoji_Hehe]': 'emoji_29@2x.png', + '[TUIEmoji_Silent]': 'emoji_30@2x.png', + '[TUIEmoji_Skull]': 'emoji_31@2x.png', + '[TUIEmoji_Mask]': 'emoji_32@2x.png', + '[TUIEmoji_Beer]': 'emoji_33@2x.png', + '[TUIEmoji_Cake]': 'emoji_34@2x.png', + '[TUIEmoji_RedPacket]': 'emoji_35@2x.png', + '[TUIEmoji_Bombs]': 'emoji_36@2x.png', + '[TUIEmoji_Ai]': 'emoji_37@2x.png', + '[TUIEmoji_Celebrate]': 'emoji_38@2x.png', + '[TUIEmoji_Bless]': 'emoji_39@2x.png', + '[TUIEmoji_Flower]': 'emoji_40@2x.png', + '[TUIEmoji_Watermelon]': 'emoji_41@2x.png', + '[TUIEmoji_Cow]': 'emoji_42@2x.png', + '[TUIEmoji_Fool]': 'emoji_43@2x.png', + '[TUIEmoji_Surprised]': 'emoji_44@2x.png', + '[TUIEmoji_Askance]': 'emoji_45@2x.png', + '[TUIEmoji_Monster]': 'emoji_46@2x.png', + '[TUIEmoji_Pig]': 'emoji_47@2x.png', + '[TUIEmoji_Coffee]': 'emoji_48@2x.png', + '[TUIEmoji_Ok]': 'emoji_49@2x.png', + '[TUIEmoji_Heart]': 'emoji_50@2x.png', + '[TUIEmoji_Sun]': 'emoji_51@2x.png', + '[TUIEmoji_Moon]': 'emoji_52@2x.png', + '[TUIEmoji_Star]': 'emoji_53@2x.png', + '[TUIEmoji_Rich]': 'emoji_54@2x.png', + '[TUIEmoji_Fortune]': 'emoji_55@2x.png', + '[TUIEmoji_857]': 'emoji_56@2x.png', + '[TUIEmoji_666]': 'emoji_57@2x.png', + '[TUIEmoji_Prohibit]': 'emoji_58@2x.png', + '[TUIEmoji_Convinced]': 'emoji_59@2x.png', + '[TUIEmoji_Knife]': 'emoji_60@2x.png', + '[TUIEmoji_Like]': 'emoji_61@2x.png', +}; + +export const BIG_EMOJI_GROUP_LIST: IEmojiGroupList = [ + { + emojiGroupID: 1, + type: EMOJI_TYPE.BIG, + url: DEFAULT_BIG_EMOJI_URL, + list: ['yz00', 'yz01', 'yz02', 'yz03', 'yz04', 'yz05', 'yz06', 'yz07', 'yz08', + 'yz09', 'yz10', 'yz11', 'yz12', 'yz13', 'yz14', 'yz15', 'yz16', 'yz17'], + }, + { + emojiGroupID: 2, + type: EMOJI_TYPE.BIG, + url: DEFAULT_BIG_EMOJI_URL, + list: ['ys00', 'ys01', 'ys02', 'ys03', 'ys04', 'ys05', 'ys06', 'ys07', 'ys08', + 'ys09', 'ys10', 'ys11', 'ys12', 'ys13', 'ys14', 'ys15'], + }, + { + emojiGroupID: 3, + type: EMOJI_TYPE.BIG, + url: DEFAULT_BIG_EMOJI_URL, + list: ['gcs00', 'gcs01', 'gcs02', 'gcs03', 'gcs04', 'gcs05', 'gcs06', 'gcs07', + 'gcs08', 'gcs09', 'gcs10', 'gcs11', 'gcs12', 'gcs13', 'gcs14', 'gcs15', 'gcs16'], + }, +]; + +export const BASIC_EMOJI_NAME_TO_KEY_MAPPING = { + ...Object.fromEntries( + Object.entries(emojiCNLocales)?.map(([key, val]) => [val, key]), + ), + ...Object.fromEntries( + Object.entries(emojiENLocales)?.map(([key, val]) => [val, key]), + ), +}; diff --git a/src/TUIKit/components/TUIChat/emoji-config/index.ts b/src/TUIKit/components/TUIChat/emoji-config/index.ts new file mode 100644 index 0000000..c6ee4dc --- /dev/null +++ b/src/TUIKit/components/TUIChat/emoji-config/index.ts @@ -0,0 +1,140 @@ +import { TUITranslateService } from '@tencentcloud/chat-uikit-engine'; +import { CUSTOM_BASIC_EMOJI_URL, CUSTOM_BIG_EMOJI_URL, CUSTOM_BASIC_EMOJI_URL_MAPPING, CUSTOM_BIG_EMOJI_GROUP_LIST } from './custom-emoji'; +import { DEFAULT_BASIC_EMOJI_URL, BIG_EMOJI_GROUP_LIST, DEFAULT_BASIC_EMOJI_URL_MAPPING, BASIC_EMOJI_NAME_TO_KEY_MAPPING, DEFAULT_BIG_EMOJI_URL } from './default-emoji'; +import { default as emojiCNLocales } from './locales/zh_cn'; +import { IEmojiGroupList } from '../../../interface'; +import { EMOJI_TYPE } from '../../../constant'; +import { isWeChat } from '../../../utils/env'; + +const hasCustomBasicEmoji = CUSTOM_BASIC_EMOJI_URL && Object.keys(CUSTOM_BASIC_EMOJI_URL_MAPPING).length; + +const BASIC_EMOJI_URL = hasCustomBasicEmoji ? CUSTOM_BASIC_EMOJI_URL : DEFAULT_BASIC_EMOJI_URL; + +const BASIC_EMOJI_URL_MAPPING = hasCustomBasicEmoji ? CUSTOM_BASIC_EMOJI_URL_MAPPING : DEFAULT_BASIC_EMOJI_URL_MAPPING; + +const EMOJI_GROUP_LIST: IEmojiGroupList = [ + { + emojiGroupID: 0, + type: EMOJI_TYPE.BASIC, + url: BASIC_EMOJI_URL, + list: Object.keys(BASIC_EMOJI_URL_MAPPING), + }, + ...BIG_EMOJI_GROUP_LIST, + ...CUSTOM_BIG_EMOJI_GROUP_LIST, +]; + +/** + * Converts a basic emoji key into its corresponding name. + * Example: + * '[Smile]' => '[TUIEmoji_Smile]' + * @param {string} key - The emoji key. + * @return {string} The corresponding emoji name. + */ +const convertKeyToEmojiName = (key: string): string => { + // WeChat does not support emoji translation + return isWeChat ? emojiCNLocales[key] : TUITranslateService.t(`Emoji.${key}`); +}; + +/** + * Transforms a text containing emoji keys into a text with Chinese or English basic emoji names + * Example: + * 'hello[TUIEmoji_Smile]!' => 'hello[Smile]!'' + * @param {string} text - The text containing emoji keys. + * @return {string} The transformed text with emoji keys replaced by emoji names. + */ +const transformTextWithKeysToEmojiNames = (text: string): string => { + if (!text) { + return ''; + } + const reg = /(\[.+?\])/g; + let txt: string = text; + if (reg.test(text)) { + txt = text.replace(reg, match => BASIC_EMOJI_URL_MAPPING[match] ? convertKeyToEmojiName(match) : match); + } + return txt; +}; + +/** + * Transforms a text containing Chinese or English basic emoji names into a text with emoji keys. + * Example: + * 'hello[Smile]!' => 'hello[TUIEmoji_Smile]!' + * @param {string} text - The text containing emoji names. + * @return {string} The transformed text with emoji names replaced by emoji keys. + */ +const transformTextWithEmojiNamesToKeys = (text: string) => { + if (!text) { + return ''; + } + const reg = /(\[.+?\])/g; + let txt: string = text; + if (reg.test(text)) { + txt = text.replace(reg, match => BASIC_EMOJI_NAME_TO_KEY_MAPPING[match] || match); + } + return txt; +}; + +/** +* The configuration aims to provide compatibility with versions prior to 2.2.0 +*/ +const emojiConfig = { + emojiBaseUrl: BASIC_EMOJI_URL, + emojiUrlMapping: BASIC_EMOJI_URL_MAPPING, + emojiNameMapping: { + ...emojiCNLocales, + }, +}; + +/** + * Transform text message to renderable array contains image and text. + * Example: hello[TUIEmoji_Smile], I am happy. + * -> [{type: 'text', content: 'hello'}, {type: 'image', content: 'https://.../smile.png'}, {type: 'text', content: ', I am happy.'}] + * @param text + * @returns Array<{ type: 'text' | 'image'; content: string; emojiKey?: string; }> + */ +const parseTextToRenderArray = (text: string): Array<{ type: 'text' | 'image'; content: string; emojiKey?: string }> => { + const emojiRegex = /\[([^\]]+)\]/g; + const result: any[] = []; + + let match: RegExpExecArray | null; + let lastIndex = 0; + + while ((match = emojiRegex.exec(text)) !== null) { + const startIndex = match.index; + const endIndex = emojiRegex.lastIndex; + const emojiKey = match[0]; + + if (startIndex > lastIndex) { + result.push({ type: 'text', content: text.substring(lastIndex, startIndex) }); + } + + const emojiUrl = BASIC_EMOJI_URL + BASIC_EMOJI_URL_MAPPING[emojiKey]; + if (emojiUrl) { + result.push({ type: 'image', content: emojiUrl, emojiKey }); + } else { + result.push({ type: 'text', content: emojiKey }); + } + + lastIndex = endIndex; + emojiRegex.lastIndex = lastIndex; + } + + if (lastIndex < text.length) { + result.push({ type: 'text', content: text.substring(lastIndex) }); + } + + return result; +}; + +export { + EMOJI_GROUP_LIST, + CUSTOM_BIG_EMOJI_URL, + DEFAULT_BIG_EMOJI_URL, + CUSTOM_BASIC_EMOJI_URL, + BASIC_EMOJI_URL_MAPPING, + CUSTOM_BASIC_EMOJI_URL_MAPPING, + convertKeyToEmojiName, + parseTextToRenderArray, + transformTextWithKeysToEmojiNames, + transformTextWithEmojiNamesToKeys, + emojiConfig, +}; diff --git a/src/TUIKit/components/TUIChat/emoji-config/locales/en.ts b/src/TUIKit/components/TUIChat/emoji-config/locales/en.ts new file mode 100644 index 0000000..baa4fd1 --- /dev/null +++ b/src/TUIKit/components/TUIChat/emoji-config/locales/en.ts @@ -0,0 +1,66 @@ +const Emoji = { + '[TUIEmoji_Smile]': '[Smile]', + '[TUIEmoji_Expect]': '[Expect]', + '[TUIEmoji_Blink]': '[Blink]', + '[TUIEmoji_Guffaw]': '[Guffaw]', + '[TUIEmoji_KindSmile]': '[KindSmile]', + '[TUIEmoji_Haha]': '[Haha]', + '[TUIEmoji_Cheerful]': '[Cheerful]', + '[TUIEmoji_Speechless]': '[Speechless]', + '[TUIEmoji_Amazed]': '[Amazed]', + '[TUIEmoji_Sorrow]': '[Sorrow]', + '[TUIEmoji_Complacent]': '[Complacent]', + '[TUIEmoji_Silly]': '[Silly]', + '[TUIEmoji_Lustful]': '[Lustful]', + '[TUIEmoji_Giggle]': '[Giggle]', + '[TUIEmoji_Kiss]': '[Kiss]', + '[TUIEmoji_Wail]': '[Wail]', + '[TUIEmoji_TearsLaugh]': '[TearsLaugh]', + '[TUIEmoji_Trapped]': '[Trapped]', + '[TUIEmoji_Mask]': '[Mask]', + '[TUIEmoji_Fear]': '[Fear]', + '[TUIEmoji_BareTeeth]': '[BareTeeth]', + '[TUIEmoji_FlareUp]': '[FlareUp]', + '[TUIEmoji_Yawn]': '[Yawn]', + '[TUIEmoji_Tact]': '[Tact]', + '[TUIEmoji_Stareyes]': '[StarEyes]', + '[TUIEmoji_ShutUp]': '[ShutUp]', + '[TUIEmoji_Sigh]': '[Sigh]', + '[TUIEmoji_Hehe]': '[Hehe]', + '[TUIEmoji_Silent]': '[Silent]', + '[TUIEmoji_Surprised]': '[Surprised]', + '[TUIEmoji_Askance]': '[Askance]]', + '[TUIEmoji_Ok]': '[OK]', + '[TUIEmoji_Shit]': '[Shit]', + '[TUIEmoji_Monster]': '[Monster]', + '[TUIEmoji_Daemon]': '[Daemon]', + '[TUIEmoji_Rage]': '[Rage]', + '[TUIEmoji_Fool]': '[Fool]', + '[TUIEmoji_Pig]': '[Pig]', + '[TUIEmoji_Cow]': '[Cow]', + '[TUIEmoji_Ai]': '[AI]', + '[TUIEmoji_Skull]': '[Skull]', + '[TUIEmoji_Bombs]': '[Bombs]', + '[TUIEmoji_Coffee]': '[Coffee]', + '[TUIEmoji_Cake]': '[Cake]', + '[TUIEmoji_Beer]': '[Beer]', + '[TUIEmoji_Flower]': '[Flower]', + '[TUIEmoji_Watermelon]': '[Watermelon]', + '[TUIEmoji_Rich]': '[Rich]', + '[TUIEmoji_Heart]': '[Heart]', + '[TUIEmoji_Moon]': '[Moon]', + '[TUIEmoji_Sun]': '[Sun]', + '[TUIEmoji_Star]': '[Star]', + '[TUIEmoji_RedPacket]': '[RedPacket]', + '[TUIEmoji_Celebrate]': '[Celebrate]', + '[TUIEmoji_Bless]': '[Bless]', + '[TUIEmoji_Fortune]': '[Fortune]', + '[TUIEmoji_Convinced]': '[Convinced]', + '[TUIEmoji_Prohibit]': '[Prohibit]', + '[TUIEmoji_666]': '[666]', + '[TUIEmoji_857]': '[857]', + '[TUIEmoji_Knife]': '[Knife]', + '[TUIEmoji_Like]': '[Like]', +}; + +export default Emoji; diff --git a/src/TUIKit/components/TUIChat/emoji-config/locales/zh_cn.ts b/src/TUIKit/components/TUIChat/emoji-config/locales/zh_cn.ts new file mode 100644 index 0000000..7086a1f --- /dev/null +++ b/src/TUIKit/components/TUIChat/emoji-config/locales/zh_cn.ts @@ -0,0 +1,66 @@ +const Emoji: Record = { + '[TUIEmoji_Smile]': '[微笑]', + '[TUIEmoji_Expect]': '[期待]', + '[TUIEmoji_Blink]': '[眨眼]', + '[TUIEmoji_Guffaw]': '[大笑]', + '[TUIEmoji_KindSmile]': '[姨母笑]', + '[TUIEmoji_Haha]': '[哈哈哈]', + '[TUIEmoji_Cheerful]': '[愉快]', + '[TUIEmoji_Speechless]': '[无语]', + '[TUIEmoji_Amazed]': '[惊讶]', + '[TUIEmoji_Sorrow]': '[悲伤]', + '[TUIEmoji_Complacent]': '[得意]', + '[TUIEmoji_Silly]': '[傻了]', + '[TUIEmoji_Lustful]': '[色]', + '[TUIEmoji_Giggle]': '[憨笑]', + '[TUIEmoji_Kiss]': '[亲亲]', + '[TUIEmoji_Wail]': '[大哭]', + '[TUIEmoji_TearsLaugh]': '[哭笑]', + '[TUIEmoji_Trapped]': '[困]', + '[TUIEmoji_Mask]': '[口罩]', + '[TUIEmoji_Fear]': '[恐惧]', + '[TUIEmoji_BareTeeth]': '[龇牙]', + '[TUIEmoji_FlareUp]': '[发怒]', + '[TUIEmoji_Yawn]': '[打哈欠]', + '[TUIEmoji_Tact]': '[机智]', + '[TUIEmoji_Stareyes]': '[星星眼]', + '[TUIEmoji_ShutUp]': '[闭嘴]', + '[TUIEmoji_Sigh]': '[叹气]', + '[TUIEmoji_Hehe]': '[呵呵]', + '[TUIEmoji_Silent]': '[收声]', + '[TUIEmoji_Surprised]': '[惊喜]', + '[TUIEmoji_Askance]': '[白眼]', + '[TUIEmoji_Ok]': '[OK]', + '[TUIEmoji_Shit]': '[便便]', + '[TUIEmoji_Monster]': '[怪兽]', + '[TUIEmoji_Daemon]': '[恶魔]', + '[TUIEmoji_Rage]': '[恶魔怒]', + '[TUIEmoji_Fool]': '[衰]', + '[TUIEmoji_Pig]': '[猪]', + '[TUIEmoji_Cow]': '[牛]', + '[TUIEmoji_Ai]': '[AI]', + '[TUIEmoji_Skull]': '[骷髅]', + '[TUIEmoji_Bombs]': '[炸弹]', + '[TUIEmoji_Coffee]': '[咖啡]', + '[TUIEmoji_Cake]': '[蛋糕]', + '[TUIEmoji_Beer]': '[啤酒]', + '[TUIEmoji_Flower]': '[花]', + '[TUIEmoji_Watermelon]': '[瓜]', + '[TUIEmoji_Rich]': '[壕]', + '[TUIEmoji_Heart]': '[爱心]', + '[TUIEmoji_Moon]': '[月亮]', + '[TUIEmoji_Sun]': '[太阳]', + '[TUIEmoji_Star]': '[星星]', + '[TUIEmoji_RedPacket]': '[红包]', + '[TUIEmoji_Celebrate]': '[庆祝]', + '[TUIEmoji_Bless]': '[福]', + '[TUIEmoji_Fortune]': '[发]', + '[TUIEmoji_Convinced]': '[服]', + '[TUIEmoji_Prohibit]': '[禁]', + '[TUIEmoji_666]': '[666]', + '[TUIEmoji_857]': '[857]', + '[TUIEmoji_Knife]': '[刀]', + '[TUIEmoji_Like]': '[赞]', +}; + +export default Emoji; diff --git a/src/TUIKit/components/TUIChat/emoji-config/locales/zh_tw.ts b/src/TUIKit/components/TUIChat/emoji-config/locales/zh_tw.ts new file mode 100644 index 0000000..144009e --- /dev/null +++ b/src/TUIKit/components/TUIChat/emoji-config/locales/zh_tw.ts @@ -0,0 +1,66 @@ +const Emoji: Record = { + '[TUIEmoji_Smile]': '[微笑]', + '[TUIEmoji_Expect]': '[期待]', + '[TUIEmoji_Blink]': '[眨眼]', + '[TUIEmoji_Guffaw]': '[大笑]', + '[TUIEmoji_KindSmile]': '[姨母笑]', + '[TUIEmoji_Haha]': '[哈哈哈]', + '[TUIEmoji_Cheerful]': '[愉快]', + '[TUIEmoji_Speechless]': '[無語]', + '[TUIEmoji_Amazed]': '[驚訝]', + '[TUIEmoji_Sorrow]': '[悲傷]', + '[TUIEmoji_Complacent]': '[得意]', + '[TUIEmoji_Silly]': '[傻了]', + '[TUIEmoji_Lustful]': '[色]', + '[TUIEmoji_Giggle]': '[憨笑]', + '[TUIEmoji_Kiss]': '[親親]', + '[TUIEmoji_Wail]': '[大哭]', + '[TUIEmoji_TearsLaugh]': '[哭笑]', + '[TUIEmoji_Trapped]': '[困]', + '[TUIEmoji_Mask]': '[口罩]', + '[TUIEmoji_Fear]': '[恐懼]', + '[TUIEmoji_BareTeeth]': '[齜牙]', + '[TUIEmoji_FlareUp]': '[發怒]', + '[TUIEmoji_Yawn]': '[打哈欠]', + '[TUIEmoji_Tact]': '[機智]', + '[TUIEmoji_Stareyes]': '[星星眼]', + '[TUIEmoji_ShutUp]': '[閉嘴]', + '[TUIEmoji_Sigh]': '[嘆氣]', + '[TUIEmoji_Hehe]': '[呵呵]', + '[TUIEmoji_Silent]': '[收聲]', + '[TUIEmoji_Surprised]': '[驚喜]', + '[TUIEmoji_Askance]': '[白眼]', + '[TUIEmoji_Ok]': '[OK]', + '[TUIEmoji_Shit]': '[便便]', + '[TUIEmoji_Monster]': '[怪獸]', + '[TUIEmoji_Daemon]': '[惡魔]', + '[TUIEmoji_Rage]': '[惡魔怒]', + '[TUIEmoji_Fool]': '[衰]', + '[TUIEmoji_Pig]': '[豬]', + '[TUIEmoji_Cow]': '[牛]', + '[TUIEmoji_Ai]': '[AI]', + '[TUIEmoji_Skull]': '[骷髏]', + '[TUIEmoji_Bombs]': '[炸彈]', + '[TUIEmoji_Coffee]': '[咖啡]', + '[TUIEmoji_Cake]': '[蛋糕]', + '[TUIEmoji_Beer]': '[啤酒]', + '[TUIEmoji_Flower]': '[花]', + '[TUIEmoji_Watermelon]': '[瓜]', + '[TUIEmoji_Rich]': '[壕]', + '[TUIEmoji_Heart]': '[愛心]', + '[TUIEmoji_Moon]': '[月亮]', + '[TUIEmoji_Sun]': '[太陽]', + '[TUIEmoji_Star]': '[星星]', + '[TUIEmoji_RedPacket]': '[紅包]', + '[TUIEmoji_Celebrate]': '[慶祝]', + '[TUIEmoji_Bless]': '[福]', + '[TUIEmoji_Fortune]': '[發]', + '[TUIEmoji_Convinced]': '[服]', + '[TUIEmoji_Prohibit]': '[禁]', + '[TUIEmoji_666]': '[666]', + '[TUIEmoji_857]': '[857]', + '[TUIEmoji_Knife]': '[刀]', + '[TUIEmoji_Like]': '[讚]', +}; + +export default Emoji; diff --git a/src/TUIKit/components/TUIChat/forward/index.vue b/src/TUIKit/components/TUIChat/forward/index.vue new file mode 100644 index 0000000..4b87813 --- /dev/null +++ b/src/TUIKit/components/TUIChat/forward/index.vue @@ -0,0 +1,159 @@ + + + diff --git a/src/TUIKit/components/TUIChat/index.ts b/src/TUIKit/components/TUIChat/index.ts new file mode 100644 index 0000000..a4f6c17 --- /dev/null +++ b/src/TUIKit/components/TUIChat/index.ts @@ -0,0 +1,6 @@ +import TUIChat from './index.vue'; +import Server from './server'; + +new Server(); + +export default TUIChat; diff --git a/src/TUIKit/components/TUIChat/index.vue b/src/TUIKit/components/TUIChat/index.vue new file mode 100644 index 0000000..e9a909a --- /dev/null +++ b/src/TUIKit/components/TUIChat/index.vue @@ -0,0 +1,273 @@ + + + + diff --git a/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/emoji-picker-dialog.vue b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/emoji-picker-dialog.vue new file mode 100644 index 0000000..faf192d --- /dev/null +++ b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/emoji-picker-dialog.vue @@ -0,0 +1,185 @@ + + + + diff --git a/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/index.ts b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/index.ts new file mode 100644 index 0000000..33cc740 --- /dev/null +++ b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/index.ts @@ -0,0 +1,2 @@ +import EmojiPicker from './index.vue'; +export default EmojiPicker; diff --git a/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/index.vue b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/index.vue new file mode 100644 index 0000000..3066bc8 --- /dev/null +++ b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/index.vue @@ -0,0 +1,81 @@ + + + diff --git a/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/style/h5.scss b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/style/h5.scss new file mode 100644 index 0000000..552adfc --- /dev/null +++ b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/style/h5.scss @@ -0,0 +1,25 @@ +.emoji-picker-h5 { + width: 100%; + + &-list { + justify-content: space-between; + } + + &-list::after { + content: ""; + display: block; + flex: 1 1 auto; + } + + .send-btn { + width: 50px; + height: 30px; + background-color: #55C06A; + position: absolute; + right: 10px; + font-size: 16px; + color: #fff; + text-align: center; + line-height: 30px; + } +} diff --git a/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/style/index.scss b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/style/index.scss new file mode 100644 index 0000000..618221f --- /dev/null +++ b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/style/index.scss @@ -0,0 +1,4 @@ +@import "../../../../../assets/styles/common"; +@import "./web"; +@import "./h5"; + diff --git a/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/style/web.scss b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/style/web.scss new file mode 100644 index 0000000..536b050 --- /dev/null +++ b/src/TUIKit/components/TUIChat/message-input-toolbar/emoji-picker/style/web.scss @@ -0,0 +1,55 @@ +.emoji-picker { + width: 405px; + height: 300px; + display: flex; + flex-direction: column; + + &-list { + flex: 1; + display: flex; + flex-wrap: wrap; + overflow-y: auto; + margin: 2px; + + &::-webkit-scrollbar { + display: none; + } + + &-item { + cursor: pointer; + padding: 5px; + + .emoji { + width: 30px; + height: 30px; + } + + .emoji-big { + width: 70px; + height: 70px; + } + } + } + + &-tab { + display: flex; + align-items: center; + + &-item { + padding: 0 10px; + cursor: pointer; + + .icon { + margin: 10px; + width: 20px; + height: 20px; + + &-big { + margin: 2px 0; + width: 30px; + height: 30px; + } + } + } + } +} diff --git a/src/TUIKit/components/TUIChat/message-input-toolbar/evaluate/index.ts b/src/TUIKit/components/TUIChat/message-input-toolbar/evaluate/index.ts new file mode 100644 index 0000000..f9a4b11 --- /dev/null +++ b/src/TUIKit/components/TUIChat/message-input-toolbar/evaluate/index.ts @@ -0,0 +1,2 @@ +import Evaluate from './index.vue'; +export default Evaluate; diff --git a/src/TUIKit/components/TUIChat/message-input-toolbar/evaluate/index.vue b/src/TUIKit/components/TUIChat/message-input-toolbar/evaluate/index.vue new file mode 100644 index 0000000..83e41fa --- /dev/null +++ b/src/TUIKit/components/TUIChat/message-input-toolbar/evaluate/index.vue @@ -0,0 +1,211 @@ +