From 5cba5b30cf5dbea38d741e139f0b8d1c665f01bd Mon Sep 17 00:00:00 2001 From: anonymous Date: Tue, 27 Dec 2022 16:36:17 +0800 Subject: [PATCH] update flutter uikit to 1.1.0 --- CHANGELOG.md | 15 + README.md | 80 ++- doc/I18N.md | 174 +++++- doc/I18N_en.md | 169 ++++++ doc/表情.md | 453 ++++++++++++++++ doc/表情_en.md | 457 ++++++++++++++++ doc/表情_国际中文.md | 454 ++++++++++++++++ example/pubspec.lock | 80 +-- .../view_models/tui_chat_global_model.dart | 1 - .../view_models/tui_setting_model.dart | 26 + lib/data_services/core/core_services.dart | 25 + .../core/core_services_implements.dart | 22 +- lib/data_services/services_locatar.dart | 5 +- lib/i18n/strings.i18n.json | 2 +- lib/i18n/strings_zh-Hans.i18n.json | 145 ++++- lib/i18n/strings_zh-Hant.i18n.json | 2 +- lib/tencent_cloud_chat_uikit.dart | 6 + lib/ui/constants/emoji.dart | 139 ----- .../tim_uikit_profile_controller.dart | 3 +- lib/ui/utils/common_utils.dart | 7 + lib/ui/utils/constant_data.dart | 153 ------ .../utils/custom_emoji_face_data_class.dart | 19 - lib/ui/utils/message.dart | 67 +-- lib/ui/utils/permission.dart | 40 +- .../tim_uikit_add_friend.dart | 57 +- .../tim_uikit_send_application.dart | 57 +- .../TIMUIKitAddGroup/tim_uikit_add_group.dart | 50 +- .../tim_uikit_send_application.dart | 19 +- .../tim_uikit_black_list.dart | 4 +- .../tim_uikit_chat_history_message_list.dart | 1 + ..._uikit_chat_history_message_list_item.dart | 50 +- .../tim_uikit_chat_message_tooltip.dart | 7 + .../TIMUIKitAppBar/tim_uikit_appbar.dart | 23 +- .../tim_uikit_message_reaction_detail.dart | 3 +- ...m_uikit_message_reaction_select_emoji.dart | 5 +- .../tim_uikit_chat_file_elem.dart | 11 +- .../tim_uikit_chat_image_elem.dart | 68 ++- .../tim_uikit_chat_text_elem.dart | 2 +- .../TIMUIKitTextField/intl_camer_picker.dart | 10 + .../special_text/emoji_text.dart | 37 +- .../tim_uikit_more_panel.dart | 135 +++-- .../tim_uikit_send_sound_message.dart | 5 +- .../tim_uikit_text_field.dart | 511 ++++++++++-------- lib/ui/views/TIMUIKitChat/tim_uikit_chat.dart | 4 +- .../tim_uikit_multi_select_panel.dart | 13 +- .../tim_uikit_conversation.dart | 15 +- .../tim_uikit_conversation_draft_text.dart | 10 +- .../tim_uikit_conversation_item.dart | 33 +- .../tim_uikit_group_profile.dart | 10 +- .../widgets/tim_ui_group_profile_widget.dart | 4 +- .../widgets/tim_uikit_group_manage.dart | 16 +- .../widgets/tim_uikit_group_name_card.dart | 79 +-- .../TIMUIKitProfile/tim_uikit_profile.dart | 13 +- .../widget/tim_uikit_operation_item.dart | 45 +- .../tim_uikit_profile_userinfo_card.dart | 15 +- .../widget/tim_uikit_profile_widget.dart | 8 +- .../pureUI/tim_uikit_search_indicator.dart | 113 ++++ .../TIMUIKitSearch/tim_uikit_search.dart | 76 ++- lib/ui/widgets/avatar.dart | 92 ++-- lib/ui/widgets/image_screen.dart | 57 +- .../link_preview/widgets/link_text.dart | 3 +- lib/ui/widgets/radio_button.dart | 49 +- lib/ui/widgets/text_input_bottom_sheet.dart | 22 +- lib/ui/widgets/unread_message.dart | 12 +- lib/ui/widgets/video_custom_control.dart | 32 +- lib/ui/widgets/video_screen.dart | 51 +- pubspec.lock | 50 +- pubspec.yaml | 10 +- 68 files changed, 3177 insertions(+), 1254 deletions(-) create mode 100644 doc/I18N_en.md create mode 100644 doc/表情.md create mode 100644 doc/表情_en.md create mode 100644 doc/表情_国际中文.md create mode 100644 lib/business_logic/view_models/tui_setting_model.dart delete mode 100644 lib/ui/constants/emoji.dart create mode 100644 lib/ui/utils/common_utils.dart delete mode 100644 lib/ui/utils/constant_data.dart delete mode 100644 lib/ui/utils/custom_emoji_face_data_class.dart create mode 100644 lib/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_indicator.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 02c1052..0aae52a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +## 1.1.0 + +* Add: Supports two new languages, Japanese and Korean. +* Add: Supports adding new other languages, apart from our default ones, including English, Chinese(Simplified and Traditional), Japanese and Korean, or modifying the translations, refers to [this documentation](https://www.tencentcloud.com/document/product/1047/52154). +* Add: Sticker plug-in has been embedded in TUIKit by default. Now we support three types of stickers, Unicode Emoji, small image emoji and big image stickers, the usage has been optimized, refers to [this documentation](https://www.tencentcloud.com/document/product/1047/52227). +* Optimize: Themes, more customization. +* Optimize: The animation of the input area, keyboard, sticker panel and the more panel. +* Optimize: Emoji, both Unicode and small images, can be inserted to any position in text messages. +* Optimize: Avatar in profile can be previewed with a large image. +* Optimize: UserID in profile can be copied. +* Optimize: Several UI details, including `TIMUIKitAddFriend`, `TIMUIKitAddGroup`, `TIMUIKitGroupProfile` and `TIMUIKitProfile`. +* Optimize: `TIMUIKitGroupProfile` and `TIMUIKitProfile` can update automatically after `ID` changed. +* Optimize: New loading animation when downloading the image/video on `TIMUIKitGroupChat`. +* Fix: Some bugs. + ## 1.0.1 * Modify: Remove `groupTRTCTipsItemBuilder` from `MessageItemBuilder`, please use `customMessageItemBuilder` instead. diff --git a/README.md b/README.md index 4eaa204..9988a98 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,41 @@ +
@@ -34,6 +71,8 @@ More languages: +
+ ## Experience DEMO You can experience our Chat and Voice/Video Call modules via the following demos. @@ -59,7 +98,7 @@ You can experience our Chat and Voice/Video Call modules via the following demos You can use these UI components to build your APP with the In-APP chat module quickly and easily. -TUIKit screenshots +![img](https://qcloudimg.tencent-cloud.cn/raw/f140dd76be01a65abfb7e6ba2bf50ed5.png) Currently, Flutter [TUIKit](https://www.tencentcloud.com/document/product/1047/50059?from=pub) contains the following main components: @@ -77,29 +116,13 @@ Currently, Flutter [TUIKit](https://www.tencentcloud.com/document/product/1047/5 Also, there are some other useful components and widgets, that can help to build your APP, and meet your business needs, including group entry application list and group member list, etc. -For the source code of the project in the figure above, see [chat-demo-flutter](https://github.com/TencentCloud/chat-demo-flutter). The project is open source and can be used directly. +For the source code of the project in the figure above, see [im-flutter-uikit](https://github.com/TencentCloud/tc-chat-demo-flutter). The project is open source and can be used directly. -### Supported Platforms +## Supported Platforms - Android - iOS -- Web(Since version of 0.1.4) - -### What's more - -In addition to Flutter SDK & TUIKit, we have numerous SDKs that covering all platforms. The following platforms can communicate with each other and provide services across devices and platforms. - -[**chat-uikit-android**](https://github.com/TencentCloud/chat-uikit-android) - -[**chat-uikit-ios**](https://github.com/TencentCloud/chat-uikit-ios) - -[**chat-uikit-vue**](https://github.com/TencentCloud/chat-uikit-vue) - -[**chat-uikit-react**](https://github.com/TencentCloud/chat-uikit-react) - -[**chat-uikit-uniapp**](https://github.com/TencentCloud/chat-uikit-uniapp) - -[**chat-uikit-wechat**](https://github.com/TencentCloud/chat-uikit-wechat) +- Web(After version of 0.1.4) ## Get Started @@ -840,6 +863,21 @@ TIMUIKitSearchMsgDetail( ); ``` +## What's more + +In addition to Flutter SDK, we have numerous SDKs that covering all platforms. The following platforms can communicate with each other and provide services across devices and platforms. + +| Platform | Introduction | Demo | Download | UI Components library | +| --- | --- | --- | --- | --- | +| Android | Compatible with JDK 1.6 and Android SDK version 14 and later | [Get](https://www.tencentcloud.com/document/product/1047/34279) | [Get](https://github.com/TencentCloud/TIMSDK/tree/master/Android/IMSDK) | [Get](https://www.tencentcloud.com/document/product/1047/50062) | +| iOS | Compatible with iOS 8.0 and later | [Get](https://www.tencentcloud.com/document/product/1047/34279) | [Get](https://github.com/TencentCloud/TIMSDK/tree/master/iOS/IMSDK) | [Get](https://www.tencentcloud.com/document/product/1047/50062) | +| Mac | Compatible with OS X 10.10 and later | - | [Get](https://github.com/TencentCloud/TIMSDK/tree/master/Mac/IMSDK) | - | +| Windows | C and C++ are included. Compatible with Windows 7, Windows 8 and 8.1, and Windows 10. Both 32-bit and 64-bit programs can be connected | - | [Get](https://github.com/TencentCloud/TIMSDK/tree/master/Windows/IMSDK) | - | +| Web | Supports Internet Explorer 11+, Chrome 7+, Firefox 3.6+, Opera 12+ and Safari 6+ | [Get](https://www.tencentcloud.com/document/product/1047/34279) | [Get](https://www.npmjs.com/package/tim-js-sdk) | [Get](https://www.tencentcloud.com/document/product/1047/50061) | +| Unity | Supports 2020.2.7f1c1 or later | - | [Get](https://www.tencentcloud.com/document/product/1047/46263) | - | +| Flutter | Supports Flutter 2 & dart 2.12 and later, deploying to Android, iOS, Web, macOS and Windows. | [Get](https://www.tencentcloud.com/document/product/1047/34279) | Here | [Get](https://pub.dev/packages/tencent_cloud_chat_uikit) | +| Electron | Electron SDK | - | [Get](https://github.com/tencentyun/im_electron_demo) | - | + ## Contact Us Please do not hesitate to contact us in the following place, if you have any further questions or tend to learn more about the use cases. @@ -848,4 +886,4 @@ Please do not hesitate to contact us in the following place, if you have any fur - WhatsApp Group: - QQ Group: 788910197, chat in Chinese -Our Website: +Our Website: \ No newline at end of file diff --git a/doc/I18N.md b/doc/I18N.md index a4098c3..782353c 100644 --- a/doc/I18N.md +++ b/doc/I18N.md @@ -1,2 +1,172 @@ -【企微文档】TIM Flutter国际化方案 -https://doc.weixin.qq.com/doc/w3_AWcADQY0AA8u9RhcnhqRSSW6RZc4w?scode=AJEAIQdfAAoaC0QLyWAWcADQY0AA8 \ No newline at end of file + +腾讯云IM Flutter TUIKit默认自带 英文/简体中文/繁体中文/日语/韩语 语言包,作为界面展示语言。 + +根据此文档指引,您可以使用默认语言包,也可自定义语言翻译表述,并增添额外的非自带语言的支持。 + +![](https://qcloudimg.tencent-cloud.cn/raw/2df62f8a62453c063c396cb656dd07bc.png) + +## 使用自带语言 + +如果您的App,需要的语言仅包括英语/简体中文/繁体中文/日语/韩语,请参考本部分。 + +### 跟随系统语言 + +直接使用TUIKit即可,无需额外步骤。插件内部会跟随系统语言自适应。 + +### 预指定显示的语言 + +如果您需要在初始化是,手动设置TUIKit界面语言,请在`TIMUIKitCore.getInstance()`中调用`init`方法时,传入需要的语言。 + +```dart +import 'package:tim_ui_kit/tim_ui_kit.dart'; + +final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance(); + +final isInitSuccess = await _coreInstance.init( + language: LanguageEnum.en, // 请在此处定义语言,枚举值见下方 + // ...其他配置 +); +``` + +语言可选项,枚举值为: + +```dart +enum LanguageEnum { + zhHant, //繁体中文 + zhHans, //简体中文 + en, // 英文 + ko, // 韩语 + ja // 日语 +} +``` + +### 实时动态修改 + +调用 `I18nUtils(null, language);` 即可。此处的 `language` 为 [ISO 639-1 语言代码](#code)。示例如下: + +```dart +I18nUtils(null, "en"); +``` + +>? 语言代码清单见[附录](#code)。 + +## 使用更多语言/自定义翻译表述 + +如果您需要支持,除 英文/简体中文/繁体中文/日语/韩语 外的更多语言,或更改我们部分词条的翻译,请参考本部分。 + +>? 本方案仅适用于,目标语言为的阅读方向为从左至右的语言。对于阅读方向从右至左的小语种,如阿拉伯语,请自行在[GitHub fork](https://github.com/TencentCloud/chat-uikit-flutter)一份我们的源码,完成自定义左右镜像开发适配。 + +### 新增语言词条包 + +本章节的核心为本部分, 即,将您自定义的国际化多语言词条库文件,注入腾讯云IM项目内。 + +#### 获取语言模板 + +在您的项目中,允许如下代码。 + +```shell +flutter pub run tencent_im_base +``` + +根据提示,选择 `A` 选项。 + +![](https://qcloudimg.tencent-cloud.cn/raw/01215e7861ed2736c0155c456ad2d0d6.png) + +此时,我们自带的所有语言包,以JSON文件模板的形式,存储于您项目根目录下,`languages/` 路径内。 + +![](https://qcloudimg.tencent-cloud.cn/raw/2618d546ece854d93cfe21d1ad342ade.png) + +请复制一份您熟悉的语言JSON模板文件,例如,简体中文版,`strings_zh-Hans.i18n.json`。 + +复制一份新的,并命名为 `strings_${语言编码}.i18n.json`。其中,`${语言编码}` 需要替换为 [ISO 639-1 语言代码](#code)。例如,丹麦语,`strings_da.i18n.json`。 + +如果您需要兼容支持多个新语言,复制多份,并准确指定每一份的语言编码即可。 + +#### 个性化自定义翻译 + +此时,您可以修改上一步 **复制新生成的目标语言模板**。 + +打开您复制生成的新文档,**保留不动JSON的md5 key值**,将所有的value值替换成对应目标翻译语言。 + +![](https://qcloudimg.tencent-cloud.cn/raw/540536815ec579ca4343a7013a768178.png) + +>? 如果您需要修改默认语言模板的翻译文案,也可直接打开自动生成的语言模板,进行修改。**除简体中文版本外**,其他翻译文案,均可修改。 + +翻译完成后,`languages/` 内,包含原始提供的自带语言模板,及您复制生成的其他语言词条集。 + +![](https://qcloudimg.tencent-cloud.cn/raw/0b409d05e26b81b60a4babed07936cda.png) + +#### 回装您的语言包 + +在您项目的根目录下,执行 `flutter pub run tencent_im_base` 命令,并选择 `B` 选项。 + +代码运行完成后,即可使您的语言包,在当前电脑本地生效。 + +![](https://qcloudimg.tencent-cloud.cn/raw/7823200ee5f323bc254aad61be122907.png) + +>? 如果您是团队协同开发,或使用了远程流水线编译。需要在您同事电脑中或流水线编译命令脚本中,使用同样的方式,执行本章节所述方法。 + +### 跟随系统语言 + +直接使用TUIKit即可,无需额外步骤。 + +只要您新增的语言词条包命名[符合标准](#code),插件内部会跟随系统语言自适应。 + +### 预指定显示的语言 + +如果您需要在初始化是,手动设置TUIKit界面语言,请在`TIMUIKitCore.getInstance()`中调用`init`方法时,传入需要的语言。 + +```dart +import 'package:tim_ui_kit/tim_ui_kit.dart'; + +final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance(); + +final isInitSuccess = await _coreInstance.init( + extraLanguage: "ja", // 请在此处定义语言,ISO 639-1 语言代码 见下方 + // ...其他配置 +); +``` + +### 实时动态修改 + +调用 `I18nUtils(null, language);` 即可。此处的 `language` 为 [ISO 639-1 语言代码](#code)。示例如下: + +```dart +I18nUtils(null, "ja"); +``` + +>? 语言代码清单见[附录](#code)。 + +[](id:code) + +## 附录:语言代码表 + +| 语言 | 代码 | 语言 | 代码 | +|--------|--------|--------|--------| +| 阿拉伯语 | ar | 保加利亚语 | bg | +| 克罗地亚语 | hr | 捷克语 | cs | +| 丹麦语 | da | 德语 | de | +| 希腊语 | el | 英语 | en | +| 爱沙尼亚语 | et | 西班牙语 | es | +| 芬兰语 | fi | 法语 | fr | +| 爱尔兰语 | ga | 印地语 | hi | +| 匈牙利语 | hu | 希伯来语 | he | +| 意大利语 | it | 日语 | ja | +| 朝鲜语/韩语 | ko | 拉脱维亚语 | lv | +| 立陶宛语 | lt | 荷兰语 | nl | +| 挪威语 | no | 波兰语 | pl | +| 葡萄牙语 | pt | 瑞典语 | sv | +| 罗马尼亚语 | ro | 俄语 | ru | +| 塞尔维亚语 | sr | 斯洛伐克语 | sk | +| 斯洛文尼亚语 | sl | 泰语 | th | +| 土耳其语 | tr | 乌克兰语 | uk-UA | +| 中文(简体) | zh-Hans | 中文(繁体) | zh-Hant | + +完整版[请见此处](https://quickref.me/iso-639-1)。 + +## 联系我们[](id:contact) + +如果您在接入使用过程中有任何疑问,请通过如下方式联系我们。 + +- [Telegram Group](https://t.me/+1doS9AUBmndhNGNl) +- [WhatsApp Group](https://chat.whatsapp.com/Gfbxk7rQBqc8Rz4pzzP27A) diff --git a/doc/I18N_en.md b/doc/I18N_en.md new file mode 100644 index 0000000..ee4d0aa --- /dev/null +++ b/doc/I18N_en.md @@ -0,0 +1,169 @@ + +English, Simplified Chinese, Traditional Chinese, Japanese and Korean have been embedded in Tencent Cloud Chat TUIKit as the default interface languages. + +Adding other interface languages or modifying the current language items are available for you, according to the instructions of this tutorial. + +![](https://qcloudimg.tencent-cloud.cn/raw/2df62f8a62453c063c396cb656dd07bc.png) + +## Using the default languages + +If only Chinese(both traditional and simplified), English, Japanese and Korean are needed for your application, please refer to this section. + +### Choosing device language + +No further steps are needed, as meeting device language can be automatically. + +### Pre-set the language manually + +If you tend to specify the language manually, please provide the target language Enum to `init()` in `TIMUIKitCore.getInstance()`. + +```dart +import 'package:tim_ui_kit/tim_ui_kit.dart'; + +final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance(); + +final isInitSuccess = await _coreInstance.init( + language: LanguageEnum.en, // Enums as below +// ...Other configurations +); +``` + +Enum options for language: + + +```dart +enum LanguageEnum { + zhHant, // Chinese, traditional + zhHans, // Chinese, simplified + en, // English + ko, // korean + ja // Japanese +} +``` + +### Modify language dynamically + +Please just invoking `I18nUtils(null, language);`, while the `language` here should be set as the [ISO 639 Language codes](#code). + +Example code: + +```dart +I18nUtils(null, "en"); +``` + +## Need more languages / customize translation items + +Adding languages, apart from English, Simplified Chinese, Traditional Chinese, Japanese and Korean, or modifying some translation items words, can be referred to this section. + +>? This solution only works for languages with a left-to-right reading direction. For small languages that read from right to left, such as Arabic, please fork our source code from [our GitHub repository](https://github.com/TencentCloud/chat-uikit-flutter) to complete the custom left and right mirroring Development adaptation, and import to your project manually. + +### Adding language translation files + +The key of this section is this part, that is, inject your custom internationalized language file into the Tencent Cloud Chat. + +#### Get the language template + +Run the following command, and choose `A` as instruction. + +```shell +flutter pub run tencent_im_base +``` + +![](https://qcloudimg.tencent-cloud.cn/raw/01215e7861ed2736c0155c456ad2d0d6.png) + +Now, all the pre-set default language files, as JSON, have been generated to your project, `languages/` directory. + +![](https://qcloudimg.tencent-cloud.cn/raw/2618d546ece854d93cfe21d1ad342ade.png) + +Duplicate for language files, based on the template you are most familiar with. + +The newly duplicated language files should be named as `strings_${language code}.i18n.json`. While, `${language code}` should be replaced by [ISO 639 Language Codes](#code). Such as, the file containing Danish language items should be named as `strings_da.i18n.json`. + +Duplicate multiple language files, if you need to support multiple other languages. + +#### Customize translations + +Now, you can modify the language files generated in the previous step. + +Open each language file, including the files you just duplicated, except `strings_zh-Hans.i18n.json`, translate or modify each `value` to target language, while keeping the md5 key unchanged. + +![](https://qcloudimg.tencent-cloud.cn/raw/540536815ec579ca4343a7013a768178.png) + +After translation and modification, all the supported languages files, including those you duplicated and default, should be in the `languages/` directory. + +![](https://qcloudimg.tencent-cloud.cn/raw/0b409d05e26b81b60a4babed07936cda.png) + +#### Activate those language files + +Run the following command, and choose `B` as instruction. + +```dart +flutter pub run tencent_im_base +``` + +After the script has finished, those customization languages are activated on your local Flutter environment. + +![](https://qcloudimg.tencent-cloud.cn/raw/7823200ee5f323bc254aad61be122907.png) + +>? If you are developing with a team collaboratively, or using DevOps pipeline compilation. You also need to execute this solution on your colleague's computer or in the DevOps pipeline compilation command script. + +### Choosing device language + +No further steps are needed, as meeting device language can be automatically. + +### Pre-set the language manually + +If you tend to specify the language manually, please provide the [ISO 639 Language Codes](#code) of the language to `init()` in `TIMUIKitCore.getInstance()`. + +```dart +import 'package:tim_ui_kit/tim_ui_kit.dart'; + +final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance(); + +final isInitSuccess = await _coreInstance.init( + extraLanguage: "ja", // ISO 639 Language Codes +// ...Other configurations +); +``` + +### Modify language dynamically + +Please just invoking `I18nUtils(null, language);`, while the `language` here should be set as the [ISO 639 Language codes](#code). + +Example code: + +```dart +I18nUtils(null, "en"); +``` + +[](id:code) + +## Appendix: Language codes + +| Language | Code | Language | Code | +|--------|--------|--------|--------| +| Arabic | ar | Bulgarian | bg | +| Croatian | hr | Czech | cs | +| Danish | da | German | de | +| Greek | el | English | en | +| Estonian | et | Spanish | es | +| Finnish | fi | French | fr | +| Irish | ga | Hindi | hi | +| Hungarian | hu | Hebrew | he | +| Italian | it | Japanese | ja | +| Korean | ko | Latvian | lv | +| Lithuanian | lt | Dutch | nl | +| Norwegian | no | Polish | pl | +| Portuguese | pt | Swedish | sv | +| Romanian | ro | Russian | ru | +| Serbian | sr | Slovak | sk | +| Slovenian | sl | Thai | th | +| Turkish | tr | Ukrainian | uk | +| Chinese (Simplified)) | zh-Hans | Chinese (Traditional) | zh-Hant | + +## Contact us[](id:contact) + +If there's anything unclear or you have more ideas, feel free to contact us! + +- [Telegram Group](https://t.me/+1doS9AUBmndhNGNl) +- [WhatsApp Group](https://chat.whatsapp.com/Gfbxk7rQBqc8Rz4pzzP27A) diff --git a/doc/表情.md b/doc/表情.md new file mode 100644 index 0000000..57fed56 --- /dev/null +++ b/doc/表情.md @@ -0,0 +1,453 @@ + +以下为您介绍,如何为腾讯云IM Flutter TUIKit引入表情能力。 + +我们的 `TIMUIKitChat` 组件中,支持发送及接收三种类型的表情: + +| 表情类型 | 发送形式 | 是否文字混排 | 发送内容 | 解析方式 | 引入方式 | TUIKit默认自带 | +|---------|---------|---------|---------|---------|---------|---------| +| [Unicode](https://unicode.org/emoji/charts/full-emoji-list.html) Emoji表情 | 文本消息 | 是 | [Unicode](https://unicode.org/emoji/charts/full-emoji-list.html)编码 | 设备自动将[Unicode](https://unicode.org/emoji/charts/full-emoji-list.html)编码解析成小表情。不同的设备,对[Unicode](https://unicode.org/emoji/charts/full-emoji-list.html)解析后的图形,略有不同 | [Unicode](https://unicode.org/emoji/charts/full-emoji-list.html) List | 文档中提供一套[默认Unicode列表示例](#unicode) | +| 小图片表情 | 文本消息 | 是 | 表情图片名称 | 根据名称,自动匹配本地Asset图片资源 | 图片资源预存于Asset,并定义 `List` | 一套 QQ 同款小表情图库,可直接使用 | +| 大图片表情 | 表情消息 | 否 | `baseURL` 拼接图片文件名,表情图片Asset路径 | 通过路径,解析Asset资源 | 图片资源预存于Asset,并定义 `List` | - | + +![](https://qcloudimg.tencent-cloud.cn/raw/bf06763d76d0c6e0c1871a1da401f6ab.png) + +现在,我们就来动手接入TUIKit的表情能力。 + +>? [TUIKit](https://pub.dev/packages/tencent_cloud_chat_uikit)在升级至1.1.0版本后,对表情能力用法有较大改动。请您在升级最新版后,根据本文档指引,重新适配接入表情能力。谢谢~ + +## STEP1: 自定义表情图片资源 + +>? **本步骤选做:** +> 如果您需要用到非默认提供的QQ小表情外的其他图片表情,如自定义图片小表情及图片大表情,才需完成本步骤。 +> QQ小表情包,TUIKit已自带提供,无需在本步骤引入,请关注后续步骤。 + +### 将文件导入项目 + +请将您的表情资源文件,导入项目的 `assets/custom_face_resource/` 目录内。无论是图片大表情,亦或是图片小表情,都需按此步骤引入。 + +该目录内,请使用不同的文件夹,区分表情面板中的不同Tab。每个Tab内表情,仅支持一种类型,图片大表情或图片小表情。 + +文件夹的名称,请使用该Tab的 `name` 命名。该命名不会对客户展现,请根据开发需要,自定义即可。 + +请保证,所有表情资源文件,不要重名。 + +此路径的表情图片放置引入,可参考我们的[Demo](https://github.com/TencentCloud/chat-demo-flutter/tree/main/assets/custom_face_resource)。 + +![](https://qcloudimg.tencent-cloud.cn/raw/9cf910304e3161bd17336054de3ba7d9.png) + +### 声明表情文件 + +打开 `pubspec.yaml` 文件,在 `flutter` => `assets` 中,声明刚刚引入的表情资源文件。 + +```yaml +flutter: + assets: + - assets/custom_face_resource/ +``` + +### 在代码中配置图片资源List + +>? 本步骤代码示例请[参考此处](https://github.com/TencentCloud/chat-demo-flutter/blob/main/lib/utils/constant.dart),直接看 `emojiList` 即可。 + +在您代码定义静态参数或配置的地方,定义一个 `static List`,用于将本地图片资源,转换成TUIKit可以接受的格式,后续以 `List` 方式传入。 + +此 `List` 中,每个item都是 `CustomEmojiFaceData`,每个 `CustomEmojiFaceData` 构成一个表情面板中的Tab。具体参数说明如下: + +```dart +CustomEmojiFaceData( + { + String name, // 文件夹目录名称 + String icon, // Tab中的icon资源文件名 + List list, // 每个图片的文件名,以List + bool isEmoji // 是否为图片小表情,默认为false,即图片大表情 + } +); +``` + +示例代码如下: + +```dart +static final List emojiList = [ + // 使用图片小表情,支持图文混排,以文本消息形式发送 + CustomEmojiFaceData( + name: '4349', + icon: "aircraft.png", + isEmoji: true, + list: [ + "aircraft.png", + "alarmClock.png", + "anger.png", + // ... + ]), + + // 使用图片大表情,不支持图文混排,以表情消息形式发送 + CustomEmojiFaceData( + name: '4350', + icon: "menu@2x.png", + list: [ + "yz00@2x.png", + // ... + ]), +] +``` + +## STEP2: 自定义Emoji Unicode 字符串List + +>? **本步骤选做:** +> 如果您需要用到[Unicode](https://unicode.org/emoji/charts/full-emoji-list.html) Emoji表情,才需完成本步骤。 + +在您代码定义静态参数或配置的地方,定义一个 `List>` Unicode 列表,供传入。 + +该列表,我们提供一套示例,在[附录](#unicode)中。 + +您看直接复制引入这套示例列表,或基于此修改。 + +## STEP3: 表情资源预读入内存 + +>? +> 本步骤代码示例请[参考此处](https://github.com/TencentCloud/chat-demo-flutter/blob/main/lib/src/pages/app.dart),直接看 `setCustomSticker` 方法即可。 +> QQ小表情包,TUIKit已自带提供,无需在本步骤引入,请关注后续步骤。 + +在您的项目启动后,首个 `TIMUIKitChat` 组件渲染前,将上一步定义的图片表情资源List,转换成TUIKit表情的实例,放入全局Provider中,存储于内存里。 + +**本步骤方法仅需执行一次,一次性全部读入内存中。** 因展示渲染表情资源为高频操作,如每次展示前才动态读入内存,对资源与性能占用比较大。 + +单个表情内存实例,使用 `CustomSticker` 类生成。如果传入了 `unicode` 则为 Unicode Emoji表情,否则为图片类型表情。 + +```dart +class CustomSticker { + int? unicode; // Unicode int值。如果传入了 `unicode` 则为 Unicode Emoji表情,否则为图片类型表情 + String name; // 表情名称 + int index; // 表情序号 + bool isEmoji; // 是否为图片小表情,默认为图片大表情 +} +``` + +每个Tab的内存实例,使用 `CustomStickerPackage` 类生成。 + +```dart +class CustomStickerPackage { // 一个系列的表情包定义为一个package,占据一个表情面板Tab + String name; // 表情包package name,该Tab文件夹名称。 + String? baseUrl; // 表情包package baseUrl,建议配置成:"assets/custom_face_resource/${表情包文件夹名称 即 表情包package name}" + List stickerList; // 表情资源列表 + CustomSticker menuItem; // 表情面包Tab按钮icon + bool isEmoji; // 是否为图片小表情,默认为图片大表情 +} +``` + +综上所述,需要写的代码,我们给出示例版本。 + +表情项一演示如何使用Emoji Unicode表情包,表情项二演示如何使用图片类型(包含大或小)表情包。您可以根据需要,使用全部或部分代码。 + +```dart +setCustomSticker() async { + // 定义一个大List来承载各个表情包 package Tab + List customStickerPackageList = []; + + // 表情项一:使用Emoji Unicode表情列表。可以嵌入文字内容中。 + // `emojiData` 来自于STEP2。 + final defEmojiList = emojiData.asMap().keys.map((emojiIndex) { + final emoji = Emoji.fromJson(emojiData[emojiIndex]); + return CustomSticker( + index: emojiIndex, name: emoji.name, unicode: emoji.unicode); + }).toList(); + customStickerPackageList.add(CustomStickerPackage( + name: "defaultEmoji", + stickerList: defEmojiList, + menuItem: defEmojiList[0])); + + // 表情项二:使用您提供的图片表情包。 + // 务必保证 `customEmojiPackage.name` 为该Tab文件夹名称。 + // `Const.emojiList` 来自于STEP1。 + customStickerPackageList.addAll(Const.emojiList.map((customEmojiPackage) { + return CustomStickerPackage( + name: customEmojiPackage.name, + baseUrl: "assets/custom_face_resource/${customEmojiPackage.name}", + stickerList: customEmojiPackage.list + .asMap() + .keys + .map((idx) => + CustomSticker(index: idx, name: customEmojiPackage.list[idx])) + .toList(), + menuItem: CustomSticker( + index: 0, + name: customEmojiPackage.icon, + )); + }).toList()); + + Provider.of(context, listen: false) + .customStickerPackageList = customStickerPackageList; +} +``` + +## STEP4: 为 TIMUIKitChat 组件添加表情解析能力 + +>? +> 本步骤代码示例请[参考此处](https://github.com/TencentCloud/chat-demo-flutter/blob/main/lib/src/chat.dart),重点浏览 `renderCustomStickerPanel`, `customStickerPanel` 及 `customEmojiList` 即可。 + +将以下代码,直接拷贝进入您用于承载 `TIMUIKitChat` 组件的类中。 + +```dart +Widget renderCustomStickerPanel({ + sendTextMessage, + sendFaceMessage, + deleteText, + addCustomEmojiText, + addText, + List defaultCustomEmojiStickerList = const [], +}) { + final theme = Provider.of(context).theme; + final customStickerPackageList = + Provider.of(context).customStickerPackageList; + final defaultEmojiList = + defaultCustomEmojiStickerList.map((customEmojiPackage) { + return CustomStickerPackage( + name: customEmojiPackage.name, + baseUrl: "assets/custom_face_resource/${customEmojiPackage.name}", + isEmoji: customEmojiPackage.isEmoji, + isDefaultEmoji: true, + stickerList: customEmojiPackage.list + .asMap() + .keys + .map((idx) => + CustomSticker(index: idx, name: customEmojiPackage.list[idx])) + .toList(), + menuItem: CustomSticker( + index: 0, + name: customEmojiPackage.icon, + )); + }).toList(); + return StickerPanel( + sendTextMsg: sendTextMessage, + sendFaceMsg: (index, data) => + sendFaceMessage(index + 1, (data.split("/")[3]).split("@")[0]), + deleteText: deleteText, + addText: addText, + addCustomEmojiText: addCustomEmojiText, + customStickerPackageList: [ + ...defaultEmojiList, + ...customStickerPackageList + ], + backgroundColor: theme.weakBackgroundColor, + lightPrimaryColor: theme.lightPrimaryColor); +} +``` + +### STEP4.1: 渲染图片小表情 + +>? **本步骤选做:** +> - 如果您的项目需要用到图片小表情,包括自定义图片小表情,或直接使用默认自带 QQ 同款图片小表情,才需完成本步骤。 +> - 图片小表情展现形式和Unicode Emoji类似,建议Unicode Emoji和图片小表情选用一个即可。即,如果您选用了Unicode Emoji,可直接跳过本步骤。 + +- STEP4.1(a) 为使用自定义图片小表情; +- STEP4.1(b) 为使用默认自带 QQ 同款图片小表情。 + +以上方案,建议直接选用一个方案即可。 + +如果需要同时使用,请保证您的自定义图片小表情名称,不要和我们默认提供的 QQ 同款图片小表情重复。 + +#### STEP4.1(a): 添加渲染解析自定义图片小表情的支持 + +在您用于承载 `TIMUIKitChat` 组件的 `build` 方法中,定义一个 `List customEmojiList` 变量,用于存放图片小表情列表。 + +```dart +List customEmojiList = + Const.emojiList.where((element) => element.isEmoji == true).toList(); +``` + +并将此列表,传入 `TIMUIKitChat` 组件的 `customEmojiStickerList` 参数内。 + +```dart +return TIMUIKitChat( + customEmojiStickerList: customEmojiList, + // ...... +); +``` + +>? 如果您用于承载 `TIMUIKitChat` 组件的类为 `StatefulWidget`,您可将 `customEmojiList` 变量,放如State中,仅在首次build时,才去执行 `where` 命令,优化性能。 + +#### STEP4.1(b): 启用 QQ 小表情包 + +将 `TIMUIKitChat` 的 `TIMUIKitChatConfig` 的 `isUseDefaultEmoji` 参数,设置为 `true` 即可。此时,会向表情包面板最左侧,自动生成一个承载 QQ 小表情包的 Tab。 + +```dart +return TIMUIKitChat( + config: TIMUIKitChatConfig( + isUseDefaultEmoji: true, + // ...... + ), + // ...... +); +``` + +![](https://qcloudimg.tencent-cloud.cn/raw/f096cf79710207a0db6f33936a55bbb0.png) + +### STEP4.2: 将表情包能力,注入 TIMUIKitChat + +将本步骤最开始让您复制的代码方法,传入 `TIMUIKitChat` 组件的 `customStickerPanel` 参数内。 + +```dart +return TIMUIKitChat( + customStickerPanel: renderCustomStickerPanel, + // ...... +); +``` + +此时,TUIKit表情能力接入完成。您可正常收发测试。如在接入过程中,有任何问题,欢迎随时[联系我们](#contact)。 + +[](id:unicode) + +## 附录: Emoji Unicode 列表示例 + +本列表仅用于示例演示,您可根据需要,增加或修改。 + +```dart +List> emojiData = [ + {"name": "GRINNING FACE WITH SMILING EYES", "unicode": 128513}, + {"name": "FACE WITH TEARS OF JOY", "unicode": 128514}, + {"name": "SMILING FACE WITH OPEN MOUTH", "unicode": 128515}, + {"name": "SMILING FACE WITH OPEN MOUTH AND SMILING EYES", "unicode": 128516}, + {"name": "SMILING FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128517}, + { + "name": "SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES", + "unicode": 128518 + }, + {"name": "WINKING FACE", "unicode": 128521}, + {"name": "SMILING FACE WITH SMILING EYES", "unicode": 128522}, + {"name": "FACE SAVOURING DELICIOUS FOOD", "unicode": 128523}, + {"name": "RELIEVED FACE", "unicode": 128524}, + {"name": "SMILING FACE WITH HEART-SHAPED EYES", "unicode": 128525}, + {"name": "SMIRKING FACE", "unicode": 128527}, + {"name": "UNAMUSED FACE", "unicode": 128530}, + {"name": "FACE WITH COLD SWEAT", "unicode": 128531}, + {"name": "PENSIVE FACE", "unicode": 128532}, + {"name": "CONFOUNDED FACE", "unicode": 128534}, + {"name": "FACE THROWING A KISS", "unicode": 128536}, + {"name": "KISSING FACE WITH CLOSED EYES", "unicode": 128538}, + {"name": "FACE WITH STUCK-OUT TONGUE AND WINKING EYE", "unicode": 128540}, + { + "name": "FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES", + "unicode": 128541 + }, + {"name": "DISAPPOINTED FACE", "unicode": 128542}, + {"name": "ANGRY FACE", "unicode": 128544}, + {"name": "POUTING FACE", "unicode": 128545}, + {"name": "CRYING FACE", "unicode": 128546}, + {"name": "PERSEVERING FACE", "unicode": 128547}, + {"name": "FACE WITH LOOK OF TRIUMPH", "unicode": 128548}, + {"name": "DISAPPOINTED BUT RELIEVED FACE", "unicode": 128549}, + {"name": "FEARFUL FACE", "unicode": 128552}, + {"name": "WEARY FACE", "unicode": 128553}, + {"name": "SLEEPY FACE", "unicode": 128554}, + {"name": "TIRED FACE", "unicode": 128555}, + {"name": "LOUDLY CRYING FACE", "unicode": 128557}, + {"name": "FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128560}, + {"name": "FACE SCREAMING IN FEAR", "unicode": 128561}, + {"name": "ASTONISHED FACE", "unicode": 128562}, + {"name": "FLUSHED FACE", "unicode": 128563}, + {"name": "DIZZY FACE", "unicode": 128565}, + {"name": "FACE WITH MEDICAL MASK", "unicode": 128567}, + {"name": "GRINNING CAT FACE WITH SMILING EYES", "unicode": 128568}, + {"name": "CAT FACE WITH TEARS OF JOY", "unicode": 128569}, + {"name": "SMILING CAT FACE WITH OPEN MOUTH", "unicode": 128570}, + {"name": "SMILING CAT FACE WITH HEART-SHAPED EYES", "unicode": 128571}, + {"name": "CAT FACE WITH WRY SMILE", "unicode": 128572}, + {"name": "KISSING CAT FACE WITH CLOSED EYES", "unicode": 128573}, + {"name": "POUTING CAT FACE", "unicode": 128574}, + {"name": "CRYING CAT FACE", "unicode": 128575}, + {"name": "WEARY CAT FACE", "unicode": 128576}, + {"name": "FACE WITH NO GOOD GESTURE", "unicode": 128581}, + {"name": "FACE WITH OK GESTURE", "unicode": 128582}, + {"name": "PERSON BOWING DEEPLY", "unicode": 128583}, + {"name": "SEE-NO-EVIL MONKEY", "unicode": 128584}, + {"name": "HEAR-NO-EVIL MONKEY", "unicode": 128585}, + {"name": "SPEAK-NO-EVIL MONKEY", "unicode": 128586}, + {"name": "HAPPY PERSON RAISING ONE HAND", "unicode": 128587}, + {"name": "PERSON RAISING BOTH HANDS IN CELEBRATION", "unicode": 128588}, + {"name": "PERSON FROWNING", "unicode": 128589}, + {"name": "PERSON WITH POUTING FACE", "unicode": 128590}, + {"name": "PERSON WITH FOLDED HANDS", "unicode": 128591}, + {"name": "BLACK SCISSORS", "unicode": 9986}, + {"name": "WHITE HEAVY CHECK MARK", "unicode": 9989}, + {"name": "AIRPLANE", "unicode": 9992}, + {"name": "ENVELOPE", "unicode": 9993}, + {"name": "RAISED FIST", "unicode": 9994}, + {"name": "RAISED HAND", "unicode": 9995}, + {"name": "VICTORY HAND", "unicode": 9996}, + {"name": "PENCIL", "unicode": 9999}, + {"name": "BLACK NIB", "unicode": 10002}, + {"name": "HEAVY CHECK MARK", "unicode": 10004}, + {"name": "HEAVY MULTIPLICATION X", "unicode": 10006}, + {"name": "SPARKLES", "unicode": 10024}, + {"name": "EIGHT SPOKED ASTERISK", "unicode": 10035}, + {"name": "EIGHT POINTED BLACK STAR", "unicode": 10036}, + {"name": "SNOWFLAKE", "unicode": 10052}, + {"name": "SPARKLE", "unicode": 10055}, + {"name": "CROSS MARK", "unicode": 10060}, + {"name": "NEGATIVE SQUARED CROSS MARK", "unicode": 10062}, + {"name": "BLACK QUESTION MARK ORNAMENT", "unicode": 10067}, + {"name": "WHITE QUESTION MARK ORNAMENT", "unicode": 10068}, + {"name": "WHITE EXCLAMATION MARK ORNAMENT", "unicode": 10069}, + {"name": "HEAVY EXCLAMATION MARK SYMBOL", "unicode": 10071}, + {"name": "HEAVY BLACK HEART", "unicode": 10084}, + {"name": "HEAVY PLUS SIGN", "unicode": 10133}, + {"name": "HEAVY MINUS SIGN", "unicode": 10134}, + {"name": "HEAVY DIVISION SIGN", "unicode": 10135}, + {"name": "BLACK RIGHTWARDS ARROW", "unicode": 10145}, + {"name": "CURLY LOOP", "unicode": 10160}, + {"name": "ROCKET", "unicode": 128640}, + {"name": "RAILWAY CAR", "unicode": 128643}, + {"name": "HIGH-SPEED TRAIN", "unicode": 128644}, + {"name": "HIGH-SPEED TRAIN WITH BULLET NOSE", "unicode": 128645}, + {"name": "METRO", "unicode": 128647}, + {"name": "STATION", "unicode": 128649}, + {"name": "BUS", "unicode": 128652}, + {"name": "BUS STOP", "unicode": 128655}, + {"name": "AMBULANCE", "unicode": 128657}, + {"name": "FIRE ENGINE", "unicode": 128658}, + {"name": "POLICE CAR", "unicode": 128659}, + {"name": "TAXI", "unicode": 128661}, + {"name": "AUTOMOBILE", "unicode": 128663}, + {"name": "RECREATIONAL VEHICLE", "unicode": 128665}, + {"name": "DELIVERY TRUCK", "unicode": 128666}, + {"name": "SHIP", "unicode": 128674}, + {"name": "SPEEDBOAT", "unicode": 128676}, + {"name": "HORIZONTAL TRAFFIC LIGHT", "unicode": 128677}, + {"name": "CONSTRUCTION SIGN", "unicode": 128679}, + {"name": "POLICE CARS REVOLVING LIGHT", "unicode": 128680}, + {"name": "TRIANGULAR FLAG ON POST", "unicode": 128681}, + {"name": "DOOR", "unicode": 128682}, + {"name": "NO ENTRY SIGN", "unicode": 128683}, + {"name": "SMOKING SYMBOL", "unicode": 128684}, + {"name": "NO SMOKING SYMBOL", "unicode": 128685}, + {"name": "BICYCLE", "unicode": 128690}, + {"name": "PEDESTRIAN", "unicode": 128694}, + {"name": "MENS SYMBOL", "unicode": 128697}, + {"name": "WOMENS SYMBOL", "unicode": 128698}, + {"name": "RESTROOM", "unicode": 128699}, + {"name": "BABY SYMBOL", "unicode": 128700}, + {"name": "TOILET", "unicode": 128701}, + {"name": "WATER CLOSET", "unicode": 128702}, + {"name": "BATH", "unicode": 128704}, + {"name": "CIRCLED LATIN CAPITAL LETTER M", "unicode": 9410}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER A", "unicode": 127344}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER B", "unicode": 127345}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER O", "unicode": 127358}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER P", "unicode": 127359}, + {"name": "NEGATIVE SQUARED AB", "unicode": 127374}, + {"name": "SQUARED CL", "unicode": 127377}, + {"name": "SQUARED COOL", "unicode": 127378}, + {"name": "SQUARED FREE", "unicode": 127379}, + {"name": "SQUARED ID", "unicode": 127380}, + {"name": "SQUARED NEW", "unicode": 127381}, +]; +``` + +[](id:contact) + +## 联系我们 + +如果您在接入使用过程中有任何疑问,请扫码加入微信群,或加入QQ群:788910197 咨询。 + +![](https://qcloudimg.tencent-cloud.cn/raw/e830ae8c7b8d9253eb71e7c3d9f7b2be.png) + diff --git a/doc/表情_en.md b/doc/表情_en.md new file mode 100644 index 0000000..3f5ddc2 --- /dev/null +++ b/doc/表情_en.md @@ -0,0 +1,457 @@ + +## Overview + +Tencent Cloud Chat Flutter TUIKit provides powerful Emoji and Sticker modules to help you customize the Emoji and Sticker sharing of your app. + +Through simple configurations, you can easily choose and integrate those three types of stickers to your app. + +| Sticker Type | Message Type | Embed to text | Sending content | Render | Import | Provide by default | +|---------|---------|---------|---------|---------|---------|---------| +| [Unicode](https://unicode.org/emoji/charts/full-emoji-list.html) Emoji | Text Message | Yes | [Unicode](https://unicode.org/emoji/charts/full-emoji-list.html) |[Unicode](https://unicode.org/emoji/charts/full-emoji-list.html) to Emoji can be compiled automatically by devices, while different devices or platforms have different Emoji rendering | [Unicode](https://unicode.org/emoji/charts/full-emoji-list.html) List | Sample [Unicode](https://unicode.org/emoji/charts/full-emoji-list.html) List is provided [here](#unicode) | +| Small Image Emoji | Text Message | Yes | Image name | Match local Asset image resources according to name automatically | Image stored in asset, and define `List` | A set of QQ Emoji is provided by default | +| Big Image Sticker | Sticker Message | No | `baseURL` join with image name, as asset path | Render image from asset | Image stored in asset, and define `List` | - | + +![](https://qcloudimg.tencent-cloud.cn/raw/023c3c716b481401c8da763e66ba08d1.png) + +Now, let's start integrating Emoji and Sticker to your app with TUIKit. + +>? The usage of this module has been modified since the 1.1.0 version of [TUIKit](https://pub.dev/packages/tencent_cloud_chat_uikit). Please check all the parts in this tutorial if you upgrade the version. + +## STEP 1: Customize Image Emoji and Sticker + +>? **This step is optional:** +> This step is necessary only if image stickers, except default QQ emoji one, includes both small and big, are needed. +> QQ Emoji set is provided by default, and is unnecessary to import in this step. + +### Import Image File to Project + +Please add your image resources file to `assets/custom_face_resource/` of your project, including both small and big images. + +In this directory, separate subdirectory with different sticker packages, means each Tabs on Sticker panel. Only one type of sticker is allowed in each Tab(package or subdirectory). + +Name those subdirectories differently, and this name will be used as the `name` field of `CustomEmojiFaceData` and `CustomStickerPackage` in the following steps. Please allocate the name as you need. + +Also, please make sure that all image resource files do not have the same name. + +You can refer to our [sample project](https://github.com/TencentCloud/chat-demo-flutter/tree/main/assets/custom_face_resource), if not clear. + +![](https://qcloudimg.tencent-cloud.cn/raw/060d5846a3ad0f5078f40eb05686f9ec.png) + +### Add assets to app + +Open `pubspec.yaml`, add those following lines to `flutter` => `assets`. + +```yaml +flutter: + assets: + - assets/custom_face_resource/ +``` + +### Configure assets list + +>? The sample code for this part can be found [here](https://github.com/TencentCloud/chat-demo-flutter/blob/main/lib/utils/constant.dart), mainly focused on `emojiList`. + +Define a static `List` in your project, aiming for transferring the local image assets to TUIKit, as List. + +In this `List`, each item is `CustomEmojiFaceData`, while it constitutes each Tab in the sticker panel. + +```dart +CustomEmojiFaceData( + { + String name, // The name of the package and subdirectory. + String icon, // The file name of the icon on the Tab. + List list, // The list of the files name. + bool isEmoji //Whether it contains small image emojis, default is big image stickers. + } +); +``` + +Sample Code: + +```dart +static final List emojiList = [ + // Small Image Emoji, embedded in text messages. + CustomEmojiFaceData( + name: '4349', + icon: "aircraft.png", + isEmoji: true, + list: [ + "aircraft.png", + "alarmClock.png", + "anger.png", + // ... + ]), + + // Big image stickers, sent as sticker messages independently. + CustomEmojiFaceData( + name: '4350', + icon: "menu@2x.png", + list: [ + "yz00@2x.png", + // ... + ]), +] +``` + +## Step 2: Customize the Unicode Emoji List + +>? **This step is optional:** +> This step is necessary only if Unicode Emoji is needed. + +Define a static `List>` of Unicode in your project, you can build it based on the [sample list we provided](#unicode). + +You can add, delete and modify some items in this List, based on the official [Unicode](https://unicode.org/emoji/charts/full-emoji-list.html). + + +## Step 3: Cache the Emoji and Sticker to memory + +>? +> - Sample code for this step [can be found here](https://github.com/TencentCloud/chat-demo-flutter/blob/main/lib/src/pages/app.dart), mainly focus on `setCustomSticker` function. +> - QQ Emoji has been embedded by default, and unnecessary to do this step. + +Cache those Emoji and Stickers to global `Provider`, memory, **just after your app launched, and before the first `TIMUIKitChat` shows**. + +**This steps should only be done once.** Aiming for reducing the load of memory IO, as rendering each sticker is a high frequency event, and will cost a lot. + +The instance of each sticker is generated by the following `CustomSticker` class. It will show Unicode Emoji if `unicode` is not null, otherwise it shows an image. + +```dart +class CustomSticker { + int? unicode; // Unicode int value。It will show Unicode Emoji if this field is not null, otherwise it shows an image. + String name; // The name of the sticker + int index; // The index of the sticker + bool isEmoji; // Whether it is a small image emoji, while a big image sticker is as default. +} +``` + +The instance of each Tab on sticker panel, each sticker package, is generated by the `CustomStickerPackage` class. + +```dart +class CustomStickerPackage { // Each Tab on sticker panel, each sticker package + String name; // The name of this sticker package, subdirectory, and the Tab. + String? baseUrl; // Sticker package baseUrl,recommend specify as "assets/custom_face_resource/${package name}" + List stickerList; // The list of the image files name + CustomSticker menuItem; // The file name of the icon of Tab + bool isEmoji; // Whether it contains small image emojis, while big image stickers are as default. +} +``` + +For the classes shown above, we provide sample codes as follows, for the code you may need to write. + +`Solution A` shows the usage of Unicode Emoji while `Solution B` shows the usage of image stickers. You can choose all or part of them as needed. + + +```dart +setCustomSticker() async { + // Define a list to store sticker packages. + List customStickerPackageList = []; + + // Solution A: Use Emoji Unicode list. Can be added to text messages. + // `emojiData` comes from step 2. + final defEmojiList = emojiData.asMap().keys.map((emojiIndex) { + final emoji = Emoji.fromJson(emojiData[emojiIndex]); + return CustomSticker( + index: emojiIndex, name: emoji.name, unicode: emoji.unicode); + }).toList(); + customStickerPackageList.add(CustomStickerPackage( + name: "defaultEmoji", + stickerList: defEmojiList, + menuItem: defEmojiList[0])); + + // Solution B: Use the image sticker. + // Please make sure `customEmojiPackage.name` is the name of the subdirectory. + customStickerPackageList.addAll(Const.emojiList.map((customEmojiPackage) { + return CustomStickerPackage( + name: customEmojiPackage.name, + baseUrl: "assets/custom_face_resource/${customEmojiPackage.name}", + stickerList: customEmojiPackage.list + .asMap() + .keys + .map((idx) => + CustomSticker(index: idx, name: customEmojiPackage.list[idx])) + .toList(), + menuItem: CustomSticker( + index: 0, + name: customEmojiPackage.icon, + )); + }).toList()); + + Provider.of(context, listen: false) + .customStickerPackageList = customStickerPackageList; +} +``` + +## STEP 4: Adding those stickers to TIMUIKitChat + +>? +> - Sample code for this step [can be found here](https://github.com/TencentCloud/chat-demo-flutter/blob/main/lib/src/chat.dart), mainly focus on `renderCustomStickerPanel`, `customStickerPanel` and `customEmojiList`. + +Copy the following codes to the class that contains the `TIMUIKitChat` widget directly. + +```dart +Widget renderCustomStickerPanel({ + sendTextMessage, + sendFaceMessage, + deleteText, + addCustomEmojiText, + addText, + List defaultCustomEmojiStickerList = const [], +}) { + final theme = Provider.of(context).theme; + final customStickerPackageList = + Provider.of(context).customStickerPackageList; + final defaultEmojiList = + defaultCustomEmojiStickerList.map((customEmojiPackage) { + return CustomStickerPackage( + name: customEmojiPackage.name, + baseUrl: "assets/custom_face_resource/${customEmojiPackage.name}", + isEmoji: customEmojiPackage.isEmoji, + isDefaultEmoji: true, + stickerList: customEmojiPackage.list + .asMap() + .keys + .map((idx) => + CustomSticker(index: idx, name: customEmojiPackage.list[idx])) + .toList(), + menuItem: CustomSticker( + index: 0, + name: customEmojiPackage.icon, + )); + }).toList(); + return StickerPanel( + sendTextMsg: sendTextMessage, + sendFaceMsg: (index, data) => + sendFaceMessage(index + 1, (data.split("/")[3]).split("@")[0]), + deleteText: deleteText, + addText: addText, + addCustomEmojiText: addCustomEmojiText, + customStickerPackageList: [ + ...defaultEmojiList, + ...customStickerPackageList + ], + backgroundColor: theme.weakBackgroundColor, + lightPrimaryColor: theme.lightPrimaryColor); +} +``` + +### STEP 4.1: Render Small Image Emoji + +>? **This step is optional:** +> - This step is necessary only if small images emoji are needed for your app, except the QQ Emoji we provided by default. +> - Unicode Emoji and small image emoji are similar, it is not recommended to integrate these two types of emoji at the same time. + +- STEP 4.1(a) shows the usage of using custom small image emoji. +- STEP 4.1(b) shows the usage of using default QQ emojis. + +It is recommended to choose one of them. + +If you tend to use both of them, please make sure those image resource files do not have the same name. + +#### STEP 4.1(a): Render custom small image emoji + +Add a `List customEmojiList` field to the `build` function of the `Widget` that contains `TIMUIKitChat`, storing the list of small image emoji. + +```dart +List customEmojiList = + Const.emojiList.where((element) => element.isEmoji == true).toList(); +``` + +And transferring this list to `customEmojiStickerList` of `TIMUIKitChat`. + +```dart +return TIMUIKitChat( + customEmojiStickerList: customEmojiList, + // ...... +); +``` + +>? +> If this widget is a `StatefulWidget`, choosing to place this list to state, and execute the `where` method once, to improve the performance are recommended. + +#### STEP 4.1(b): Enable QQ Emoji + +Enable the `isUseDefaultEmoji` of `TIMUIKitChatConfig` from `TIMUIKitChat` to `true`. Meanwhile, a Tab shows the default QQ Emoji will occur on the left of the sticker panel. + +```dart +return TIMUIKitChat( + config: TIMUIKitChatConfig( + isUseDefaultEmoji: true, + // ...... + ), + // ...... +); +``` + +![](https://qcloudimg.tencent-cloud.cn/raw/ed14b886c08cb1c0e8371ba54925bd71.png) + +### STEP 4.2: Add the sticker panel to TIMUIKitChat + +Transfer the function, you copied in this step, to the `customStickerPanel` field of `TIMUIKitChat`. + +```dart +return TIMUIKitChat( + customStickerPanel: renderCustomStickerPanel, + // ...... +); +``` + +That's all you need to integrate Emoji and Sticker modules to your app, with Tencent Cloud Chat Flutter TUIKit. + +[](id:unicode) + +## Appendix: Sample list of Emoji Unicodes + +The list is for sample and presentation purposes only, you can modify it as you need. + +```dart +List> emojiData = [ + {"name": "GRINNING FACE WITH SMILING EYES", "unicode": 128513}, + {"name": "FACE WITH TEARS OF JOY", "unicode": 128514}, + {"name": "SMILING FACE WITH OPEN MOUTH", "unicode": 128515}, + {"name": "SMILING FACE WITH OPEN MOUTH AND SMILING EYES", "unicode": 128516}, + {"name": "SMILING FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128517}, + { + "name": "SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES", + "unicode": 128518 + }, + {"name": "WINKING FACE", "unicode": 128521}, + {"name": "SMILING FACE WITH SMILING EYES", "unicode": 128522}, + {"name": "FACE SAVOURING DELICIOUS FOOD", "unicode": 128523}, + {"name": "RELIEVED FACE", "unicode": 128524}, + {"name": "SMILING FACE WITH HEART-SHAPED EYES", "unicode": 128525}, + {"name": "SMIRKING FACE", "unicode": 128527}, + {"name": "UNAMUSED FACE", "unicode": 128530}, + {"name": "FACE WITH COLD SWEAT", "unicode": 128531}, + {"name": "PENSIVE FACE", "unicode": 128532}, + {"name": "CONFOUNDED FACE", "unicode": 128534}, + {"name": "FACE THROWING A KISS", "unicode": 128536}, + {"name": "KISSING FACE WITH CLOSED EYES", "unicode": 128538}, + {"name": "FACE WITH STUCK-OUT TONGUE AND WINKING EYE", "unicode": 128540}, + { + "name": "FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES", + "unicode": 128541 + }, + {"name": "DISAPPOINTED FACE", "unicode": 128542}, + {"name": "ANGRY FACE", "unicode": 128544}, + {"name": "POUTING FACE", "unicode": 128545}, + {"name": "CRYING FACE", "unicode": 128546}, + {"name": "PERSEVERING FACE", "unicode": 128547}, + {"name": "FACE WITH LOOK OF TRIUMPH", "unicode": 128548}, + {"name": "DISAPPOINTED BUT RELIEVED FACE", "unicode": 128549}, + {"name": "FEARFUL FACE", "unicode": 128552}, + {"name": "WEARY FACE", "unicode": 128553}, + {"name": "SLEEPY FACE", "unicode": 128554}, + {"name": "TIRED FACE", "unicode": 128555}, + {"name": "LOUDLY CRYING FACE", "unicode": 128557}, + {"name": "FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128560}, + {"name": "FACE SCREAMING IN FEAR", "unicode": 128561}, + {"name": "ASTONISHED FACE", "unicode": 128562}, + {"name": "FLUSHED FACE", "unicode": 128563}, + {"name": "DIZZY FACE", "unicode": 128565}, + {"name": "FACE WITH MEDICAL MASK", "unicode": 128567}, + {"name": "GRINNING CAT FACE WITH SMILING EYES", "unicode": 128568}, + {"name": "CAT FACE WITH TEARS OF JOY", "unicode": 128569}, + {"name": "SMILING CAT FACE WITH OPEN MOUTH", "unicode": 128570}, + {"name": "SMILING CAT FACE WITH HEART-SHAPED EYES", "unicode": 128571}, + {"name": "CAT FACE WITH WRY SMILE", "unicode": 128572}, + {"name": "KISSING CAT FACE WITH CLOSED EYES", "unicode": 128573}, + {"name": "POUTING CAT FACE", "unicode": 128574}, + {"name": "CRYING CAT FACE", "unicode": 128575}, + {"name": "WEARY CAT FACE", "unicode": 128576}, + {"name": "FACE WITH NO GOOD GESTURE", "unicode": 128581}, + {"name": "FACE WITH OK GESTURE", "unicode": 128582}, + {"name": "PERSON BOWING DEEPLY", "unicode": 128583}, + {"name": "SEE-NO-EVIL MONKEY", "unicode": 128584}, + {"name": "HEAR-NO-EVIL MONKEY", "unicode": 128585}, + {"name": "SPEAK-NO-EVIL MONKEY", "unicode": 128586}, + {"name": "HAPPY PERSON RAISING ONE HAND", "unicode": 128587}, + {"name": "PERSON RAISING BOTH HANDS IN CELEBRATION", "unicode": 128588}, + {"name": "PERSON FROWNING", "unicode": 128589}, + {"name": "PERSON WITH POUTING FACE", "unicode": 128590}, + {"name": "PERSON WITH FOLDED HANDS", "unicode": 128591}, + {"name": "BLACK SCISSORS", "unicode": 9986}, + {"name": "WHITE HEAVY CHECK MARK", "unicode": 9989}, + {"name": "AIRPLANE", "unicode": 9992}, + {"name": "ENVELOPE", "unicode": 9993}, + {"name": "RAISED FIST", "unicode": 9994}, + {"name": "RAISED HAND", "unicode": 9995}, + {"name": "VICTORY HAND", "unicode": 9996}, + {"name": "PENCIL", "unicode": 9999}, + {"name": "BLACK NIB", "unicode": 10002}, + {"name": "HEAVY CHECK MARK", "unicode": 10004}, + {"name": "HEAVY MULTIPLICATION X", "unicode": 10006}, + {"name": "SPARKLES", "unicode": 10024}, + {"name": "EIGHT SPOKED ASTERISK", "unicode": 10035}, + {"name": "EIGHT POINTED BLACK STAR", "unicode": 10036}, + {"name": "SNOWFLAKE", "unicode": 10052}, + {"name": "SPARKLE", "unicode": 10055}, + {"name": "CROSS MARK", "unicode": 10060}, + {"name": "NEGATIVE SQUARED CROSS MARK", "unicode": 10062}, + {"name": "BLACK QUESTION MARK ORNAMENT", "unicode": 10067}, + {"name": "WHITE QUESTION MARK ORNAMENT", "unicode": 10068}, + {"name": "WHITE EXCLAMATION MARK ORNAMENT", "unicode": 10069}, + {"name": "HEAVY EXCLAMATION MARK SYMBOL", "unicode": 10071}, + {"name": "HEAVY BLACK HEART", "unicode": 10084}, + {"name": "HEAVY PLUS SIGN", "unicode": 10133}, + {"name": "HEAVY MINUS SIGN", "unicode": 10134}, + {"name": "HEAVY DIVISION SIGN", "unicode": 10135}, + {"name": "BLACK RIGHTWARDS ARROW", "unicode": 10145}, + {"name": "CURLY LOOP", "unicode": 10160}, + {"name": "ROCKET", "unicode": 128640}, + {"name": "RAILWAY CAR", "unicode": 128643}, + {"name": "HIGH-SPEED TRAIN", "unicode": 128644}, + {"name": "HIGH-SPEED TRAIN WITH BULLET NOSE", "unicode": 128645}, + {"name": "METRO", "unicode": 128647}, + {"name": "STATION", "unicode": 128649}, + {"name": "BUS", "unicode": 128652}, + {"name": "BUS STOP", "unicode": 128655}, + {"name": "AMBULANCE", "unicode": 128657}, + {"name": "FIRE ENGINE", "unicode": 128658}, + {"name": "POLICE CAR", "unicode": 128659}, + {"name": "TAXI", "unicode": 128661}, + {"name": "AUTOMOBILE", "unicode": 128663}, + {"name": "RECREATIONAL VEHICLE", "unicode": 128665}, + {"name": "DELIVERY TRUCK", "unicode": 128666}, + {"name": "SHIP", "unicode": 128674}, + {"name": "SPEEDBOAT", "unicode": 128676}, + {"name": "HORIZONTAL TRAFFIC LIGHT", "unicode": 128677}, + {"name": "CONSTRUCTION SIGN", "unicode": 128679}, + {"name": "POLICE CARS REVOLVING LIGHT", "unicode": 128680}, + {"name": "TRIANGULAR FLAG ON POST", "unicode": 128681}, + {"name": "DOOR", "unicode": 128682}, + {"name": "NO ENTRY SIGN", "unicode": 128683}, + {"name": "SMOKING SYMBOL", "unicode": 128684}, + {"name": "NO SMOKING SYMBOL", "unicode": 128685}, + {"name": "BICYCLE", "unicode": 128690}, + {"name": "PEDESTRIAN", "unicode": 128694}, + {"name": "MENS SYMBOL", "unicode": 128697}, + {"name": "WOMENS SYMBOL", "unicode": 128698}, + {"name": "RESTROOM", "unicode": 128699}, + {"name": "BABY SYMBOL", "unicode": 128700}, + {"name": "TOILET", "unicode": 128701}, + {"name": "WATER CLOSET", "unicode": 128702}, + {"name": "BATH", "unicode": 128704}, + {"name": "CIRCLED LATIN CAPITAL LETTER M", "unicode": 9410}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER A", "unicode": 127344}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER B", "unicode": 127345}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER O", "unicode": 127358}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER P", "unicode": 127359}, + {"name": "NEGATIVE SQUARED AB", "unicode": 127374}, + {"name": "SQUARED CL", "unicode": 127377}, + {"name": "SQUARED COOL", "unicode": 127378}, + {"name": "SQUARED FREE", "unicode": 127379}, + {"name": "SQUARED ID", "unicode": 127380}, + {"name": "SQUARED NEW", "unicode": 127381}, +]; +``` + +[](id:contact) + +## Contact Us + +If there's anything unclear or you have more ideas, feel free to contact us! + +- Telegram Group: https://t.me/+1doS9AUBmndhNGNl +- WhatsApp Group: https://chat.whatsapp.com/Gfbxk7rQBqc8Rz4pzzP27A + + diff --git a/doc/表情_国际中文.md b/doc/表情_国际中文.md new file mode 100644 index 0000000..de10516 --- /dev/null +++ b/doc/表情_国际中文.md @@ -0,0 +1,454 @@ + +以下为您介绍,如何为腾讯云IM Flutter TUIKit引入表情能力。 + +我们的 `TIMUIKitChat` 组件中,支持发送及接收三种类型的表情: + +| 表情类型 | 发送形式 | 是否文字混排 | 发送内容 | 解析方式 | 引入方式 | TUIKit默认自带 | +|---------|---------|---------|---------|---------|---------|---------| +| [Unicode](https://unicode.org/emoji/charts/full-emoji-list.html) Emoji表情 | 文本消息 | 是 | [Unicode](https://unicode.org/emoji/charts/full-emoji-list.html)编码 | 设备自动将[Unicode](https://unicode.org/emoji/charts/full-emoji-list.html)编码解析成小表情。不同的设备,对[Unicode](https://unicode.org/emoji/charts/full-emoji-list.html)解析后的图形,略有不同 | [Unicode](https://unicode.org/emoji/charts/full-emoji-list.html) List | 文档中提供一套[默认Unicode列表示例](#unicode) | +| 小图片表情 | 文本消息 | 是 | 表情图片名称 | 根据名称,自动匹配本地Asset图片资源 | 图片资源预存于Asset,并定义 `List` | 一套 QQ 同款小表情图库,可直接使用 | +| 大图片表情 | 表情消息 | 否 | `baseURL` 拼接图片文件名,表情图片Asset路径 | 通过路径,解析Asset资源 | 图片资源预存于Asset,并定义 `List` | - | + +![](https://qcloudimg.tencent-cloud.cn/raw/023c3c716b481401c8da763e66ba08d1.png) + +现在,我们就来动手接入TUIKit的表情能力。 + +>? [TUIKit](https://pub.dev/packages/tencent_cloud_chat_uikit)在升级至1.1.0版本后,对表情能力用法有较大改动。请您在升级最新版后,根据本文档指引,重新适配接入表情能力。谢谢~ + +## STEP1: 自定义表情图片资源 + +>? **本步骤选做:** +> 如果您需要用到非默认提供的QQ小表情外的其他图片表情,如自定义图片小表情及图片大表情,才需完成本步骤。 +> QQ小表情包,TUIKit已自带提供,无需在本步骤引入,请关注后续步骤。 + +### 将文件导入项目 + +请将您的表情资源文件,导入项目的 `assets/custom_face_resource/` 目录内。无论是图片大表情,亦或是图片小表情,都需按此步骤引入。 + +该目录内,请使用不同的文件夹,区分表情面板中的不同Tab。每个Tab内表情,仅支持一种类型,图片大表情或图片小表情。 + +文件夹的名称,请使用该Tab的 `name` 命名。该命名不会对客户展现,请根据开发需要,自定义即可。 + +请保证,所有表情资源文件,不要重名。 + +此路径的表情图片放置引入,可参考我们的[Demo](https://github.com/TencentCloud/chat-demo-flutter/tree/main/assets/custom_face_resource)。 + +![](https://qcloudimg.tencent-cloud.cn/raw/060d5846a3ad0f5078f40eb05686f9ec.png) + +### 声明表情文件 + +打开 `pubspec.yaml` 文件,在 `flutter` => `assets` 中,声明刚刚引入的表情资源文件。 + +```yaml +flutter: + assets: + - assets/custom_face_resource/ +``` + +### 在代码中配置图片资源List + +>? 本步骤代码示例请[参考此处](https://github.com/TencentCloud/chat-demo-flutter/blob/main/lib/utils/constant.dart),直接看 `emojiList` 即可。 + +在您代码定义静态参数或配置的地方,定义一个 `static List`,用于将本地图片资源,转换成TUIKit可以接受的格式,后续以 `List` 方式传入。 + +此 `List` 中,每个item都是 `CustomEmojiFaceData`,每个 `CustomEmojiFaceData` 构成一个表情面板中的Tab。具体参数说明如下: + +```dart +CustomEmojiFaceData( + { + String name, // 文件夹目录名称 + String icon, // Tab中的icon资源文件名 + List list, // 每个图片的文件名,以List + bool isEmoji // 是否为图片小表情,默认为false,即图片大表情 + } +); +``` + +示例代码如下: + +```dart +static final List emojiList = [ + // 使用图片小表情,支持图文混排,以文本消息形式发送 + CustomEmojiFaceData( + name: '4349', + icon: "aircraft.png", + isEmoji: true, + list: [ + "aircraft.png", + "alarmClock.png", + "anger.png", + // ... + ]), + + // 使用图片大表情,不支持图文混排,以表情消息形式发送 + CustomEmojiFaceData( + name: '4350', + icon: "menu@2x.png", + list: [ + "yz00@2x.png", + // ... + ]), +] +``` + +## STEP2: 自定义Emoji Unicode 字符串List + +>? **本步骤选做:** +> 如果您需要用到[Unicode](https://unicode.org/emoji/charts/full-emoji-list.html) Emoji表情,才需完成本步骤。 + +在您代码定义静态参数或配置的地方,定义一个 `List>` Unicode 列表,供传入。 + +该列表,我们提供一套示例,在[附录](#unicode)中。 + +您看直接复制引入这套示例列表,或基于此修改。 + +## STEP3: 表情资源预读入内存 + +>? +> 本步骤代码示例请[参考此处](https://github.com/TencentCloud/chat-demo-flutter/blob/main/lib/src/pages/app.dart),直接看 `setCustomSticker` 方法即可。 +> QQ小表情包,TUIKit已自带提供,无需在本步骤引入,请关注后续步骤。 + +在您的项目启动后,首个 `TIMUIKitChat` 组件渲染前,将上一步定义的图片表情资源List,转换成TUIKit表情的实例,放入全局Provider中,存储于内存里。 + +**本步骤方法仅需执行一次,一次性全部读入内存中。** 因展示渲染表情资源为高频操作,如每次展示前才动态读入内存,对资源与性能占用比较大。 + +单个表情内存实例,使用 `CustomSticker` 类生成。如果传入了 `unicode` 则为 Unicode Emoji表情,否则为图片类型表情。 + +```dart +class CustomSticker { + int? unicode; // Unicode int值。如果传入了 `unicode` 则为 Unicode Emoji表情,否则为图片类型表情 + String name; // 表情名称 + int index; // 表情序号 + bool isEmoji; // 是否为图片小表情,默认为图片大表情 +} +``` + +每个Tab的内存实例,使用 `CustomStickerPackage` 类生成。 + +```dart +class CustomStickerPackage { // 一个系列的表情包定义为一个package,占据一个表情面板Tab + String name; // 表情包package name,该Tab文件夹名称。 + String? baseUrl; // 表情包package baseUrl,建议配置成:"assets/custom_face_resource/${表情包文件夹名称 即 表情包package name}" + List stickerList; // 表情资源列表 + CustomSticker menuItem; // 表情面包Tab按钮icon + bool isEmoji; // 是否为图片小表情,默认为图片大表情 +} +``` + +综上所述,需要写的代码,我们给出示例版本。 + +表情项一演示如何使用Emoji Unicode表情包,表情项二演示如何使用图片类型(包含大或小)表情包。您可以根据需要,使用全部或部分代码。 + +```dart +setCustomSticker() async { + // 定义一个大List来承载各个表情包 package Tab + List customStickerPackageList = []; + + // 表情项一:使用Emoji Unicode表情列表。可以嵌入文字内容中。 + // `emojiData` 来自于STEP2。 + final defEmojiList = emojiData.asMap().keys.map((emojiIndex) { + final emoji = Emoji.fromJson(emojiData[emojiIndex]); + return CustomSticker( + index: emojiIndex, name: emoji.name, unicode: emoji.unicode); + }).toList(); + customStickerPackageList.add(CustomStickerPackage( + name: "defaultEmoji", + stickerList: defEmojiList, + menuItem: defEmojiList[0])); + + // 表情项二:使用您提供的图片表情包。 + // 务必保证 `customEmojiPackage.name` 为该Tab文件夹名称。 + // `Const.emojiList` 来自于STEP1。 + customStickerPackageList.addAll(Const.emojiList.map((customEmojiPackage) { + return CustomStickerPackage( + name: customEmojiPackage.name, + baseUrl: "assets/custom_face_resource/${customEmojiPackage.name}", + stickerList: customEmojiPackage.list + .asMap() + .keys + .map((idx) => + CustomSticker(index: idx, name: customEmojiPackage.list[idx])) + .toList(), + menuItem: CustomSticker( + index: 0, + name: customEmojiPackage.icon, + )); + }).toList()); + + Provider.of(context, listen: false) + .customStickerPackageList = customStickerPackageList; +} +``` + +## STEP4: 为 TIMUIKitChat 组件添加表情解析能力 + +>? +> 本步骤代码示例请[参考此处](https://github.com/TencentCloud/chat-demo-flutter/blob/main/lib/src/chat.dart),重点浏览 `renderCustomStickerPanel`, `customStickerPanel` 及 `customEmojiList` 即可。 + +将以下代码,直接拷贝进入您用于承载 `TIMUIKitChat` 组件的类中。 + +```dart +Widget renderCustomStickerPanel({ + sendTextMessage, + sendFaceMessage, + deleteText, + addCustomEmojiText, + addText, + List defaultCustomEmojiStickerList = const [], +}) { + final theme = Provider.of(context).theme; + final customStickerPackageList = + Provider.of(context).customStickerPackageList; + final defaultEmojiList = + defaultCustomEmojiStickerList.map((customEmojiPackage) { + return CustomStickerPackage( + name: customEmojiPackage.name, + baseUrl: "assets/custom_face_resource/${customEmojiPackage.name}", + isEmoji: customEmojiPackage.isEmoji, + isDefaultEmoji: true, + stickerList: customEmojiPackage.list + .asMap() + .keys + .map((idx) => + CustomSticker(index: idx, name: customEmojiPackage.list[idx])) + .toList(), + menuItem: CustomSticker( + index: 0, + name: customEmojiPackage.icon, + )); + }).toList(); + return StickerPanel( + sendTextMsg: sendTextMessage, + sendFaceMsg: (index, data) => + sendFaceMessage(index + 1, (data.split("/")[3]).split("@")[0]), + deleteText: deleteText, + addText: addText, + addCustomEmojiText: addCustomEmojiText, + customStickerPackageList: [ + ...defaultEmojiList, + ...customStickerPackageList + ], + backgroundColor: theme.weakBackgroundColor, + lightPrimaryColor: theme.lightPrimaryColor); +} +``` + +### STEP4.1: 渲染图片小表情 + +>? **本步骤选做:** +> - 如果您的项目需要用到图片小表情,包括自定义图片小表情,或直接使用默认自带 QQ 同款图片小表情,才需完成本步骤。 +> - 图片小表情展现形式和Unicode Emoji类似,建议Unicode Emoji和图片小表情选用一个即可。即,如果您选用了Unicode Emoji,可直接跳过本步骤。 + +- STEP4.1(a) 为使用自定义图片小表情; +- STEP4.1(b) 为使用默认自带 QQ 同款图片小表情。 + +以上方案,建议直接选用一个方案即可。 + +如果需要同时使用,请保证您的自定义图片小表情名称,不要和我们默认提供的 QQ 同款图片小表情重复。 + +#### STEP4.1(a): 添加渲染解析自定义图片小表情的支持 + +在您用于承载 `TIMUIKitChat` 组件的 `build` 方法中,定义一个 `List customEmojiList` 变量,用于存放图片小表情列表。 + +```dart +List customEmojiList = + Const.emojiList.where((element) => element.isEmoji == true).toList(); +``` + +并将此列表,传入 `TIMUIKitChat` 组件的 `customEmojiStickerList` 参数内。 + +```dart +return TIMUIKitChat( + customEmojiStickerList: customEmojiList, + // ...... +); +``` + +>? 如果您用于承载 `TIMUIKitChat` 组件的类为 `StatefulWidget`,您可将 `customEmojiList` 变量,放如State中,仅在首次build时,才去执行 `where` 命令,优化性能。 + +#### STEP4.1(b): 启用 QQ 小表情包 + +将 `TIMUIKitChat` 的 `TIMUIKitChatConfig` 的 `isUseDefaultEmoji` 参数,设置为 `true` 即可。此时,会向表情包面板最左侧,自动生成一个承载 QQ 小表情包的 Tab。 + +```dart +return TIMUIKitChat( + config: TIMUIKitChatConfig( + isUseDefaultEmoji: true, + // ...... + ), + // ...... +); +``` + +![](https://qcloudimg.tencent-cloud.cn/raw/ed14b886c08cb1c0e8371ba54925bd71.png) + +### STEP4.2: 将表情包能力,注入 TIMUIKitChat + +将本步骤最开始让您复制的代码方法,传入 `TIMUIKitChat` 组件的 `customStickerPanel` 参数内。 + +```dart +return TIMUIKitChat( + customStickerPanel: renderCustomStickerPanel, + // ...... +); +``` + +此时,TUIKit表情能力接入完成。您可正常收发测试。如在接入过程中,有任何问题,欢迎随时[联系我们](#contact)。 + +[](id:unicode) + +## 附录: Emoji Unicode 列表示例 + +本列表仅用于示例演示,您可根据需要,增加或修改。 + +```dart +List> emojiData = [ + {"name": "GRINNING FACE WITH SMILING EYES", "unicode": 128513}, + {"name": "FACE WITH TEARS OF JOY", "unicode": 128514}, + {"name": "SMILING FACE WITH OPEN MOUTH", "unicode": 128515}, + {"name": "SMILING FACE WITH OPEN MOUTH AND SMILING EYES", "unicode": 128516}, + {"name": "SMILING FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128517}, + { + "name": "SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES", + "unicode": 128518 + }, + {"name": "WINKING FACE", "unicode": 128521}, + {"name": "SMILING FACE WITH SMILING EYES", "unicode": 128522}, + {"name": "FACE SAVOURING DELICIOUS FOOD", "unicode": 128523}, + {"name": "RELIEVED FACE", "unicode": 128524}, + {"name": "SMILING FACE WITH HEART-SHAPED EYES", "unicode": 128525}, + {"name": "SMIRKING FACE", "unicode": 128527}, + {"name": "UNAMUSED FACE", "unicode": 128530}, + {"name": "FACE WITH COLD SWEAT", "unicode": 128531}, + {"name": "PENSIVE FACE", "unicode": 128532}, + {"name": "CONFOUNDED FACE", "unicode": 128534}, + {"name": "FACE THROWING A KISS", "unicode": 128536}, + {"name": "KISSING FACE WITH CLOSED EYES", "unicode": 128538}, + {"name": "FACE WITH STUCK-OUT TONGUE AND WINKING EYE", "unicode": 128540}, + { + "name": "FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES", + "unicode": 128541 + }, + {"name": "DISAPPOINTED FACE", "unicode": 128542}, + {"name": "ANGRY FACE", "unicode": 128544}, + {"name": "POUTING FACE", "unicode": 128545}, + {"name": "CRYING FACE", "unicode": 128546}, + {"name": "PERSEVERING FACE", "unicode": 128547}, + {"name": "FACE WITH LOOK OF TRIUMPH", "unicode": 128548}, + {"name": "DISAPPOINTED BUT RELIEVED FACE", "unicode": 128549}, + {"name": "FEARFUL FACE", "unicode": 128552}, + {"name": "WEARY FACE", "unicode": 128553}, + {"name": "SLEEPY FACE", "unicode": 128554}, + {"name": "TIRED FACE", "unicode": 128555}, + {"name": "LOUDLY CRYING FACE", "unicode": 128557}, + {"name": "FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128560}, + {"name": "FACE SCREAMING IN FEAR", "unicode": 128561}, + {"name": "ASTONISHED FACE", "unicode": 128562}, + {"name": "FLUSHED FACE", "unicode": 128563}, + {"name": "DIZZY FACE", "unicode": 128565}, + {"name": "FACE WITH MEDICAL MASK", "unicode": 128567}, + {"name": "GRINNING CAT FACE WITH SMILING EYES", "unicode": 128568}, + {"name": "CAT FACE WITH TEARS OF JOY", "unicode": 128569}, + {"name": "SMILING CAT FACE WITH OPEN MOUTH", "unicode": 128570}, + {"name": "SMILING CAT FACE WITH HEART-SHAPED EYES", "unicode": 128571}, + {"name": "CAT FACE WITH WRY SMILE", "unicode": 128572}, + {"name": "KISSING CAT FACE WITH CLOSED EYES", "unicode": 128573}, + {"name": "POUTING CAT FACE", "unicode": 128574}, + {"name": "CRYING CAT FACE", "unicode": 128575}, + {"name": "WEARY CAT FACE", "unicode": 128576}, + {"name": "FACE WITH NO GOOD GESTURE", "unicode": 128581}, + {"name": "FACE WITH OK GESTURE", "unicode": 128582}, + {"name": "PERSON BOWING DEEPLY", "unicode": 128583}, + {"name": "SEE-NO-EVIL MONKEY", "unicode": 128584}, + {"name": "HEAR-NO-EVIL MONKEY", "unicode": 128585}, + {"name": "SPEAK-NO-EVIL MONKEY", "unicode": 128586}, + {"name": "HAPPY PERSON RAISING ONE HAND", "unicode": 128587}, + {"name": "PERSON RAISING BOTH HANDS IN CELEBRATION", "unicode": 128588}, + {"name": "PERSON FROWNING", "unicode": 128589}, + {"name": "PERSON WITH POUTING FACE", "unicode": 128590}, + {"name": "PERSON WITH FOLDED HANDS", "unicode": 128591}, + {"name": "BLACK SCISSORS", "unicode": 9986}, + {"name": "WHITE HEAVY CHECK MARK", "unicode": 9989}, + {"name": "AIRPLANE", "unicode": 9992}, + {"name": "ENVELOPE", "unicode": 9993}, + {"name": "RAISED FIST", "unicode": 9994}, + {"name": "RAISED HAND", "unicode": 9995}, + {"name": "VICTORY HAND", "unicode": 9996}, + {"name": "PENCIL", "unicode": 9999}, + {"name": "BLACK NIB", "unicode": 10002}, + {"name": "HEAVY CHECK MARK", "unicode": 10004}, + {"name": "HEAVY MULTIPLICATION X", "unicode": 10006}, + {"name": "SPARKLES", "unicode": 10024}, + {"name": "EIGHT SPOKED ASTERISK", "unicode": 10035}, + {"name": "EIGHT POINTED BLACK STAR", "unicode": 10036}, + {"name": "SNOWFLAKE", "unicode": 10052}, + {"name": "SPARKLE", "unicode": 10055}, + {"name": "CROSS MARK", "unicode": 10060}, + {"name": "NEGATIVE SQUARED CROSS MARK", "unicode": 10062}, + {"name": "BLACK QUESTION MARK ORNAMENT", "unicode": 10067}, + {"name": "WHITE QUESTION MARK ORNAMENT", "unicode": 10068}, + {"name": "WHITE EXCLAMATION MARK ORNAMENT", "unicode": 10069}, + {"name": "HEAVY EXCLAMATION MARK SYMBOL", "unicode": 10071}, + {"name": "HEAVY BLACK HEART", "unicode": 10084}, + {"name": "HEAVY PLUS SIGN", "unicode": 10133}, + {"name": "HEAVY MINUS SIGN", "unicode": 10134}, + {"name": "HEAVY DIVISION SIGN", "unicode": 10135}, + {"name": "BLACK RIGHTWARDS ARROW", "unicode": 10145}, + {"name": "CURLY LOOP", "unicode": 10160}, + {"name": "ROCKET", "unicode": 128640}, + {"name": "RAILWAY CAR", "unicode": 128643}, + {"name": "HIGH-SPEED TRAIN", "unicode": 128644}, + {"name": "HIGH-SPEED TRAIN WITH BULLET NOSE", "unicode": 128645}, + {"name": "METRO", "unicode": 128647}, + {"name": "STATION", "unicode": 128649}, + {"name": "BUS", "unicode": 128652}, + {"name": "BUS STOP", "unicode": 128655}, + {"name": "AMBULANCE", "unicode": 128657}, + {"name": "FIRE ENGINE", "unicode": 128658}, + {"name": "POLICE CAR", "unicode": 128659}, + {"name": "TAXI", "unicode": 128661}, + {"name": "AUTOMOBILE", "unicode": 128663}, + {"name": "RECREATIONAL VEHICLE", "unicode": 128665}, + {"name": "DELIVERY TRUCK", "unicode": 128666}, + {"name": "SHIP", "unicode": 128674}, + {"name": "SPEEDBOAT", "unicode": 128676}, + {"name": "HORIZONTAL TRAFFIC LIGHT", "unicode": 128677}, + {"name": "CONSTRUCTION SIGN", "unicode": 128679}, + {"name": "POLICE CARS REVOLVING LIGHT", "unicode": 128680}, + {"name": "TRIANGULAR FLAG ON POST", "unicode": 128681}, + {"name": "DOOR", "unicode": 128682}, + {"name": "NO ENTRY SIGN", "unicode": 128683}, + {"name": "SMOKING SYMBOL", "unicode": 128684}, + {"name": "NO SMOKING SYMBOL", "unicode": 128685}, + {"name": "BICYCLE", "unicode": 128690}, + {"name": "PEDESTRIAN", "unicode": 128694}, + {"name": "MENS SYMBOL", "unicode": 128697}, + {"name": "WOMENS SYMBOL", "unicode": 128698}, + {"name": "RESTROOM", "unicode": 128699}, + {"name": "BABY SYMBOL", "unicode": 128700}, + {"name": "TOILET", "unicode": 128701}, + {"name": "WATER CLOSET", "unicode": 128702}, + {"name": "BATH", "unicode": 128704}, + {"name": "CIRCLED LATIN CAPITAL LETTER M", "unicode": 9410}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER A", "unicode": 127344}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER B", "unicode": 127345}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER O", "unicode": 127358}, + {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER P", "unicode": 127359}, + {"name": "NEGATIVE SQUARED AB", "unicode": 127374}, + {"name": "SQUARED CL", "unicode": 127377}, + {"name": "SQUARED COOL", "unicode": 127378}, + {"name": "SQUARED FREE", "unicode": 127379}, + {"name": "SQUARED ID", "unicode": 127380}, + {"name": "SQUARED NEW", "unicode": 127381}, +]; +``` + +[](id:contact) + +## 联系我们 + +If there's anything unclear or you have more ideas, feel free to contact us! + +- Telegram Group: https://t.me/+1doS9AUBmndhNGNl +- WhatsApp Group: https://chat.whatsapp.com/Gfbxk7rQBqc8Rz4pzzP27A + diff --git a/example/pubspec.lock b/example/pubspec.lock index 9ab12b1..5de3a96 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -64,13 +64,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.3.1" - build_config: - dependency: transitive - description: - name: build_config - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" cached_network_image: dependency: transitive description: @@ -141,13 +134,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" chewie: dependency: transitive description: @@ -211,20 +197,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.5" - dart_style: - dependency: transitive - description: - name: dart_style - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.4" - dio: - dependency: transitive - description: - name: dio - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.6" disk_space: dependency: transitive description: @@ -455,13 +427,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.2" - i18n: - dependency: transitive - description: - name: i18n - url: "https://pub.dartlang.org" - source: hosted - version: "3.4.1" image_gallery_saver: dependency: transitive description: @@ -833,20 +798,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.3" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.1" - quick_log: - dependency: transitive - description: - name: quick_log - url: "https://pub.dartlang.org" - source: hosted - version: "5.2.1" quiver: dependency: transitive description: @@ -931,6 +882,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.1" + shell: + dependency: transitive + description: + name: shell + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" sky_engine: dependency: transitive description: flutter @@ -1005,14 +963,14 @@ packages: name: tencent_cloud_chat_sdk url: "https://pub.dartlang.org" source: hosted - version: "5.0.4" + version: "5.0.6" tencent_cloud_chat_uikit: dependency: "direct main" description: path: ".." relative: true source: path - version: "1.0.1" + version: "1.1.0" tencent_extended_text: dependency: transitive description: @@ -1040,14 +998,14 @@ packages: name: tencent_im_base url: "https://pub.dartlang.org" source: hosted - version: "1.0.7" + version: "1.0.14" tencent_im_sdk_plugin_platform_interface: dependency: transitive description: name: tencent_im_sdk_plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "0.3.9" + version: "0.3.10" tencent_im_sdk_plugin_web: dependency: "direct main" description: @@ -1055,6 +1013,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.3.5" + tencent_keyboard_visibility: + dependency: transitive + description: + name: tencent_keyboard_visibility + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" tencent_open_file: dependency: transitive description: @@ -1075,7 +1040,7 @@ packages: name: tencent_wechat_camera_picker url: "https://pub.dartlang.org" source: hosted - version: "3.6.2+5" + version: "3.6.5" term_glyph: dependency: transitive description: @@ -1090,6 +1055,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.12" + tim_ui_kit_sticker_plugin: + dependency: transitive + description: + name: tim_ui_kit_sticker_plugin + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" transparent_image: dependency: transitive description: diff --git a/lib/business_logic/view_models/tui_chat_global_model.dart b/lib/business_logic/view_models/tui_chat_global_model.dart index 99f8895..0211cc3 100644 --- a/lib/business_logic/view_models/tui_chat_global_model.dart +++ b/lib/business_logic/view_models/tui_chat_global_model.dart @@ -532,7 +532,6 @@ class TUIChatGlobalModel extends ChangeNotifier with TIMUIKitClass { return; } if (!(_c2cMessageFromUserActiveMap[toUser] ?? false)) { - print("to user is not online"); return; } V2TimMsgCreateInfoResult? res = await _messageService.createCustomMessage( diff --git a/lib/business_logic/view_models/tui_setting_model.dart b/lib/business_logic/view_models/tui_setting_model.dart new file mode 100644 index 0000000..a893aed --- /dev/null +++ b/lib/business_logic/view_models/tui_setting_model.dart @@ -0,0 +1,26 @@ +import 'package:flutter/cupertino.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class TUISettingModel extends ChangeNotifier { + final Future _prefs = SharedPreferences.getInstance(); + final String keyTitle = "tencent_chat_uikit_"; + + double? _keyboardHeight; + double get keyboardHeight => _keyboardHeight ?? 0; + set keyboardHeight(double value) { + if(value > 40 && _keyboardHeight != value){ + _keyboardHeight = value; + updateLocalSetting("${keyTitle}keyboardHeight", value.toString()); + } + } + + updateLocalSetting(String key, String value) async { + SharedPreferences prefs = await _prefs; + prefs.setString(key, value); + } + + init() async { + SharedPreferences prefs = await _prefs; + _keyboardHeight = double.parse(prefs.getString("${keyTitle}keyboardHeight") ?? "0"); + } +} \ No newline at end of file diff --git a/lib/data_services/core/core_services.dart b/lib/data_services/core/core_services.dart index 5024f36..5c68558 100644 --- a/lib/data_services/core/core_services.dart +++ b/lib/data_services/core/core_services.dart @@ -5,6 +5,31 @@ import 'package:tencent_cloud_chat_uikit/data_services/core/tim_uikit_config.dar enum AppStatus { foreground, background } +enum LanguageEnum { + /// Chinese, Traditional + zhHant, + + /// Chinese, Simplified + zhHans, + + /// English + en, + + /// Korean + ko, + + /// Japanese + ja, +} + +const languageEnumToString = { + LanguageEnum.zhHant: "zh-Hant", + LanguageEnum.zhHans: "zh-Hans", + LanguageEnum.en: "en", + LanguageEnum.ja: "ja", + LanguageEnum.ko: "ko", +}; + abstract class CoreServices { Future init({ required int sdkAppID, diff --git a/lib/data_services/core/core_services_implements.dart b/lib/data_services/core/core_services_implements.dart index 421db3c..e4f8504 100644 --- a/lib/data_services/core/core_services_implements.dart +++ b/lib/data_services/core/core_services_implements.dart @@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; +import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_setting_model.dart'; import 'package:tencent_im_base/tencent_im_base.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/listener_model/tui_group_listener_model.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart'; @@ -65,7 +66,9 @@ class CoreServicesImpl with CoreServices { setGlobalConfig(TIMUIKitConfig? config) { final TUISelfInfoViewModel selfInfoViewModel = serviceLocator(); + final TUISettingModel settingModel = serviceLocator(); selfInfoViewModel.globalConfig = config; + settingModel.init(); } addIdentifier() { @@ -83,12 +86,17 @@ class CoreServicesImpl with CoreServices { required LogLevelEnum loglevel, required V2TimSDKListener listener, LanguageEnum? language, + String? extraLanguage, TIMUIKitConfig? config, VoidCallback? onWebLoginSuccess}) async { addIdentifier(); - if (language != null) { + if(extraLanguage != null){ Future.delayed(const Duration(milliseconds: 1), () { - I18nUtils(null, language); + I18nUtils(null, extraLanguage); + }); + }else if (language != null) { + Future.delayed(const Duration(milliseconds: 1), () { + I18nUtils(null, languageEnumToString[language]); }); } if (onTUIKitCallbackListener != null) { @@ -132,12 +140,17 @@ class CoreServicesImpl with CoreServices { ValueChanged? onTUIKitCallbackListener, LanguageEnum? language, TIMUIKitConfig? config, + String? extraLanguage, required String userId, }) async { _userID = userId; - if (language != null) { + if(extraLanguage != null){ Future.delayed(const Duration(milliseconds: 1), () { - I18nUtils(null, language); + I18nUtils(null, extraLanguage); + }); + }else if (language != null) { + Future.delayed(const Duration(milliseconds: 1), () { + I18nUtils(null, languageEnumToString[language]); }); } if (onTUIKitCallbackListener != null) { @@ -340,7 +353,6 @@ class CoreServicesImpl with CoreServices { @override Future setOfflinePushConfig({ - // ignore: todo required String token, bool isTPNSToken = false, int? businessID, diff --git a/lib/data_services/services_locatar.dart b/lib/data_services/services_locatar.dart index 97369d1..b3deb6d 100644 --- a/lib/data_services/services_locatar.dart +++ b/lib/data_services/services_locatar.dart @@ -4,6 +4,7 @@ import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_conversation_view_model.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_friendship_view_model.dart'; +import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_setting_model.dart'; import 'package:tencent_cloud_chat_uikit/data_services/conversation/conversation_services.dart'; import 'package:tencent_cloud_chat_uikit/data_services/conversation/conversation_services_implements.dart'; import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart'; @@ -22,8 +23,10 @@ bool boolIsInitailized = false; void setupServiceLocator() { if (!boolIsInitailized) { - // services + // setting + serviceLocator.registerSingleton(TUISettingModel()); + // services serviceLocator.registerSingleton(CoreServicesImpl()); serviceLocator .registerSingleton(TUISelfInfoViewModel()); diff --git a/lib/i18n/strings.i18n.json b/lib/i18n/strings.i18n.json index 28aeb2b..9161b91 100644 --- a/lib/i18n/strings.i18n.json +++ b/lib/i18n/strings.i18n.json @@ -1 +1 @@ -{"k_1fdhj9g":"This version does not support the message","k_06pujtm":"Accept all friend requests","k_0gyhkp5":"Require approval for friend requests","k_121ruco":"Reject all friend requests","k_05nspni":"Custom field","k_03fchyy":"Group profile photo","k_03i9mfe":"Group introduction","k_03agq58":"Group name","k_039xqny":"Group notification","k_003tr0a":"Group owner","k_002wddw":"Mute","k_0got6f7":"Unmute","k_1uaqed6":"[Custom]","k_0z2z7rx":"[Voice]","k_0y39ngu":"[Emoji]","k_0y1a2my":"[Image]","k_0z4fib8":"[Video]","k_0y24mcg":"[Location]","k_0pewpd1":"[Chat history]","k_13s8d9p":"Unknown message","k_003qkx2":"Calendar","k_003n2pz":"Camera","k_03idjo0":"Contact","k_003ltgm":"Location","k_02k3k86":"Mic","k_003pm7l":"Album","k_15ao57x":"Album write","k_164m3jd":"Local storage","k_03r6qyx":"We need your approval to get information.","k_02noktt":"Reject","k_00043x4":"Agree","k_003qzac":"Yesterday","k_003r39d":"2 days ago","k_03fqp9o":"Sun","k_03ibg5h":"Mon","k_03i7hu1":"Tue","k_03iaiks":"Wed","k_03el9pa":"Thu","k_03i7ok1":"Fri","k_03efxyg":"Sat","k_003q7ba":"Afternoon","k_003q7bb":"Morning","k_003pu3h":"Now","k_002rflt":"Delete","k_1don84v":"Failed to locate the original message","k_003q5fi":"Copy","k_003prq0":"Forward","k_002r1h2":"Multiple-choice","k_003j708":"Reference","k_003pqpr":"Recall","k_03ezhho":"Copied","k_11ctfsz":"Not implemented","k_1hbjg5g":"[Group system message]","k_03tvswb":"[Unknown message]","k_155cj23":"You've recalled a message.","k_0gapun3":"Edit it again","k_0003z7x":"You","k_002wfe4":"Read","k_002wjlg":"Unread","k_003nevv":"Cancel","k_001nmhu":"Open with another app","k_105682d":"Failed to load the image","k_0pytyeu":"Image saved successfully","k_0akceel":"Failed to save the image","k_003rk1s":"Save","k_04a0awq":"[Voice message]","k_105c3y3":"Failed to load the video","k_176rzr7":"Chat history","k_002r305":"Send","k_003n8b0":"Shoot","k_003tnp0":"File","k_0ylosxn":"Custom message","k_0jhdhtp":"Sending failed. The video cannot exceed 100 MB.","k_0am7r68":"Slide up to cancel","k_13dsw4l":"Release to cancel","k_15jl6qw":"Too short","k_0gx7vl6":"Press and hold to talk","k_15dlafd":"One-by-one forward","k_15dryxy":"Combine and forward","k_1eyhieh":"Are you sure you want to delete the selected message?","k_118prbn":"Search globally","k_003kv3v":"Search","k_17fmlyf":"Clear chat","k_0dhesoz":"Unpin from top","k_002sk7x":"Pin to top","k_003ll77":"Draft","k_003kfai":"Unknown","k_13dq4an":"Automatic approval","k_0l13cde":"Admin approval","k_11y8c6a":"Disallow group joining","k_1kvyskd":"Modification failed due to network disconnection","k_16payqf":"Group joining mode","k_0vzvn8r":"Modify group name","k_003rzap":"OK","k_038lh6u":"Group management","k_0k5wyiy":"Set admin","k_0goiuwk":"Mute all","k_1g889xx":"If you mute all, only the group owner and admin can speak.","k_0wlrefq":"Add group members to mute","k_0goox5g":"Mute","k_08daijh":"Admin role canceled successfully","k_0k5u935":"Add admin","k_003ngex":"Complete","k_03enyx5":"Group member","k_03erpei":"Admin","k_0qi9tno":"Group owner and admin","k_0uj7208":"Failed to view the group members due to network disconnection","k_0ef2a12":"Modify my nickname in group","k_1aajych":"2–20 characters, including digits, letters, and underscores","k_137pab5":"My nickname in group","k_0ivim6d":"No group notice","k_03eq6cn":"Group notice","k_002vxya":"Modify","k_03gu05e":"Chat room","k_03b4f3p":"Meeting group","k_03avj1p":"Public group","k_03asq2g":"Work group","k_03b3hbi":"Unknown group","k_03es1ox":"Group type","k_003mz1i":"Agree","k_003lpre":"Reject","k_003qk66":"Profile photo","k_003lhvk":"Nickname","k_003ps50":"Account","k_15lx52z":"Status","k_003qgkp":"Gender","k_003m6hr":"Date of birth","k_0003v6a":"Male","k_00043x2":"Female","k_03bcjkv":"Not set","k_11s0gdz":"Modify nickname","k_0p3j4sd":"Allows only letters, digits, and underscores","k_15lyvdt":"Modify status","k_0vylzjp":"None","k_1hs7ese":"Modify it later","k_03exjk7":"Remarks","k_0s3skfd":"Add to blocklist","k_17fpl3y":"Pin chat to top","k_0p3b31s":"Modify remarks","k_0003y9x":"None","k_11zgnfs":"Profile","k_1tez2xl":"No status","k_0vjj2kp":"Group chat history","k_003n2rp":"Select","k_1m9exwh":"Recent contacts","k_119nwqr":"The input cannot be empty","k_0pzwbmg":"Video saved successfully","k_0aktupv":"Failed to save the video","k_1yemzyd":"Received a message","k_13sajrj":"Emoji message","k_13sjeb7":"File message","k_0yd2ft8":"Group notification","k_13s7mxn":"Image message","k_13satlt":"Location message","k_00bbtsx":"Combined message","k_13sqwu4":"Voice message","k_13sqjjp":"Video message","k_03iqsh4":" $s to ","k_191t5n4":"$opUserNickName changed ","k_1pg6aoj":"$opUserNickName quit group chat","k_1f6zt3v":"Invite $invitedMemberString to the group","k_0y7zd07":"Remove $invitedMemberString from the group","k_1d5mshh":"User $joinedMemberString joined the group","k_0yenqf0":"$userName was","k_0spotql":"Set $adminMember as admin","k_0pg5zzj":"System message: $operationType","k_1c7z88n":"[File] $fileName","k_1c3us5n":"The current group does not support @all","k_11k579v":"Invalid statements detected","k_0qba4ns":" attempted to access your $yoursItem","k_0oozw9x":"$diffMinutes minutes ago","k_13hzn00":"$yesterday, yesterday","k_0n9pyxz":"The user does not exist","k_1bjwemh":"Search by user ID","k_02owlq8":"My user ID: $userID","k_1wu8h4x":"Me: $showName","k_16758qw":"Add friend","k_1shx4d9":"Status: $selfSignature","k_0i553x0":"Enter verification information","k_031ocwx":"Enter remarks and list","k_003ojje":"Remarks","k_003lsav":"List","k_167bdvq":"My friends","k_156b4ut":"Friend request sent","k_1loix7s":"Group type: $groupType","k_1lqbsib":"The group chat does not exist","k_03h153m":"Search by group ID","k_0oxak3r":"Group request sent","k_1uh417q":"$displayName recalled a message","k_1aszp2k":"Are you sure you want to send the message again?","k_0h1ygf8":"Call initiated","k_0h169j0":"Call canceled","k_0h13jjk":"Call accepted","k_0h19hfx":"Call rejected","k_0obi9lh":"No answer","k_0ohzb9l":"Call duration: $callTime","k_0y9u662":"$appName currently does not support this file type. You can use another app to open and preview the file.","k_1ht1b80":"Receiving","k_0d5z4m5":"Select reminder receiver","k_1665ltg":"Initiate call","k_003kthh":"Photo","k_119ucng":"The image cannot be empty","k_0w9x8gw":"Selected successfully: $successPath","k_1np495n":"$messageString[Someone@me]","k_1m797yi":"$messageString[@all]","k_1uaov41":"Search for chat content","k_0bxm97s":"Admin ($adminNum/10)","k_0jayw3z":"Group members ($groupMemberNum members)","k_0h1svv1":"Delete group member","k_0h1g636":"Add group member","k_01yfa4o":"$memberCount members","k_0hpukyx":"View more group members","k_0qtsar0":"Mute notifications","k_03xd79d":"Status: $signature","k_1m9dftc":"All contacts","k_0em4gyz":"All group chats","k_002twmj":"Group chat","k_09kga0d":"More chat history","k_1ui5lzi":"$count messages are found","k_09khmso":"Related chat records","k_1kevf4k":"Chat history with $receiver","k_03ignw6":"All","k_03icaxo":"Custom","k_1969986":"[Voice Call]:$callingLastMsgShow","k_1960dlr":"[Video Call]:$callingLastMsgShow","k_1qbg9xc":"$option8 to ","k_1wq5ubm":"$option7 changed ","k_0y5pu80":"$option6 quit group chat","k_0nl7cmd":"Invite $option5 to the group","k_1ju5iqw":"Remove $option4 from the group","k_1ovt677":"User $option3 joined the group","k_0k05b8b":"$option2 was ","k_0wm4xeb":"System message: $option2","k_0nbq9v3":"Call duration: $option2","k_0i1kf53":"[File] $option2","k_1gnnby6":" attempted to access your $option2","k_1wh4atg":"$option2 minutes ago","k_07sh7g1":"$option2, yesterday","k_1pj8xzh":"My user ID: $option2","k_0py1evo":"Status: $option2","k_1kvj4i2":"$option2 recalled a message","k_1v0lbpp":"$option2 currently does not support this file type. You can use another app to open and preview the file.","k_0torwfz":"Selected successfully: $option2","k_0i1bjah":"$option1 recalled a message","k_1qzxh9q":"Call duration: $option3","k_0wrgmom":"[Voice Call]:$option1","k_06ix2f0":"[Video Call]:$option2","k_08o3z5w":"[File] $option1","k_0ezbepg":"$option2[Someone@me]","k_1ccnht1":"$option2[@all]","k_1k3arsw":"Admin ($option2/10)","k_1d4golg":"Group members ($option1 members)","k_1bg69nt":"$option1 members","k_00gjqxj":"Status: $option1","k_0c29cxr":"$option1 messages are found","k_1twk5rz":"Chat history with $option1","k_18o68ro":"Allow ","k_1onpf8u":" to access your camera to take photos, record videos, and make video calls.","k_17irga5":" to access your microphone to send voice messages, record videos, and make voice/video calls.","k_0572kc4":" to access your photos to send images and videos.","k_0slykws":" to access your album to save images and videos.","k_119pkcd":" to access your files to view, select and send files in a chat.","k_03c49qt":"Authorize now","k_0nt2uyg":"Back to the bottom","k_04l16at":"$option1 new messages","k_13p3w93":"Someone @ me","k_18w5uk6":"@ all","k_0jmujgh":"You are receiving other files","k_12s5ept":"Message details","k_0mxa4f4":"$option1 read","k_061tue3":"$option2 unread","k_1vn4xq1":"remove $adminMember from admin","k_0e35hsw":"Please allow us to use your camera to capture photos and videos sending to your friends and make video calls.","k_0dj6yr7":"Please allow us to use your microphone for sending voice message, make video/audio calls.","k_003qnsl":"Save","k_0s3rtpw":"Please allow us to access the media and files on your devices, in order to select and send to your friend, or save from them.","k_0tezv85":" Would like to access $option2","k_002rety":" permission. ","k_0gqewd3":"Later","k_03eq4s1":"Authorize Now","k_18qjstb":"Transfer Group","k_0on1aj2":"$option2 messages @ me","k_09j4izl":"[Someone @ me] ","k_1oqtjw0":"[@ all] ","k_1x5a9vb":"This is: $option1","k_14n31e7":"Add Group","k_08nc5j1":"Group type: $option1","k_1josu12":"$option1 group joining request(s)","k_0n2x5s0":"Verification message: $option2","k_03c1nx0":"Agreed","k_03aw9w8":"Rejected","k_038ryos":"Handle now","k_0gw8pum":"Add Group","k_1gcvfrj":"Please fill in the remarks","k_002v9zj":"确认","k_10oqrki":"轻触拍照","k_0f8b3ws":"加载失败","k_11cm5lm":"手动聚焦","k_002uzrd":"预览","k_003qkn3":"录像","k_003k6a7":"拍照","k_0bqpqco":"拍照按钮","k_1626ozl":"停止录像","k_003lvmu":"前置","k_003lued":"后置","k_003lwzh":"外置","k_002qzi3":"关闭","k_003pufb":"自动","k_0apm0ze":"拍照时闪光","k_157zog5":"始终闪光","k_0cfyqhy":"$option1 画面预览","k_0phctlz":"闪光模式: $option2","k_02vfqe0":"切换至 $option3 摄像头","k_0f0y9ex":"说话时间太短","k_0ln70tk":"无法打开URL","k_11a3jdv":"轻触拍照,长按摄像","k_1k18miv":"请传入离开群组生命周期函数,提供返回首页或其他页面的导航方法。","k_1fu9ahv":"全员禁言状态","k_0gmwbnd":"全员禁言中","k_0got2zr":"您被禁言","k_0y9jck8":"你必须自定义search bar,并处理点击跳转","k_0yum3tv":"如使用自定义区域,请在profileWidgetBuilder传入对应组件","k_09kalj0":"清空聊天记录","k_14j5iul":"删除并退出","k_125ru1w":"解散该群","k_0jtutmw":"退出后不会接收到此群聊消息","k_0jtzmqa":"解散后不会接收到此群聊消息","k_0r8fi93":"好友添加成功","k_02qw14e":"好友申请已发出","k_0n3md5x":"当前用户在黑名单","k_094phq4":"好友添加失败","k_129scag":"好友删除成功","k_129uzfn":"好友删除失败","k_1666isy":"清除好友","k_1679vrd":"加为好友","k_1ualc52":"看看对方带来的数据是啥","k_0szluvp":"设置对方在线状态","k_0f4rnf8":"该用户已是好友","k_1tdkom4":"您已是群成员","k_1p2lyuz":"对方正在输入中...","k_1g8wfpy":"...共$option1人","k_12rv9vw":"回应详情","k_0havgi0":"[查看详情 >>](${linkMessage.link})","k_0n9p7g8":"群组不存在","k_1tdh5vn":"您不是群成员","k_0h1q57v":"暂无群成员","k_0y5drq1":"[查看详情 >>]($option1)","k_03pjp61":"[表情消息]","k_1jpvzul":"[自定义消息]","k_03u3bh1":"[文件消息]","k_1odsnsw":"[群消息]","k_03sel4t":"[图片消息]","k_03sfw3r":"[位置消息]","k_03xpuwq":"[合并消息]","k_07ycxwo":"[没有元素]","k_03rc9vz":"[文本消息]","k_046uopf":"[视频消息]","k_0ehmsun":"设备存储空间不足,建议清理,以获得更好使用体验","k_003kmos":"图片","k_002s86q":"视频","k_06bk5ei":"视频消息仅限 mp4 格式","k_13opfxf":"Web网页端不支持搜索","k_1i0o0y2":"暂时仅限 Android/iOS 端","k_045dtzl":"$option1的聊天记录","k_0t0131u":"群资料信息","k_18ok8xz":"消息接收方式","k_03ax3ks":"群资料","k_0sqvoqo":"将 $option1 设置为管理员","k_1gbg1v8":"将 $option1 取消管理员","k_17k64g4":"群聊创建成功!","k_05mn217":"暂未安装表情包插件,如需使用表情相关功能,请根据本文档安装:https://cloud.tencent.com/document/product/269/70746","k_14j17nz":"暂无表情包","k_0fvjexh":"正在下载中","k_1cdagzz":"已加入待下载队列,其他文件下载中","k_0g4vojc":"开始下载","k_1g32es3":"[调皮]@2x.png","k_1g8qorz":"[爱你]@2x.png","k_1g4hmx6":"[爱情]@2x.png","k_1g6b558":"[爱心]@2x.png","k_1g3m4su":"[傲慢]@2x.png","k_1g2jym7":"[白眼]@2x.png","k_0cgkxuw":"[棒棒糖]@2x.png","k_1g48br2":"[抱抱]@2x.png","k_1g49ol8":"[抱拳]@2x.png","k_1g0ras3":"[爆筋]@2x.png","k_1ghy881":"[鄙视]@2x.png","k_1g86bmv":"[闭嘴]@2x.png","k_1g1xs1p":"[鞭炮]@2x.png","k_1g8i6ri":"[便便]@2x.png","k_1g2u5kf":"[擦汗]@2x.png","k_1g60uwh":"[彩带]@2x.png","k_1g1o0d0":"[彩球]@2x.png","k_1g6a6yq":"[菜刀]@2x.png","k_1g6vqo2":"[差劲]@2x.png","k_1g0kvjc":"[钞票]@2x.png","k_1g65x7e":"[车厢]@2x.png","k_0e1tjol":"[打哈欠]@2x.png","k_1g65n58":"[大兵]@2x.png","k_1g7se7o":"[大哭]@2x.png","k_1g03868":"[蛋糕]@2x.png","k_1h8nm66":"[刀]@2x.png","k_1g3dlpi":"[得意]@2x.png","k_1g3u434":"[灯泡]@2x.png","k_1giuqs7":"[凋谢]@2x.png","k_1g8r0r9":"[多云]@2x.png","k_1g7k6i1":"[发呆]@2x.png","k_1g44zsp":"[发抖]@2x.png","k_1g5l96i":"[飞机]@2x.png","k_1g7wsqj":"[飞吻]@2x.png","k_1g49luq":"[奋斗]@2x.png","k_1gixbsm":"[风车]@2x.png","k_1g6cqbq":"[尴尬]@2x.png","k_1g6jbw5":"[勾引]@2x.png","k_1g3lwo1":"[鼓掌]@2x.png","k_1g13nkj":"[害羞]@2x.png","k_1g0mt47":"[憨笑]@2x.png","k_0bxujkf":"[红灯笼]@2x.png","k_0hhaeh8":"[红双喜]@2x.png","k_1g0jnts":"[坏笑]@2x.png","k_1g46g9c":"[挥手]@2x.png","k_1g4vi9g":"[回头]@2x.png","k_1gf7hes":"[饥饿]@2x.png","k_1g6mvsm":"[激动]@2x.png","k_1gku5mf":"[街舞]@2x.png","k_1g4hidg":"[惊恐]@2x.png","k_1gjbrtu":"[惊讶]@2x.png","k_1g6sand":"[咖啡]@2x.png","k_1g4s8rj":"[磕头]@2x.png","k_1g1wn34":"[可爱]@2x.png","k_1g3l0wd":"[可怜]@2x.png","k_1ggaon9":"[抠鼻]@2x.png","k_1ggvcb0":"[骷髅]@2x.png","k_1h8yqjt":"[酷]@2x.png","k_0jac97i":"[快哭了]@2x.png","k_1h8oiby":"[困]@2x.png","k_1g0s5hg":"[蜡烛]@2x.png","k_1g1iuer":"[篮球]@2x.png","k_1g2xjfi":"[冷汗]@2x.png","k_0s5oyqw":"[礼品袋]@2x.png","k_1g1qqvf":"[礼物]@2x.png","k_1g2slew":"[流汗]@2x.png","k_1g3z9xx":"[流泪]@2x.png","k_1g6pabn":"[麻将]@2x.png","k_0pkaxul":"[麦克风]@2x.png","k_1g7m0zj":"[猫咪]@2x.png","k_0ibvtpo":"[么么哒]@2x.png","k_1g1hoh1":"[玫瑰]@2x.png","k_1gfzeow":"[米饭]@2x.png","k_1g5l15p":"[面条]@2x.png","k_1g2hfa6":"[奶瓶]@2x.png","k_1gix9pj":"[难过]@2x.png","k_1giqn6g":"[闹钟]@2x.png","k_1h8kd64":"[怒]@2x.png","k_1g0vui9":"[怄火]@2x.png","k_1g1jsj7":"[皮球]@2x.png","k_1ghdluw":"[啤酒]@2x.png","k_1gl6ec7":"[瓢虫]@2x.png","k_1g7gg5p":"[撇嘴]@2x.png","k_1g8psin":"[乒乓]@2x.png","k_1gjzu3p":"[汽车]@2x.png","k_1h8mr0k":"[强]@2x.png","k_1g45y2n":"[敲打]@2x.png","k_1gkaxsl":"[青蛙]@2x.png","k_0jcfnoo":"[糗大了]@2x.png","k_1g4njy1":"[拳头]@2x.png","k_1h8mqr3":"[弱]@2x.png","k_1h926fg":"[色]@2x.png","k_1g6rtbq":"[沙发]@2x.png","k_1giirh6":"[删除]@2x.png","k_1g14ny9":"[闪电]@2x.png","k_1g6bmsr":"[胜利]@2x.png","k_1g1rytx":"[示爱]@2x.png","k_1g52fbz":"[手枪]@2x.png","k_1h90dam":"[衰]@2x.png","k_1gigiae":"[睡觉]@2x.png","k_1gijchz":"[太阳]@2x.png","k_1g1sgji":"[跳绳]@2x.png","k_1gjwuri":"[跳跳]@2x.png","k_1g0juhk":"[偷笑]@2x.png","k_1h8nzla":"[吐]@2x.png","k_1g6cv0i":"[委屈]@2x.png","k_1g46l5g":"[握手]@2x.png","k_1g2pgkd":"[西瓜]@2x.png","k_1ging9p":"[下雨]@2x.png","k_1h8nzil":"[吓]@2x.png","k_1g7q7wr":"[献吻]@2x.png","k_1gl6uum":"[香蕉]@2x.png","k_1g23fys":"[象棋]@2x.png","k_0j75rdh":"[心碎了]@2x.png","k_1g6ajj2":"[信封]@2x.png","k_1g21prz":"[熊猫]@2x.png","k_1h8octi":"[嘘]@2x.png","k_1h91zox":"[药]@2x.png","k_1ghttfl":"[疑问]@2x.png","k_1ghk7sz":"[阴险]@2x.png","k_0gl37zz":"[右车头]@2x.png","k_0ifkj1p":"[右哼哼]@2x.png","k_0g1yh2e":"[右太极]@2x.png","k_1g9dkfc":"[雨伞]@2x.png","k_1g8jl88":"[月亮]@2x.png","k_1h8lhqj":"[晕]@2x.png","k_1gi9x2q":"[再见]@2x.png","k_1g6dwwv":"[炸弹]@2x.png","k_1fzmkfi":"[折磨]@2x.png","k_1g6jbiw":"[纸巾]@2x.png","k_1ggjnwu":"[咒骂]@2x.png","k_1g4qlq8":"[猪头]@2x.png","k_1g1lqzz":"[抓狂]@2x.png","k_1g80j3u":"[转圈]@2x.png","k_1g0z55s":"[龇牙]@2x.png","k_1g3ju6v":"[钻戒]@2x.png","k_0gl51l6":"[左车头]@2x.png","k_0iflllk":"[左哼哼]@2x.png","k_0g1y3ir":"[左太极]@2x.png","k_026hiq5":"消息列表加载中"} \ No newline at end of file +{"k_1fdhj9g":"This version does not support the message","k_06pujtm":"Accept all friend requests","k_0gyhkp5":"Require approval for friend requests","k_121ruco":"Reject all friend requests","k_05nspni":"Custom field","k_03fchyy":"Group profile photo","k_03i9mfe":"Group introduction","k_03agq58":"Group name","k_039xqny":"Group notification","k_003tr0a":"Group owner","k_002wddw":"Mute","k_0got6f7":"Unmute","k_1uaqed6":"[Custom]","k_0z2z7rx":"[Voice]","k_0y39ngu":"[Emoji]","k_0y1a2my":"[Image]","k_0z4fib8":"[Video]","k_0y24mcg":"[Location]","k_0pewpd1":"[Chat history]","k_13s8d9p":"Unknown message","k_003qkx2":"Calendar","k_003n2pz":"Camera","k_03idjo0":"Contact","k_003ltgm":"Location","k_02k3k86":"Mic","k_003pm7l":"Album","k_15ao57x":"Album write","k_164m3jd":"Local storage","k_03r6qyx":"We need your approval to get information.","k_02noktt":"Reject","k_00043x4":"Agree","k_003qzac":"Yesterday","k_003r39d":"2 days ago","k_03fqp9o":"Sun","k_03ibg5h":"Mon","k_03i7hu1":"Tue","k_03iaiks":"Wed","k_03el9pa":"Thu","k_03i7ok1":"Fri","k_03efxyg":"Sat","k_003q7ba":"Afternoon","k_003q7bb":"Morning","k_003pu3h":"Now","k_002rflt":"Delete","k_1don84v":"Failed to locate the original message","k_003q5fi":"Copy","k_003prq0":"Forward","k_002r1h2":"Multiple-choice","k_003j708":"Reference","k_003pqpr":"Recall","k_03ezhho":"Copied","k_11ctfsz":"Not implemented","k_1hbjg5g":"[Group system message]","k_03tvswb":"[Unknown message]","k_155cj23":"You've recalled a message.","k_0gapun3":"Edit it again","k_0003z7x":"You","k_002wfe4":"Read","k_002wjlg":"Unread","k_003nevv":"Cancel","k_001nmhu":"Open with another app","k_105682d":"Failed to load the image","k_0pytyeu":"Image saved successfully","k_0akceel":"Failed to save the image","k_003rk1s":"Save","k_04a0awq":"[Voice message]","k_105c3y3":"Failed to load the video","k_176rzr7":"Chat history","k_002r305":"Send","k_003n8b0":"Shoot","k_003tnp0":"File","k_0ylosxn":"Custom message","k_0jhdhtp":"Sending failed. The video cannot exceed 100 MB.","k_0am7r68":"Slide up to cancel","k_13dsw4l":"Release to cancel","k_15jl6qw":"Too short","k_0gx7vl6":"Press and hold to talk","k_15dlafd":"One-by-one forward","k_15dryxy":"Combine and forward","k_1eyhieh":"Are you sure you want to delete the selected message?","k_118prbn":"Search globally","k_003kv3v":"Search","k_17fmlyf":"Clear chat","k_0dhesoz":"Unpin from top","k_002sk7x":"Pin to top","k_003ll77":"Draft","k_003kfai":"Unknown","k_13dq4an":"Automatic approval","k_0l13cde":"Admin approval","k_11y8c6a":"Disallow group joining","k_1kvyskd":"Modification failed due to network disconnection","k_16payqf":"Group joining mode","k_0vzvn8r":"Modify group name","k_003rzap":"OK","k_038lh6u":"Group management","k_0k5wyiy":"Set admin","k_0goiuwk":"Mute all","k_1g889xx":"If you mute all, only the group owner and admin can speak.","k_0wlrefq":"Add group members to mute","k_0goox5g":"Mute","k_08daijh":"Admin role canceled successfully","k_0k5u935":"Add admin","k_003ngex":"Complete","k_03enyx5":"Group member","k_03erpei":"Admin","k_0qi9tno":"Group owner and admin","k_0uj7208":"Failed to view the group members due to network disconnection","k_0ef2a12":"Modify my nickname in group","k_1aajych":"2–20 characters, including digits, letters, and underscores","k_137pab5":"My nickname in group","k_0ivim6d":"No group notice","k_03eq6cn":"Group notice","k_002vxya":"Modify","k_03gu05e":"Chat room","k_03b4f3p":"Meeting group","k_03avj1p":"Public group","k_03asq2g":"Work group","k_03b3hbi":"Unknown group","k_03es1ox":"Group type","k_003mz1i":"Agree","k_003lpre":"Reject","k_003qk66":"Profile photo","k_003lhvk":"Nickname","k_003ps50":"Account","k_15lx52z":"Status","k_003qgkp":"Gender","k_003m6hr":"Date of birth","k_0003v6a":"Male","k_00043x2":"Female","k_03bcjkv":"Not set","k_11s0gdz":"Modify nickname","k_0p3j4sd":"Allows only letters, digits, and underscores","k_15lyvdt":"Modify status","k_0vylzjp":"None","k_1hs7ese":"Modify it later","k_03exjk7":"Remarks","k_0s3skfd":"Add to blocklist","k_17fpl3y":"Pin chat to top","k_0p3b31s":"Modify remarks","k_0003y9x":"None","k_11zgnfs":"Profile","k_1tez2xl":"No status","k_0vjj2kp":"Group chat history","k_003n2rp":"Select","k_1m9exwh":"Recent contacts","k_119nwqr":"The input cannot be empty","k_0pzwbmg":"Video saved successfully","k_0aktupv":"Failed to save the video","k_1yemzyd":"Received a message","k_13sajrj":"Emoji message","k_13sjeb7":"File message","k_0yd2ft8":"Group notification","k_13s7mxn":"Image message","k_13satlt":"Location message","k_00bbtsx":"Combined message","k_13sqwu4":"Voice message","k_13sqjjp":"Video message","k_03iqsh4":" $s to ","k_191t5n4":"$opUserNickName changed ","k_1pg6aoj":"$opUserNickName quit group chat","k_1f6zt3v":"Invite $invitedMemberString to the group","k_0y7zd07":"Remove $invitedMemberString from the group","k_1d5mshh":"User $joinedMemberString joined the group","k_0yenqf0":"$userName was","k_0spotql":"Set $adminMember as admin","k_0pg5zzj":"System message: $operationType","k_1c7z88n":"[File] $fileName","k_1c3us5n":"The current group does not support @all","k_11k579v":"Invalid statements detected","k_0qba4ns":" attempted to access your $yoursItem","k_0oozw9x":"$diffMinutes minutes ago","k_13hzn00":"$yesterday, yesterday","k_0n9pyxz":"The user does not exist","k_1bjwemh":"Search by user ID","k_02owlq8":"My user ID: $userID","k_1wu8h4x":"Me: $showName","k_16758qw":"Add friend","k_1shx4d9":"Status: $selfSignature","k_0i553x0":"Enter verification information","k_031ocwx":"Enter remarks and list","k_003ojje":"Remarks","k_003lsav":"List","k_167bdvq":"My friends","k_156b4ut":"Friend request sent","k_1loix7s":"Group type: $groupType","k_1lqbsib":"The group chat does not exist","k_03h153m":"Search by group ID","k_0oxak3r":"Group request sent","k_1uh417q":"$displayName recalled a message","k_1aszp2k":"Are you sure you want to send the message again?","k_0h1ygf8":"Call initiated","k_0h169j0":"Call canceled","k_0h13jjk":"Call accepted","k_0h19hfx":"Call rejected","k_0obi9lh":"No answer","k_0ohzb9l":"Call duration: $callTime","k_0y9u662":"$appName currently does not support this file type. You can use another app to open and preview the file.","k_1ht1b80":"Receiving","k_0d5z4m5":"Select reminder receiver","k_1665ltg":"Initiate call","k_003kthh":"Photo","k_119ucng":"The image cannot be empty","k_0w9x8gw":"Selected successfully: $successPath","k_1np495n":"$messageString[Someone@me]","k_1m797yi":"$messageString[@all]","k_1uaov41":"Search for chat content","k_0bxm97s":"Admin ($adminNum/10)","k_0jayw3z":"Group members ($groupMemberNum members)","k_0h1svv1":"Delete group member","k_0h1g636":"Add group member","k_01yfa4o":"$memberCount members","k_0hpukyx":"View more group members","k_0qtsar0":"Mute notifications","k_03xd79d":"Status: $signature","k_1m9dftc":"All contacts","k_0em4gyz":"All group chats","k_002twmj":"Group chat","k_09kga0d":"More chat history","k_1ui5lzi":"$count messages are found","k_09khmso":"Related chat records","k_1kevf4k":"Chat history with $receiver","k_03ignw6":"All","k_03icaxo":"Custom","k_1969986":"[Voice Call]:$callingLastMsgShow","k_1960dlr":"[Video Call]:$callingLastMsgShow","k_1qbg9xc":"$option8 to ","k_1wq5ubm":"$option7 changed ","k_0y5pu80":"$option6 quit group chat","k_0nl7cmd":"Invite $option5 to the group","k_1ju5iqw":"Remove $option4 from the group","k_1ovt677":"User $option3 joined the group","k_0k05b8b":"$option2 was ","k_0wm4xeb":"System message: $option2","k_0nbq9v3":"Call duration: $option2","k_0i1kf53":"[File] $option2","k_1gnnby6":" attempted to access your $option2","k_1wh4atg":"$option2 minutes ago","k_07sh7g1":"$option2, yesterday","k_1pj8xzh":"My user ID: $option2","k_0py1evo":"Status: $option2","k_1kvj4i2":"$option2 recalled a message","k_1v0lbpp":"$option2 currently does not support this file type. You can use another app to open and preview the file.","k_0torwfz":"Selected successfully: $option2","k_0i1bjah":"$option1 recalled a message","k_1qzxh9q":"Call duration: $option3","k_0wrgmom":"[Voice Call]:$option1","k_06ix2f0":"[Video Call]:$option2","k_08o3z5w":"[File] $option1","k_0ezbepg":"$option2[Someone@me]","k_1ccnht1":"$option2[@all]","k_1k3arsw":"Admin ($option2/10)","k_1d4golg":"Group members ($option1 members)","k_1bg69nt":"$option1 members","k_00gjqxj":"Status: $option1","k_0c29cxr":"$option1 messages are found","k_1twk5rz":"Chat history with $option1","k_18o68ro":"Allow ","k_1onpf8u":" to access your camera to take photos, record videos, and make video calls.","k_17irga5":" to access your microphone to send voice messages, record videos, and make voice/video calls.","k_0572kc4":" to access your photos to send images and videos.","k_0slykws":" to access your album to save images and videos.","k_119pkcd":" to access your files to view, select and send files in a chat.","k_03c49qt":"Authorize now","k_0nt2uyg":"Back to the bottom","k_04l16at":"$option1 new messages","k_13p3w93":"Someone @ me","k_18w5uk6":"@ all","k_0jmujgh":"You are receiving other files","k_12s5ept":"Message details","k_0mxa4f4":"$option1 read","k_061tue3":"$option2 unread","k_1vn4xq1":"remove $adminMember from admin","k_0e35hsw":"Please allow us to use your camera to capture photos and videos sending to your friends and make video calls.","k_0dj6yr7":"Please allow us to use your microphone for sending voice message, make video/audio calls.","k_003qnsl":"Save","k_0s3rtpw":"Please allow us to access the media and files on your devices, in order to select and send to your friend, or save from them.","k_0tezv85":" Would like to access $option2","k_002rety":" permission. ","k_0gqewd3":"Later","k_03eq4s1":"Authorize Now","k_18qjstb":"Transfer Group","k_0on1aj2":"$option2 messages @ me","k_09j4izl":"[Someone @ me] ","k_1oqtjw0":"[@ all] ","k_1x5a9vb":"This is: $option1","k_14n31e7":"Add Group","k_08nc5j1":"Group type: $option1","k_1josu12":"$option1 group joining request(s)","k_0n2x5s0":"Verification message: $option2","k_03c1nx0":"Agreed","k_03aw9w8":"Rejected","k_038ryos":"Handle now","k_0gw8pum":"Add Group","k_1gcvfrj":"Please fill in the remarks","k_002v9zj":"确认","k_10oqrki":"轻触拍照","k_0f8b3ws":"加载失败","k_11cm5lm":"手动聚焦","k_002uzrd":"预览","k_003qkn3":"录像","k_003k6a7":"拍照","k_0bqpqco":"拍照按钮","k_1626ozl":"停止录像","k_003lvmu":"前置","k_003lued":"后置","k_003lwzh":"外置","k_002qzi3":"关闭","k_003pufb":"自动","k_0apm0ze":"拍照时闪光","k_157zog5":"始终闪光","k_0cfyqhy":"$option1 画面预览","k_0phctlz":"闪光模式: $option2","k_02vfqe0":"切换至 $option3 摄像头","k_0f0y9ex":"说话时间太短","k_0ln70tk":"无法打开URL","k_11a3jdv":"轻触拍照,长按摄像","k_1k18miv":"请传入离开群组生命周期函数,提供返回首页或其他页面的导航方法。","k_1fu9ahv":"全员禁言状态","k_0gmwbnd":"全员禁言中","k_0got2zr":"您被禁言","k_0y9jck8":"你必须自定义search bar,并处理点击跳转","k_0yum3tv":"如使用自定义区域,请在profileWidgetBuilder传入对应组件","k_09kalj0":"清空聊天记录","k_14j5iul":"删除并退出","k_125ru1w":"解散该群","k_0jtutmw":"退出后不会接收到此群聊消息","k_0jtzmqa":"解散后不会接收到此群聊消息","k_0r8fi93":"好友添加成功","k_02qw14e":"好友申请已发出","k_0n3md5x":"当前用户在黑名单","k_094phq4":"好友添加失败","k_129scag":"好友删除成功","k_129uzfn":"好友删除失败","k_1666isy":"清除好友","k_1679vrd":"加为好友","k_1ualc52":"看看对方带来的数据是啥","k_0szluvp":"设置对方在线状态","k_0f4rnf8":"该用户已是好友","k_1tdkom4":"您已是群成员","k_1p2lyuz":"对方正在输入中...","k_1g8wfpy":"...共$option1人","k_12rv9vw":"回应详情","k_0havgi0":"[查看详情 >>](${linkMessage.link})","k_0n9p7g8":"群组不存在","k_1tdh5vn":"您不是群成员","k_0h1q57v":"暂无群成员","k_0y5drq1":"[查看详情 >>]($option1)","k_03pjp61":"[表情消息]","k_1jpvzul":"[自定义消息]","k_03u3bh1":"[文件消息]","k_1odsnsw":"[群消息]","k_03sel4t":"[图片消息]","k_03sfw3r":"[位置消息]","k_03xpuwq":"[合并消息]","k_07ycxwo":"[没有元素]","k_03rc9vz":"[文本消息]","k_046uopf":"[视频消息]","k_0ehmsun":"设备存储空间不足,建议清理,以获得更好使用体验","k_003kmos":"图片","k_002s86q":"视频","k_06bk5ei":"视频消息仅限 mp4 格式","k_13opfxf":"Web网页端不支持搜索","k_1i0o0y2":"暂时仅限 Android/iOS 端","k_045dtzl":"$option1的聊天记录","k_0t0131u":"群资料信息","k_18ok8xz":"消息接收方式","k_03ax3ks":"群资料","k_0sqvoqo":"将 $option1 设置为管理员","k_1gbg1v8":"将 $option1 取消管理员","k_17k64g4":"群聊创建成功!","k_05mn217":"暂未安装表情包插件,如需使用表情相关功能,请根据本文档安装:https://cloud.tencent.com/document/product/269/70746","k_14j17nz":"暂无表情包","k_0fvjexh":"正在下载中","k_1cdagzz":"已加入待下载队列,其他文件下载中","k_0g4vojc":"开始下载","k_1g32es3":"[调皮]@2x.png","k_1g8qorz":"[爱你]@2x.png","k_1g4hmx6":"[爱情]@2x.png","k_1g6b558":"[爱心]@2x.png","k_1g3m4su":"[傲慢]@2x.png","k_1g2jym7":"[白眼]@2x.png","k_0cgkxuw":"[棒棒糖]@2x.png","k_1g48br2":"[抱抱]@2x.png","k_1g49ol8":"[抱拳]@2x.png","k_1g0ras3":"[爆筋]@2x.png","k_1ghy881":"[鄙视]@2x.png","k_1g86bmv":"[闭嘴]@2x.png","k_1g1xs1p":"[鞭炮]@2x.png","k_1g8i6ri":"[便便]@2x.png","k_1g2u5kf":"[擦汗]@2x.png","k_1g60uwh":"[彩带]@2x.png","k_1g1o0d0":"[彩球]@2x.png","k_1g6a6yq":"[菜刀]@2x.png","k_1g6vqo2":"[差劲]@2x.png","k_1g0kvjc":"[钞票]@2x.png","k_1g65x7e":"[车厢]@2x.png","k_0e1tjol":"[打哈欠]@2x.png","k_1g65n58":"[大兵]@2x.png","k_1g7se7o":"[大哭]@2x.png","k_1g03868":"[蛋糕]@2x.png","k_1h8nm66":"[刀]@2x.png","k_1g3dlpi":"[得意]@2x.png","k_1g3u434":"[灯泡]@2x.png","k_1giuqs7":"[凋谢]@2x.png","k_1g8r0r9":"[多云]@2x.png","k_1g7k6i1":"[发呆]@2x.png","k_1g44zsp":"[发抖]@2x.png","k_1g5l96i":"[飞机]@2x.png","k_1g7wsqj":"[飞吻]@2x.png","k_1g49luq":"[奋斗]@2x.png","k_1gixbsm":"[风车]@2x.png","k_1g6cqbq":"[尴尬]@2x.png","k_1g6jbw5":"[勾引]@2x.png","k_1g3lwo1":"[鼓掌]@2x.png","k_1g13nkj":"[害羞]@2x.png","k_1g0mt47":"[憨笑]@2x.png","k_0bxujkf":"[红灯笼]@2x.png","k_0hhaeh8":"[红双喜]@2x.png","k_1g0jnts":"[坏笑]@2x.png","k_1g46g9c":"[挥手]@2x.png","k_1g4vi9g":"[回头]@2x.png","k_1gf7hes":"[饥饿]@2x.png","k_1g6mvsm":"[激动]@2x.png","k_1gku5mf":"[街舞]@2x.png","k_1g4hidg":"[惊恐]@2x.png","k_1gjbrtu":"[惊讶]@2x.png","k_1g6sand":"[咖啡]@2x.png","k_1g4s8rj":"[磕头]@2x.png","k_1g1wn34":"[可爱]@2x.png","k_1g3l0wd":"[可怜]@2x.png","k_1ggaon9":"[抠鼻]@2x.png","k_1ggvcb0":"[骷髅]@2x.png","k_1h8yqjt":"[酷]@2x.png","k_0jac97i":"[快哭了]@2x.png","k_1h8oiby":"[困]@2x.png","k_1g0s5hg":"[蜡烛]@2x.png","k_1g1iuer":"[篮球]@2x.png","k_1g2xjfi":"[冷汗]@2x.png","k_0s5oyqw":"[礼品袋]@2x.png","k_1g1qqvf":"[礼物]@2x.png","k_1g2slew":"[流汗]@2x.png","k_1g3z9xx":"[流泪]@2x.png","k_1g6pabn":"[麻将]@2x.png","k_0pkaxul":"[麦克风]@2x.png","k_1g7m0zj":"[猫咪]@2x.png","k_0ibvtpo":"[么么哒]@2x.png","k_1g1hoh1":"[玫瑰]@2x.png","k_1gfzeow":"[米饭]@2x.png","k_1g5l15p":"[面条]@2x.png","k_1g2hfa6":"[奶瓶]@2x.png","k_1gix9pj":"[难过]@2x.png","k_1giqn6g":"[闹钟]@2x.png","k_1h8kd64":"[怒]@2x.png","k_1g0vui9":"[怄火]@2x.png","k_1g1jsj7":"[皮球]@2x.png","k_1ghdluw":"[啤酒]@2x.png","k_1gl6ec7":"[瓢虫]@2x.png","k_1g7gg5p":"[撇嘴]@2x.png","k_1g8psin":"[乒乓]@2x.png","k_1gjzu3p":"[汽车]@2x.png","k_1h8mr0k":"[强]@2x.png","k_1g45y2n":"[敲打]@2x.png","k_1gkaxsl":"[青蛙]@2x.png","k_0jcfnoo":"[糗大了]@2x.png","k_1g4njy1":"[拳头]@2x.png","k_1h8mqr3":"[弱]@2x.png","k_1h926fg":"[色]@2x.png","k_1g6rtbq":"[沙发]@2x.png","k_1giirh6":"[删除]@2x.png","k_1g14ny9":"[闪电]@2x.png","k_1g6bmsr":"[胜利]@2x.png","k_1g1rytx":"[示爱]@2x.png","k_1g52fbz":"[手枪]@2x.png","k_1h90dam":"[衰]@2x.png","k_1gigiae":"[睡觉]@2x.png","k_1gijchz":"[太阳]@2x.png","k_1g1sgji":"[跳绳]@2x.png","k_1gjwuri":"[跳跳]@2x.png","k_1g0juhk":"[偷笑]@2x.png","k_1h8nzla":"[吐]@2x.png","k_1g6cv0i":"[委屈]@2x.png","k_1g46l5g":"[握手]@2x.png","k_1g2pgkd":"[西瓜]@2x.png","k_1ging9p":"[下雨]@2x.png","k_1h8nzil":"[吓]@2x.png","k_1g7q7wr":"[献吻]@2x.png","k_1gl6uum":"[香蕉]@2x.png","k_1g23fys":"[象棋]@2x.png","k_0j75rdh":"[心碎了]@2x.png","k_1g6ajj2":"[信封]@2x.png","k_1g21prz":"[熊猫]@2x.png","k_1h8octi":"[嘘]@2x.png","k_1h91zox":"[药]@2x.png","k_1ghttfl":"[疑问]@2x.png","k_1ghk7sz":"[阴险]@2x.png","k_0gl37zz":"[右车头]@2x.png","k_0ifkj1p":"[右哼哼]@2x.png","k_0g1yh2e":"[右太极]@2x.png","k_1g9dkfc":"[雨伞]@2x.png","k_1g8jl88":"[月亮]@2x.png","k_1h8lhqj":"[晕]@2x.png","k_1gi9x2q":"[再见]@2x.png","k_1g6dwwv":"[炸弹]@2x.png","k_1fzmkfi":"[折磨]@2x.png","k_1g6jbiw":"[纸巾]@2x.png","k_1ggjnwu":"[咒骂]@2x.png","k_1g4qlq8":"[猪头]@2x.png","k_1g1lqzz":"[抓狂]@2x.png","k_1g80j3u":"[转圈]@2x.png","k_1g0z55s":"[龇牙]@2x.png","k_1g3ju6v":"[钻戒]@2x.png","k_0gl51l6":"[左车头]@2x.png","k_0iflllk":"[左哼哼]@2x.png","k_0g1y3ir":"[左太极]@2x.png","k_026hiq5":"消息列表加载中","k_003tu8k":"爱你","k_003myvp":"傲慢","k_003kddw":"白眼","k_039yfhv":"棒棒糖","k_003nu3p":"抱抱","k_003nijr":"抱拳","k_003mg88":"爆筋","k_002v17e":"鄙视","k_003qhy4":"闭嘴","k_003l5fq":"鞭炮","k_003uacl":"便便","k_003oq1g":"擦汗","k_003qvey":"彩带","k_003jci7":"彩球","k_003pyu1":"菜刀","k_003q97d":"差劲","k_003po5d":"车厢","k_03eadb2":"打哈欠","k_003pnuf":"大兵","k_003kg57":"蛋糕","k_003mxkt":"得意","k_003onu3":"灯泡","k_002uv8s":"凋谢","k_003kqy0":"调皮","k_003tyum":"多云","k_003pv9u":"发呆","k_036o6mu":"发抖t","k_003nogx":"飞机","k_003q7wg":"飞吻","k_003m0jd":"奋斗","k_002ult9":"风车","k_003r8gt":"尴尬","k_003qy4u":"勾引","k_003mnoa":"鼓掌","k_003lmw8":"害羞","k_003mb30":"憨笑","k_03bj41g":"红灯笼","k_03dxw2f":"红双喜","k_003mk57":"坏笑","k_003nmvf":"挥手","k_003r2i7":"回头","k_002s6f3":"饥饿","k_003qd0t":"激动","k_002vgi4":"街舞","k_003nz33":"惊恐","k_002wh4p":"惊讶","k_003ozpu":"咖啡","k_003qvs4":"磕头","k_003l3wb":"可爱","k_003nuwm":"可怜","k_002rw1q":"抠鼻","k_002tujb":"骷髅","k_00030eq":"酷","k_03i8ath":"快哭了","k_000421h":"困","k_003l5i7":"蜡烛","k_003j72g":"篮球","k_003ofwl":"冷汗","k_02mw65v":"礼品袋","k_003ku40":"礼物","k_003ookz":"流汗","k_003on72":"流泪","k_003rjy0":"麻将","k_003q2f8":"猫咪","k_03et393":"么么哒","k_003j7j2":"玫瑰","k_002sr0b":"米饭","k_003nnza":"面条","k_003jef9":"奶瓶","k_002umn0":"难过","k_002rjib":"闹钟","k_0003zcn":"怒","k_003jzwq":"怄火","k_003j4js":"皮球","k_002r5ir":"啤酒","k_002ubu4":"瓢虫","k_003ppo6":"撇嘴","k_003ty3o":"乒乓","k_002vxwe":"汽车","k_00043hb":"强","k_003nmbo":"敲打","k_002tfhq":"青蛙","k_03i7lrn":"糗大了","k_003r03m":"拳头","k_00043h0":"弱","k_000345z":"色","k_003qmp9":"沙发","k_003it8a":"闪电","k_003pxow":"胜利","k_003kw8e":"示爱","k_003n99g":"手枪","k_00035cl":"衰","k_002vl3h":"睡觉","k_002rgqk":"太阳","k_003m9d1":"跳绳","k_002vobp":"跳跳","k_003mkoz":"偷笑","k_00041px":"吐","k_003rjh5":"委屈","k_003j36u":"西瓜","k_002re92":"下雨","k_00041py":"吓","k_003q06o":"献吻","k_002ubjp":"香蕉","k_003o2tr":"象棋","k_03ie6pa":"心碎了","k_003rao5":"信封","k_003l3us":"熊猫","k_000424d":"嘘","k_00033yi":"药","k_002qtyy":"疑问","k_002qe0o":"阴险","k_03gu7us":"右车头","k_03ere8m":"右哼哼","k_003uqk3":"雨伞","k_003tzdv":"月亮","k_0003z00":"晕","k_002vdrd":"再见","k_003ra1w":"炸弹","k_003lcad":"折磨","k_003q7sz":"纸巾","k_002thn9":"咒骂","k_003qx7f":"猪头","k_003l044":"抓狂","k_003qg4h":"转圈","k_003kb97":"龇牙","k_03gu53l":"左车头","k_03erd1f":"左哼哼","k_003nyvl":"爱情","k_003r85z":"爱心","k_003mk8j":"钞票","k_003pwfj":"大哭","k_00042w5":"刀","k_003nmtr":"握手","k_03c529p":"右太极","k_003n4mk":"钻戒","k_03c5488":"左太极","k_1llp7tu":"该用户不存在","k_0tbyqyb":"加载中…","k_0td1p3f":"保存中…","k_1klqdh1":"仅限汉字、英文、数字和下划线","k_03el5lp":"未填写","k_1ui0gai":"搜索指定内容"} \ No newline at end of file diff --git a/lib/i18n/strings_zh-Hans.i18n.json b/lib/i18n/strings_zh-Hans.i18n.json index 310bb26..51ecdb3 100644 --- a/lib/i18n/strings_zh-Hans.i18n.json +++ b/lib/i18n/strings_zh-Hans.i18n.json @@ -513,5 +513,148 @@ "k_0gl51l6": "[左车头]@2x.png", "k_0iflllk": "[左哼哼]@2x.png", "k_0g1y3ir": "[左太极]@2x.png", - "k_026hiq5": "消息列表加载中" + "k_026hiq5": "消息列表加载中", + "k_003tu8k": "爱你", + "k_003myvp": "傲慢", + "k_003kddw": "白眼", + "k_039yfhv": "棒棒糖", + "k_003nu3p": "抱抱", + "k_003nijr": "抱拳", + "k_003mg88": "爆筋", + "k_002v17e": "鄙视", + "k_003qhy4": "闭嘴", + "k_003l5fq": "鞭炮", + "k_003uacl": "便便", + "k_003oq1g": "擦汗", + "k_003qvey": "彩带", + "k_003jci7": "彩球", + "k_003pyu1": "菜刀", + "k_003q97d": "差劲", + "k_003po5d": "车厢", + "k_03eadb2": "打哈欠", + "k_003pnuf": "大兵", + "k_003kg57": "蛋糕", + "k_003mxkt": "得意", + "k_003onu3": "灯泡", + "k_002uv8s": "凋谢", + "k_003kqy0": "调皮", + "k_003tyum": "多云", + "k_003pv9u": "发呆", + "k_036o6mu": "发抖t", + "k_003nogx": "飞机", + "k_003q7wg": "飞吻", + "k_003m0jd": "奋斗", + "k_002ult9": "风车", + "k_003r8gt": "尴尬", + "k_003qy4u": "勾引", + "k_003mnoa": "鼓掌", + "k_003lmw8": "害羞", + "k_003mb30": "憨笑", + "k_03bj41g": "红灯笼", + "k_03dxw2f": "红双喜", + "k_003mk57": "坏笑", + "k_003nmvf": "挥手", + "k_003r2i7": "回头", + "k_002s6f3": "饥饿", + "k_003qd0t": "激动", + "k_002vgi4": "街舞", + "k_003nz33": "惊恐", + "k_002wh4p": "惊讶", + "k_003ozpu": "咖啡", + "k_003qvs4": "磕头", + "k_003l3wb": "可爱", + "k_003nuwm": "可怜", + "k_002rw1q": "抠鼻", + "k_002tujb": "骷髅", + "k_00030eq": "酷", + "k_03i8ath": "快哭了", + "k_000421h": "困", + "k_003l5i7": "蜡烛", + "k_003j72g": "篮球", + "k_003ofwl": "冷汗", + "k_02mw65v": "礼品袋", + "k_003ku40": "礼物", + "k_003ookz": "流汗", + "k_003on72": "流泪", + "k_003rjy0": "麻将", + "k_003q2f8": "猫咪", + "k_03et393": "么么哒", + "k_003j7j2": "玫瑰", + "k_002sr0b": "米饭", + "k_003nnza": "面条", + "k_003jef9": "奶瓶", + "k_002umn0": "难过", + "k_002rjib": "闹钟", + "k_0003zcn": "怒", + "k_003jzwq": "怄火", + "k_003j4js": "皮球", + "k_002r5ir": "啤酒", + "k_002ubu4": "瓢虫", + "k_003ppo6": "撇嘴", + "k_003ty3o": "乒乓", + "k_002vxwe": "汽车", + "k_00043hb": "强", + "k_003nmbo": "敲打", + "k_002tfhq": "青蛙", + "k_03i7lrn": "糗大了", + "k_003r03m": "拳头", + "k_00043h0": "弱", + "k_000345z": "色", + "k_003qmp9": "沙发", + "k_003it8a": "闪电", + "k_003pxow": "胜利", + "k_003kw8e": "示爱", + "k_003n99g": "手枪", + "k_00035cl": "衰", + "k_002vl3h": "睡觉", + "k_002rgqk": "太阳", + "k_003m9d1": "跳绳", + "k_002vobp": "跳跳", + "k_003mkoz": "偷笑", + "k_00041px": "吐", + "k_003rjh5": "委屈", + "k_003j36u": "西瓜", + "k_002re92": "下雨", + "k_00041py": "吓", + "k_003q06o": "献吻", + "k_002ubjp": "香蕉", + "k_003o2tr": "象棋", + "k_03ie6pa": "心碎了", + "k_003rao5": "信封", + "k_003l3us": "熊猫", + "k_000424d": "嘘", + "k_00033yi": "药", + "k_002qtyy": "疑问", + "k_002qe0o": "阴险", + "k_03gu7us": "右车头", + "k_03ere8m": "右哼哼", + "k_003uqk3": "雨伞", + "k_003tzdv": "月亮", + "k_0003z00": "晕", + "k_002vdrd": "再见", + "k_003ra1w": "炸弹", + "k_003lcad": "折磨", + "k_003q7sz": "纸巾", + "k_002thn9": "咒骂", + "k_003qx7f": "猪头", + "k_003l044": "抓狂", + "k_003qg4h": "转圈", + "k_003kb97": "龇牙", + "k_03gu53l": "左车头", + "k_03erd1f": "左哼哼", + "k_003nyvl": "爱情", + "k_003r85z": "爱心", + "k_003mk8j": "钞票", + "k_003pwfj": "大哭", + "k_00042w5": "刀", + "k_003nmtr": "握手", + "k_03c529p": "右太极", + "k_003n4mk": "钻戒", + "k_03c5488": "左太极", + "k_1llp7tu": "该用户不存在", + "k_0tbyqyb": "加载中…", + "k_0td1p3f": "保存中…", + "k_1klqdh1": "仅限汉字、英文、数字和下划线", + "k_03el5lp": "未填写", + "k_1ui0gai": "搜索指定内容" } \ No newline at end of file diff --git a/lib/i18n/strings_zh-Hant.i18n.json b/lib/i18n/strings_zh-Hant.i18n.json index 8bc3216..5c5f102 100644 --- a/lib/i18n/strings_zh-Hant.i18n.json +++ b/lib/i18n/strings_zh-Hant.i18n.json @@ -1 +1 @@ -{"k_1yemzyd":"收到一條訊息","k_0ylosxn":"自定義訊息","k_13sajrj":"貼圖訊息","k_13sjeb7":"檔案訊息","k_0yd2ft8":"群提示訊息","k_13s7mxn":"圖片訊息","k_13satlt":"位置訊息","k_00bbtsx":"合並轉發訊息","k_13sqwu4":"語音訊息","k_13sqjjp":"影片","k_1fdhj9g":"該版本不支持此訊息","k_06pujtm":"同意任何用戶添加好友","k_0gyhkp5":"需要驗證","k_121ruco":"拒絕任何人加好友","k_05nspni":"自定義字段","k_03fchyy":"群頭像","k_03i9mfe":"群簡介","k_03agq58":"群名稱","k_039xqny":"群通知","k_003tr0a":"群主","k_03iqsh4":"$s為 ","k_191t5n4":"$opUserNickName修改","k_1pg6aoj":"$opUserNickName退出群組","k_1f6zt3v":"邀請$invitedMemberString加入群組","k_0y7zd07":"將$invitedMemberString踢出群組","k_03c49qt":"去授權","k_1d5mshh":"用戶$joinedMemberString加入了群組","k_002wddw":"禁言","k_0got6f7":"解除禁言","k_0yenqf0":"$userName 被","k_0spotql":"將 $adminMember 設置為管理員","k_0pg5zzj":"系統訊息 $operationType","k_0ohzb9l":"通話時間:$callTime","k_1uaqed6":"[自定義]","k_0z2z7rx":"[語音]","k_0y39ngu":"[貼圖]","k_1c7z88n":"[檔案] $fileName","k_0y1a2my":"[圖片]","k_0z4fib8":"[影片]","k_0y24mcg":"[位置]","k_0pewpd1":"[聊天記錄]","k_13s8d9p":"未知訊息","k_1c3us5n":"當前群組不支持@全體成員","k_11k579v":"發言中有非法語句","k_003qkx2":"日歷","k_003n2pz":"相機","k_03idjo0":"聯絡人","k_003ltgm":"位置","k_02k3k86":"咪高風","k_003pm7l":"相冊","k_15ao57x":"相冊寫入","k_164m3jd":"本地存儲","k_0qba4ns":"想訪問您的$yoursItem","k_03r6qyx":"我們需要您的同意才能獲取信息","k_02noktt":"不允許","k_00043x4":"好","k_003qzac":"昨天","k_003r39d":"前天","k_03fqp9o":"星期天","k_03ibg5h":"星期一","k_03i7hu1":"星期二","k_03iaiks":"星期三","k_03el9pa":"星期四","k_03i7ok1":"星期五","k_03efxyg":"星期六","k_0oozw9x":"$diffMinutes 分鐘前","k_003q7ba":"下午","k_003q7bb":"上午","k_003pu3h":"現在","k_13hzn00":"昨天 $yesterday","k_0n9pyxz":"用戶不存在","k_1bjwemh":"搜尋用戶 ID","k_003kv3v":"搜尋","k_02owlq8":"我的用戶ID: $userID","k_1wu8h4x":"我是: $showName","k_16758qw":"添加好友","k_1shx4d9":"個性簽名: $selfSignature","k_0i553x0":"填寫驗證信息","k_031ocwx":"請填寫備註和分組","k_003ojje":"備註","k_003lsav":"分組","k_167bdvq":"我的好友","k_156b4ut":"好友申請已發送","k_002r305":"發送","k_03gu05e":"聊天室","k_03b4f3p":"會議群","k_03avj1p":"公開群","k_03asq2g":"工作群","k_03b3hbi":"未知群","k_1loix7s":"群類型: $groupType","k_1lqbsib":"該群組不存在","k_03h153m":"搜尋群ID","k_0oxak3r":"群申請已發送","k_002rflt":"刪除","k_1don84v":"無法定位到原訊息","k_003q5fi":"復製","k_003prq0":"轉發","k_002r1h2":"多選","k_003j708":"引用","k_003pqpr":"回收","k_03ezhho":"已復製","k_11ctfsz":"暫未實現","k_1hbjg5g":"[群系統訊息]","k_03tvswb":"[未知訊息]","k_155cj23":"您回收了一條訊息,","k_0gapun3":"重新編輯","k_1uh417q":"$displayName回收了一條訊息","k_1aszp2k":"您確定要重發這條訊息麽?","k_003rzap":"確定","k_003nevv":"取消","k_0003z7x":"您","k_002wfe4":"已讀","k_002wjlg":"未讀","k_0h1ygf8":"發起通話","k_0h169j0":"取消通話","k_0h13jjk":"接受通話","k_0h19hfx":"拒絕通話","k_0obi9lh":"超時未接聽","k_0y9u662":"「$appName」暫不可以開啟此類檔案,你可以使用其他應用開啟並預覽","k_001nmhu":"用其他應用開啟","k_1ht1b80":"正在接收中","k_105682d":"圖片載入失敗","k_0pytyeu":"圖片保存成功","k_0akceel":"圖片保存失敗","k_003rk1s":"保存","k_04a0awq":"[語音訊息]","k_105c3y3":"影片載入失敗","k_176rzr7":"聊天記錄","k_0d5z4m5":"選擇提醒人","k_003ngex":"完成","k_1665ltg":"發起呼叫","k_003n8b0":"拍攝","k_003kthh":"照片","k_003tnp0":"檔案","k_0jhdhtp":"發送失敗,影片不能大於100MB","k_119ucng":"圖片不能為空","k_0w9x8gw":"選擇成功$successPath","k_13dsw4l":"松開取消","k_0am7r68":"手指上滑,取消發送","k_15jl6qw":"說話時間太短!","k_0gx7vl6":"按住說話","k_15dlafd":"逐條轉發","k_15dryxy":"合並轉發","k_1eyhieh":"確定刪除已選訊息","k_17fmlyf":"清除聊天","k_0dhesoz":"取消置頂","k_002sk7x":"置頂","k_003ll77":"草稿","k_03icaxo":"自定義","k_1969986":"[語音通話]:$callingLastMsgShow","k_1960dlr":"[視訊通話]:$callingLastMsgShow","k_1np495n":"$messageString[有人@我]","k_1m797yi":"$messageString[@所有人]","k_1uaov41":"查找聊天內容","k_003kfai":"未知","k_13dq4an":"自動審批","k_0l13cde":"管理員審批","k_11y8c6a":"禁止加群","k_1kvyskd":"無網絡連接,無法修改","k_16payqf":"加群方式","k_0vzvn8r":"修改群名稱","k_038lh6u":"群管理","k_0k5wyiy":"設置管理員","k_0goiuwk":"全員禁言","k_1g889xx":"全員禁言開啟後,只允許群主和管理員發言。","k_0wlrefq":"添加需要禁言的群成員","k_0goox5g":"設置禁言","k_08daijh":"成功取消管理員身份","k_0bxm97s":"管理員 ($adminNum/10)","k_0k5u935":"添加管理員","k_03enyx5":"群成員","k_0jayw3z":"群成員($groupMemberNum人)","k_0h1svv1":"刪除群成員","k_0h1g636":"添加群成員","k_0uj7208":"無網絡連接,無法查看群成員","k_01yfa4o":"$memberCount人","k_0hpukyx":"查看更多群成員","k_0qtsar0":"訊息免打擾","k_0ef2a12":"修改我的群昵稱","k_1aajych":"僅限中文、字母、數字和下劃線,2-20個字","k_137pab5":"我的群昵稱","k_0ivim6d":"暫無群公告","k_03eq6cn":"群公告","k_002vxya":"編輯","k_17fpl3y":"置頂聊天","k_03es1ox":"群類型","k_003mz1i":"同意","k_003lpre":"拒絕","k_003qk66":"頭像","k_003lhvk":"昵稱","k_003ps50":"賬號","k_15lx52z":"個性簽名","k_003qgkp":"性別","k_003m6hr":"生日","k_0003v6a":"男","k_00043x2":"女","k_03bcjkv":"未設置","k_11s0gdz":"修改昵稱","k_0p3j4sd":"僅限中字、字母、數字和下劃線","k_15lyvdt":"修改簽名","k_0vylzjp":"這個人很懶,什麽也沒寫","k_1hs7ese":"等上線再改這個","k_03exjk7":"備註名","k_0s3skfd":"加入黑名單","k_0p3b31s":"修改備註名","k_0003y9x":"無","k_11zgnfs":"個人資料","k_03xd79d":"個性簽名: $signature","k_1tez2xl":"暫無個性簽名","k_118prbn":"全局搜尋","k_1m9dftc":"全部聯絡人","k_0em4gyz":"全部群組","k_002twmj":"群組","k_09kga0d":"更多聊天記錄","k_1ui5lzi":"$count條相關聊天記錄","k_09khmso":"相關聊天記錄","k_1kevf4k":"與$receiver的聊天記錄","k_0vjj2kp":"群組的聊天記錄","k_003n2rp":"選擇","k_03ignw6":"所有人","k_03erpei":"管理員","k_0qi9tno":"群主、管理員","k_1m9exwh":"最近聯絡人","k_119nwqr":"輸入不能為空","k_0pzwbmg":"影片保存成功","k_0aktupv":"影片保存失敗","k_1qbg9xc":"$option8為 ","k_1wq5ubm":"$option7修改","k_0y5pu80":"$option6退出群組","k_0nl7cmd":"邀請$option5加入群組","k_1ju5iqw":"將$option4踢出群組","k_1ovt677":"用戶$option3加入了群組","k_0k05b8b":"$option2 被","k_0wm4xeb":"系統訊息 $option2","k_0nbq9v3":"通話時間:$option2","k_0i1kf53":"[檔案] $option2","k_1gnnby6":"想訪問您的$option2","k_1wh4atg":"$option2 分鐘前","k_07sh7g1":"昨天 $option2","k_1pj8xzh":"我的用戶ID: $option2","k_0py1evo":"個性簽名: $option2","k_1kvj4i2":"$option2回收了一條訊息","k_1v0lbpp":"「$option2」暫不可以開啟此類檔案,你可以使用其他應用開啟並預覽","k_0torwfz":"選擇成功$option2","k_0i1bjah":"$option1回收了一條訊息","k_1qzxh9q":"通話時間:$option3","k_0wrgmom":"[語音通話]:$option1","k_06ix2f0":"[視訊通話]:$option2","k_08o3z5w":"[檔案] $option1","k_0ezbepg":"$option2[有人@我]","k_1ccnht1":"$option2[@所有人]","k_1k3arsw":"管理員 ($option2/10)","k_1d4golg":"群成員($option1人)","k_1bg69nt":"$option1人","k_00gjqxj":"個性簽名: $option1","k_0c29cxr":"$option1條相關聊天記錄","k_1twk5rz":"與$option1的聊天記錄","k_1vn4xq1":"將 $adminMember 取消管理員","k_0e35hsw":"為方便您將所拍攝的照片或影片發送給朋友,以及進行視訊通話,請允許我們訪問攝像頭進行拍攝照片和影片。","k_0dj6yr7":"為方便您發送語音訊息、拍攝影片以及音視訊通話,請允許我們使用咪高風進行錄音。","k_003qnsl":"存儲","k_0s3rtpw":"為方便您查看和選擇相冊裏的圖片影片發送給朋友,以及保存內容到設備,請允許我們訪問您設備上的照片、媒體內容。","k_0tezv85":" 申請獲取$option2","k_002rety":"權限","k_18o68ro":"需要授予","k_1onpf8u":" 相機權限,以正常使用拍攝圖片/影片、視訊通話等功能。","k_17irga5":" 咪高風權限,以正常使用發送語音訊息、拍攝影片、音視訊通話等功能。","k_0572kc4":" 訪問照片權限,以正常使用發送圖片、影片等功能。","k_0slykws":" 訪問相冊寫入權限,以正常使用存儲圖片、影片等功能。","k_119pkcd":" 檔案讀寫權限,以正常使用在聊天功能中的圖片查看、選擇能力和發送檔案的能力。","k_0gqewd3":"以後再說","k_03eq4s1":"去開啟","k_0nt2uyg":"回到最新位置","k_04l16at":"$option1條新訊息","k_13p3w93":"有人@我","k_18w5uk6":"@所有人","k_0jmujgh":"其他檔案正在接收中","k_12s5ept":"訊息詳情","k_0mxa4f4":"$option1人已讀","k_061tue3":"$option2人未讀","k_18qjstb":"轉讓群主","k_0on1aj2":"有$option2條@我訊息","k_09j4izl":"[有人@我] ","k_1oqtjw0":"[@所有人] ","k_1x5a9vb":"我是: $option1","k_14n31e7":"進群請求","k_08nc5j1":"群類型: $option1","k_1josu12":"$option1 條入群請求","k_0n2x5s0":"驗證消息: $option2","k_03c1nx0":"已同意","k_03aw9w8":"已拒絕","k_038ryos":"去處理","k_0gw8pum":"進群申請","k_1gcvfrj":"請填寫備註名","k_002v9zj":"确认","k_10oqrki":"轻触拍照","k_0f8b3ws":"加载失败","k_11cm5lm":"手动聚焦","k_002uzrd":"预览","k_003qkn3":"录像","k_003k6a7":"拍照","k_0bqpqco":"拍照按钮","k_1626ozl":"停止录像","k_003lvmu":"前置","k_003lued":"后置","k_003lwzh":"外置","k_002qzi3":"关闭","k_003pufb":"自动","k_0apm0ze":"拍照时闪光","k_157zog5":"始终闪光","k_0cfyqhy":"$option1 画面预览","k_0phctlz":"闪光模式: $option2","k_02vfqe0":"切换至 $option3 摄像头","k_0f0y9ex":"说话时间太短","k_0ln70tk":"无法打开URL","k_11a3jdv":"轻触拍照,长按摄像","k_1k18miv":"请传入离开群组生命周期函数,提供返回首页或其他页面的导航方法。","k_1fu9ahv":"全员禁言状态","k_0gmwbnd":"全员禁言中","k_0got2zr":"您被禁言","k_0y9jck8":"你必须自定义search bar,并处理点击跳转","k_0yum3tv":"如使用自定义区域,请在profileWidgetBuilder传入对应组件","k_09kalj0":"清空聊天记录","k_14j5iul":"删除并退出","k_125ru1w":"解散该群","k_0jtutmw":"退出后不会接收到此群聊消息","k_0jtzmqa":"解散后不会接收到此群聊消息","k_0r8fi93":"好友添加成功","k_02qw14e":"好友申请已发出","k_0n3md5x":"当前用户在黑名单","k_094phq4":"好友添加失败","k_129scag":"好友删除成功","k_129uzfn":"好友删除失败","k_1666isy":"清除好友","k_1679vrd":"加为好友","k_1ualc52":"看看对方带来的数据是啥","k_0szluvp":"设置对方在线状态","k_0f4rnf8":"该用户已是好友","k_1tdkom4":"您已是群成员","k_1p2lyuz":"对方正在输入中...","k_1g8wfpy":"...共$option1人","k_12rv9vw":"回应详情","k_0havgi0":"[查看详情 >>](${linkMessage.link})","k_0n9p7g8":"群组不存在","k_1tdh5vn":"您不是群成员","k_0h1q57v":"暂无群成员","k_0y5drq1":"[查看详情 >>]($option1)","k_03pjp61":"[表情消息]","k_1jpvzul":"[自定义消息]","k_03u3bh1":"[文件消息]","k_1odsnsw":"[群消息]","k_03sel4t":"[图片消息]","k_03sfw3r":"[位置消息]","k_03xpuwq":"[合并消息]","k_07ycxwo":"[没有元素]","k_03rc9vz":"[文本消息]","k_046uopf":"[视频消息]","k_0ehmsun":"设备存储空间不足,建议清理,以获得更好使用体验","k_003kmos":"图片","k_002s86q":"视频","k_06bk5ei":"视频消息仅限 mp4 格式","k_13opfxf":"Web网页端不支持搜索","k_1i0o0y2":"暂时仅限 Android/iOS 端","k_045dtzl":"$option1的聊天记录","k_0t0131u":"群资料信息","k_18ok8xz":"消息接收方式","k_03ax3ks":"群资料","k_0sqvoqo":"将 $option1 设置为管理员","k_1gbg1v8":"将 $option1 取消管理员","k_17k64g4":"群聊创建成功!","k_05mn217":"暂未安装表情包插件,如需使用表情相关功能,请根据本文档安装:https://cloud.tencent.com/document/product/269/70746","k_14j17nz":"暂无表情包","k_0fvjexh":"正在下载中","k_1cdagzz":"已加入待下载队列,其他文件下载中","k_0g4vojc":"开始下载","k_1g32es3":"[调皮]@2x.png","k_1g8qorz":"[爱你]@2x.png","k_1g4hmx6":"[爱情]@2x.png","k_1g6b558":"[爱心]@2x.png","k_1g3m4su":"[傲慢]@2x.png","k_1g2jym7":"[白眼]@2x.png","k_0cgkxuw":"[棒棒糖]@2x.png","k_1g48br2":"[抱抱]@2x.png","k_1g49ol8":"[抱拳]@2x.png","k_1g0ras3":"[爆筋]@2x.png","k_1ghy881":"[鄙视]@2x.png","k_1g86bmv":"[闭嘴]@2x.png","k_1g1xs1p":"[鞭炮]@2x.png","k_1g8i6ri":"[便便]@2x.png","k_1g2u5kf":"[擦汗]@2x.png","k_1g60uwh":"[彩带]@2x.png","k_1g1o0d0":"[彩球]@2x.png","k_1g6a6yq":"[菜刀]@2x.png","k_1g6vqo2":"[差劲]@2x.png","k_1g0kvjc":"[钞票]@2x.png","k_1g65x7e":"[车厢]@2x.png","k_0e1tjol":"[打哈欠]@2x.png","k_1g65n58":"[大兵]@2x.png","k_1g7se7o":"[大哭]@2x.png","k_1g03868":"[蛋糕]@2x.png","k_1h8nm66":"[刀]@2x.png","k_1g3dlpi":"[得意]@2x.png","k_1g3u434":"[灯泡]@2x.png","k_1giuqs7":"[凋谢]@2x.png","k_1g8r0r9":"[多云]@2x.png","k_1g7k6i1":"[发呆]@2x.png","k_1g44zsp":"[发抖]@2x.png","k_1g5l96i":"[飞机]@2x.png","k_1g7wsqj":"[飞吻]@2x.png","k_1g49luq":"[奋斗]@2x.png","k_1gixbsm":"[风车]@2x.png","k_1g6cqbq":"[尴尬]@2x.png","k_1g6jbw5":"[勾引]@2x.png","k_1g3lwo1":"[鼓掌]@2x.png","k_1g13nkj":"[害羞]@2x.png","k_1g0mt47":"[憨笑]@2x.png","k_0bxujkf":"[红灯笼]@2x.png","k_0hhaeh8":"[红双喜]@2x.png","k_1g0jnts":"[坏笑]@2x.png","k_1g46g9c":"[挥手]@2x.png","k_1g4vi9g":"[回头]@2x.png","k_1gf7hes":"[饥饿]@2x.png","k_1g6mvsm":"[激动]@2x.png","k_1gku5mf":"[街舞]@2x.png","k_1g4hidg":"[惊恐]@2x.png","k_1gjbrtu":"[惊讶]@2x.png","k_1g6sand":"[咖啡]@2x.png","k_1g4s8rj":"[磕头]@2x.png","k_1g1wn34":"[可爱]@2x.png","k_1g3l0wd":"[可怜]@2x.png","k_1ggaon9":"[抠鼻]@2x.png","k_1ggvcb0":"[骷髅]@2x.png","k_1h8yqjt":"[酷]@2x.png","k_0jac97i":"[快哭了]@2x.png","k_1h8oiby":"[困]@2x.png","k_1g0s5hg":"[蜡烛]@2x.png","k_1g1iuer":"[篮球]@2x.png","k_1g2xjfi":"[冷汗]@2x.png","k_0s5oyqw":"[礼品袋]@2x.png","k_1g1qqvf":"[礼物]@2x.png","k_1g2slew":"[流汗]@2x.png","k_1g3z9xx":"[流泪]@2x.png","k_1g6pabn":"[麻将]@2x.png","k_0pkaxul":"[麦克风]@2x.png","k_1g7m0zj":"[猫咪]@2x.png","k_0ibvtpo":"[么么哒]@2x.png","k_1g1hoh1":"[玫瑰]@2x.png","k_1gfzeow":"[米饭]@2x.png","k_1g5l15p":"[面条]@2x.png","k_1g2hfa6":"[奶瓶]@2x.png","k_1gix9pj":"[难过]@2x.png","k_1giqn6g":"[闹钟]@2x.png","k_1h8kd64":"[怒]@2x.png","k_1g0vui9":"[怄火]@2x.png","k_1g1jsj7":"[皮球]@2x.png","k_1ghdluw":"[啤酒]@2x.png","k_1gl6ec7":"[瓢虫]@2x.png","k_1g7gg5p":"[撇嘴]@2x.png","k_1g8psin":"[乒乓]@2x.png","k_1gjzu3p":"[汽车]@2x.png","k_1h8mr0k":"[强]@2x.png","k_1g45y2n":"[敲打]@2x.png","k_1gkaxsl":"[青蛙]@2x.png","k_0jcfnoo":"[糗大了]@2x.png","k_1g4njy1":"[拳头]@2x.png","k_1h8mqr3":"[弱]@2x.png","k_1h926fg":"[色]@2x.png","k_1g6rtbq":"[沙发]@2x.png","k_1giirh6":"[删除]@2x.png","k_1g14ny9":"[闪电]@2x.png","k_1g6bmsr":"[胜利]@2x.png","k_1g1rytx":"[示爱]@2x.png","k_1g52fbz":"[手枪]@2x.png","k_1h90dam":"[衰]@2x.png","k_1gigiae":"[睡觉]@2x.png","k_1gijchz":"[太阳]@2x.png","k_1g1sgji":"[跳绳]@2x.png","k_1gjwuri":"[跳跳]@2x.png","k_1g0juhk":"[偷笑]@2x.png","k_1h8nzla":"[吐]@2x.png","k_1g6cv0i":"[委屈]@2x.png","k_1g46l5g":"[握手]@2x.png","k_1g2pgkd":"[西瓜]@2x.png","k_1ging9p":"[下雨]@2x.png","k_1h8nzil":"[吓]@2x.png","k_1g7q7wr":"[献吻]@2x.png","k_1gl6uum":"[香蕉]@2x.png","k_1g23fys":"[象棋]@2x.png","k_0j75rdh":"[心碎了]@2x.png","k_1g6ajj2":"[信封]@2x.png","k_1g21prz":"[熊猫]@2x.png","k_1h8octi":"[嘘]@2x.png","k_1h91zox":"[药]@2x.png","k_1ghttfl":"[疑问]@2x.png","k_1ghk7sz":"[阴险]@2x.png","k_0gl37zz":"[右车头]@2x.png","k_0ifkj1p":"[右哼哼]@2x.png","k_0g1yh2e":"[右太极]@2x.png","k_1g9dkfc":"[雨伞]@2x.png","k_1g8jl88":"[月亮]@2x.png","k_1h8lhqj":"[晕]@2x.png","k_1gi9x2q":"[再见]@2x.png","k_1g6dwwv":"[炸弹]@2x.png","k_1fzmkfi":"[折磨]@2x.png","k_1g6jbiw":"[纸巾]@2x.png","k_1ggjnwu":"[咒骂]@2x.png","k_1g4qlq8":"[猪头]@2x.png","k_1g1lqzz":"[抓狂]@2x.png","k_1g80j3u":"[转圈]@2x.png","k_1g0z55s":"[龇牙]@2x.png","k_1g3ju6v":"[钻戒]@2x.png","k_0gl51l6":"[左车头]@2x.png","k_0iflllk":"[左哼哼]@2x.png","k_0g1y3ir":"[左太极]@2x.png","k_026hiq5":"消息列表加载中"} \ No newline at end of file +{"k_1yemzyd":"收到一條訊息","k_0ylosxn":"自定義訊息","k_13sajrj":"貼圖訊息","k_13sjeb7":"檔案訊息","k_0yd2ft8":"群提示訊息","k_13s7mxn":"圖片訊息","k_13satlt":"位置訊息","k_00bbtsx":"合並轉發訊息","k_13sqwu4":"語音訊息","k_13sqjjp":"影片","k_1fdhj9g":"該版本不支持此訊息","k_06pujtm":"同意任何用戶添加好友","k_0gyhkp5":"需要驗證","k_121ruco":"拒絕任何人加好友","k_05nspni":"自定義字段","k_03fchyy":"群頭像","k_03i9mfe":"群簡介","k_03agq58":"群名稱","k_039xqny":"群通知","k_003tr0a":"群主","k_03iqsh4":"$s為 ","k_191t5n4":"$opUserNickName修改","k_1pg6aoj":"$opUserNickName退出群組","k_1f6zt3v":"邀請$invitedMemberString加入群組","k_0y7zd07":"將$invitedMemberString踢出群組","k_03c49qt":"去授權","k_1d5mshh":"用戶$joinedMemberString加入了群組","k_002wddw":"禁言","k_0got6f7":"解除禁言","k_0yenqf0":"$userName 被","k_0spotql":"將 $adminMember 設置為管理員","k_0pg5zzj":"系統訊息 $operationType","k_0ohzb9l":"通話時間:$callTime","k_1uaqed6":"[自定義]","k_0z2z7rx":"[語音]","k_0y39ngu":"[貼圖]","k_1c7z88n":"[檔案] $fileName","k_0y1a2my":"[圖片]","k_0z4fib8":"[影片]","k_0y24mcg":"[位置]","k_0pewpd1":"[聊天記錄]","k_13s8d9p":"未知訊息","k_1c3us5n":"當前群組不支持@全體成員","k_11k579v":"發言中有非法語句","k_003qkx2":"日歷","k_003n2pz":"相機","k_03idjo0":"聯絡人","k_003ltgm":"位置","k_02k3k86":"咪高風","k_003pm7l":"相冊","k_15ao57x":"相冊寫入","k_164m3jd":"本地存儲","k_0qba4ns":"想訪問您的$yoursItem","k_03r6qyx":"我們需要您的同意才能獲取信息","k_02noktt":"不允許","k_00043x4":"好","k_003qzac":"昨天","k_003r39d":"前天","k_03fqp9o":"星期天","k_03ibg5h":"星期一","k_03i7hu1":"星期二","k_03iaiks":"星期三","k_03el9pa":"星期四","k_03i7ok1":"星期五","k_03efxyg":"星期六","k_0oozw9x":"$diffMinutes 分鐘前","k_003q7ba":"下午","k_003q7bb":"上午","k_003pu3h":"現在","k_13hzn00":"昨天 $yesterday","k_0n9pyxz":"用戶不存在","k_1bjwemh":"搜尋用戶 ID","k_003kv3v":"搜尋","k_02owlq8":"我的用戶ID: $userID","k_1wu8h4x":"我是: $showName","k_16758qw":"添加好友","k_1shx4d9":"個性簽名: $selfSignature","k_0i553x0":"填寫驗證信息","k_031ocwx":"請填寫備註和分組","k_003ojje":"備註","k_003lsav":"分組","k_167bdvq":"我的好友","k_156b4ut":"好友申請已發送","k_002r305":"發送","k_03gu05e":"聊天室","k_03b4f3p":"會議群","k_03avj1p":"公開群","k_03asq2g":"工作群","k_03b3hbi":"未知群","k_1loix7s":"群類型: $groupType","k_1lqbsib":"該群組不存在","k_03h153m":"搜尋群ID","k_0oxak3r":"群申請已發送","k_002rflt":"刪除","k_1don84v":"無法定位到原訊息","k_003q5fi":"復製","k_003prq0":"轉發","k_002r1h2":"多選","k_003j708":"引用","k_003pqpr":"回收","k_03ezhho":"已復製","k_11ctfsz":"暫未實現","k_1hbjg5g":"[群系統訊息]","k_03tvswb":"[未知訊息]","k_155cj23":"您回收了一條訊息,","k_0gapun3":"重新編輯","k_1uh417q":"$displayName回收了一條訊息","k_1aszp2k":"您確定要重發這條訊息麽?","k_003rzap":"確定","k_003nevv":"取消","k_0003z7x":"您","k_002wfe4":"已讀","k_002wjlg":"未讀","k_0h1ygf8":"發起通話","k_0h169j0":"取消通話","k_0h13jjk":"接受通話","k_0h19hfx":"拒絕通話","k_0obi9lh":"超時未接聽","k_0y9u662":"「$appName」暫不可以開啟此類檔案,你可以使用其他應用開啟並預覽","k_001nmhu":"用其他應用開啟","k_1ht1b80":"正在接收中","k_105682d":"圖片載入失敗","k_0pytyeu":"圖片保存成功","k_0akceel":"圖片保存失敗","k_003rk1s":"保存","k_04a0awq":"[語音訊息]","k_105c3y3":"影片載入失敗","k_176rzr7":"聊天記錄","k_0d5z4m5":"選擇提醒人","k_003ngex":"完成","k_1665ltg":"發起呼叫","k_003n8b0":"拍攝","k_003kthh":"照片","k_003tnp0":"檔案","k_0jhdhtp":"發送失敗,影片不能大於100MB","k_119ucng":"圖片不能為空","k_0w9x8gw":"選擇成功$successPath","k_13dsw4l":"松開取消","k_0am7r68":"手指上滑,取消發送","k_15jl6qw":"說話時間太短!","k_0gx7vl6":"按住說話","k_15dlafd":"逐條轉發","k_15dryxy":"合並轉發","k_1eyhieh":"確定刪除已選訊息","k_17fmlyf":"清除聊天","k_0dhesoz":"取消置頂","k_002sk7x":"置頂","k_003ll77":"草稿","k_03icaxo":"自定義","k_1969986":"[語音通話]:$callingLastMsgShow","k_1960dlr":"[視訊通話]:$callingLastMsgShow","k_1np495n":"$messageString[有人@我]","k_1m797yi":"$messageString[@所有人]","k_1uaov41":"查找聊天內容","k_003kfai":"未知","k_13dq4an":"自動審批","k_0l13cde":"管理員審批","k_11y8c6a":"禁止加群","k_1kvyskd":"無網絡連接,無法修改","k_16payqf":"加群方式","k_0vzvn8r":"修改群名稱","k_038lh6u":"群管理","k_0k5wyiy":"設置管理員","k_0goiuwk":"全員禁言","k_1g889xx":"全員禁言開啟後,只允許群主和管理員發言。","k_0wlrefq":"添加需要禁言的群成員","k_0goox5g":"設置禁言","k_08daijh":"成功取消管理員身份","k_0bxm97s":"管理員 ($adminNum/10)","k_0k5u935":"添加管理員","k_03enyx5":"群成員","k_0jayw3z":"群成員($groupMemberNum人)","k_0h1svv1":"刪除群成員","k_0h1g636":"添加群成員","k_0uj7208":"無網絡連接,無法查看群成員","k_01yfa4o":"$memberCount人","k_0hpukyx":"查看更多群成員","k_0qtsar0":"訊息免打擾","k_0ef2a12":"修改我的群昵稱","k_1aajych":"僅限中文、字母、數字和下劃線,2-20個字","k_137pab5":"我的群昵稱","k_0ivim6d":"暫無群公告","k_03eq6cn":"群公告","k_002vxya":"編輯","k_17fpl3y":"置頂聊天","k_03es1ox":"群類型","k_003mz1i":"同意","k_003lpre":"拒絕","k_003qk66":"頭像","k_003lhvk":"昵稱","k_003ps50":"賬號","k_15lx52z":"個性簽名","k_003qgkp":"性別","k_003m6hr":"生日","k_0003v6a":"男","k_00043x2":"女","k_03bcjkv":"未設置","k_11s0gdz":"修改昵稱","k_0p3j4sd":"僅限中字、字母、數字和下劃線","k_15lyvdt":"修改簽名","k_0vylzjp":"這個人很懶,什麽也沒寫","k_1hs7ese":"等上線再改這個","k_03exjk7":"備註名","k_0s3skfd":"加入黑名單","k_0p3b31s":"修改備註名","k_0003y9x":"無","k_11zgnfs":"個人資料","k_03xd79d":"個性簽名: $signature","k_1tez2xl":"暫無個性簽名","k_118prbn":"全局搜尋","k_1m9dftc":"全部聯絡人","k_0em4gyz":"全部群組","k_002twmj":"群組","k_09kga0d":"更多聊天記錄","k_1ui5lzi":"$count條相關聊天記錄","k_09khmso":"相關聊天記錄","k_1kevf4k":"與$receiver的聊天記錄","k_0vjj2kp":"群組的聊天記錄","k_003n2rp":"選擇","k_03ignw6":"所有人","k_03erpei":"管理員","k_0qi9tno":"群主、管理員","k_1m9exwh":"最近聯絡人","k_119nwqr":"輸入不能為空","k_0pzwbmg":"影片保存成功","k_0aktupv":"影片保存失敗","k_1qbg9xc":"$option8為 ","k_1wq5ubm":"$option7修改","k_0y5pu80":"$option6退出群組","k_0nl7cmd":"邀請$option5加入群組","k_1ju5iqw":"將$option4踢出群組","k_1ovt677":"用戶$option3加入了群組","k_0k05b8b":"$option2 被","k_0wm4xeb":"系統訊息 $option2","k_0nbq9v3":"通話時間:$option2","k_0i1kf53":"[檔案] $option2","k_1gnnby6":"想訪問您的$option2","k_1wh4atg":"$option2 分鐘前","k_07sh7g1":"昨天 $option2","k_1pj8xzh":"我的用戶ID: $option2","k_0py1evo":"個性簽名: $option2","k_1kvj4i2":"$option2回收了一條訊息","k_1v0lbpp":"「$option2」暫不可以開啟此類檔案,你可以使用其他應用開啟並預覽","k_0torwfz":"選擇成功$option2","k_0i1bjah":"$option1回收了一條訊息","k_1qzxh9q":"通話時間:$option3","k_0wrgmom":"[語音通話]:$option1","k_06ix2f0":"[視訊通話]:$option2","k_08o3z5w":"[檔案] $option1","k_0ezbepg":"$option2[有人@我]","k_1ccnht1":"$option2[@所有人]","k_1k3arsw":"管理員 ($option2/10)","k_1d4golg":"群成員($option1人)","k_1bg69nt":"$option1人","k_00gjqxj":"個性簽名: $option1","k_0c29cxr":"$option1條相關聊天記錄","k_1twk5rz":"與$option1的聊天記錄","k_1vn4xq1":"將 $adminMember 取消管理員","k_0e35hsw":"為方便您將所拍攝的照片或影片發送給朋友,以及進行視訊通話,請允許我們訪問攝像頭進行拍攝照片和影片。","k_0dj6yr7":"為方便您發送語音訊息、拍攝影片以及音視訊通話,請允許我們使用咪高風進行錄音。","k_003qnsl":"存儲","k_0s3rtpw":"為方便您查看和選擇相冊裏的圖片影片發送給朋友,以及保存內容到設備,請允許我們訪問您設備上的照片、媒體內容。","k_0tezv85":" 申請獲取$option2","k_002rety":"權限","k_18o68ro":"需要授予","k_1onpf8u":" 相機權限,以正常使用拍攝圖片/影片、視訊通話等功能。","k_17irga5":" 咪高風權限,以正常使用發送語音訊息、拍攝影片、音視訊通話等功能。","k_0572kc4":" 訪問照片權限,以正常使用發送圖片、影片等功能。","k_0slykws":" 訪問相冊寫入權限,以正常使用存儲圖片、影片等功能。","k_119pkcd":" 檔案讀寫權限,以正常使用在聊天功能中的圖片查看、選擇能力和發送檔案的能力。","k_0gqewd3":"以後再說","k_03eq4s1":"去開啟","k_0nt2uyg":"回到最新位置","k_04l16at":"$option1條新訊息","k_13p3w93":"有人@我","k_18w5uk6":"@所有人","k_0jmujgh":"其他檔案正在接收中","k_12s5ept":"訊息詳情","k_0mxa4f4":"$option1人已讀","k_061tue3":"$option2人未讀","k_18qjstb":"轉讓群主","k_0on1aj2":"有$option2條@我訊息","k_09j4izl":"[有人@我] ","k_1oqtjw0":"[@所有人] ","k_1x5a9vb":"我是: $option1","k_14n31e7":"進群請求","k_08nc5j1":"群類型: $option1","k_1josu12":"$option1 條入群請求","k_0n2x5s0":"驗證消息: $option2","k_03c1nx0":"已同意","k_03aw9w8":"已拒絕","k_038ryos":"去處理","k_0gw8pum":"進群申請","k_1gcvfrj":"請填寫備註名","k_002v9zj":"确认","k_10oqrki":"轻触拍照","k_0f8b3ws":"加载失败","k_11cm5lm":"手动聚焦","k_002uzrd":"预览","k_003qkn3":"录像","k_003k6a7":"拍照","k_0bqpqco":"拍照按钮","k_1626ozl":"停止录像","k_003lvmu":"前置","k_003lued":"后置","k_003lwzh":"外置","k_002qzi3":"关闭","k_003pufb":"自动","k_0apm0ze":"拍照时闪光","k_157zog5":"始终闪光","k_0cfyqhy":"$option1 画面预览","k_0phctlz":"闪光模式: $option2","k_02vfqe0":"切换至 $option3 摄像头","k_0f0y9ex":"说话时间太短","k_0ln70tk":"无法打开URL","k_11a3jdv":"轻触拍照,长按摄像","k_1k18miv":"请传入离开群组生命周期函数,提供返回首页或其他页面的导航方法。","k_1fu9ahv":"全员禁言状态","k_0gmwbnd":"全员禁言中","k_0got2zr":"您被禁言","k_0y9jck8":"你必须自定义search bar,并处理点击跳转","k_0yum3tv":"如使用自定义区域,请在profileWidgetBuilder传入对应组件","k_09kalj0":"清空聊天记录","k_14j5iul":"删除并退出","k_125ru1w":"解散该群","k_0jtutmw":"退出后不会接收到此群聊消息","k_0jtzmqa":"解散后不会接收到此群聊消息","k_0r8fi93":"好友添加成功","k_02qw14e":"好友申请已发出","k_0n3md5x":"当前用户在黑名单","k_094phq4":"好友添加失败","k_129scag":"好友删除成功","k_129uzfn":"好友删除失败","k_1666isy":"清除好友","k_1679vrd":"加为好友","k_1ualc52":"看看对方带来的数据是啥","k_0szluvp":"设置对方在线状态","k_0f4rnf8":"该用户已是好友","k_1tdkom4":"您已是群成员","k_1p2lyuz":"对方正在输入中...","k_1g8wfpy":"...共$option1人","k_12rv9vw":"回应详情","k_0havgi0":"[查看详情 >>](${linkMessage.link})","k_0n9p7g8":"群组不存在","k_1tdh5vn":"您不是群成员","k_0h1q57v":"暂无群成员","k_0y5drq1":"[查看详情 >>]($option1)","k_03pjp61":"[表情消息]","k_1jpvzul":"[自定义消息]","k_03u3bh1":"[文件消息]","k_1odsnsw":"[群消息]","k_03sel4t":"[图片消息]","k_03sfw3r":"[位置消息]","k_03xpuwq":"[合并消息]","k_07ycxwo":"[没有元素]","k_03rc9vz":"[文本消息]","k_046uopf":"[视频消息]","k_0ehmsun":"设备存储空间不足,建议清理,以获得更好使用体验","k_003kmos":"图片","k_002s86q":"视频","k_06bk5ei":"视频消息仅限 mp4 格式","k_13opfxf":"Web网页端不支持搜索","k_1i0o0y2":"暂时仅限 Android/iOS 端","k_045dtzl":"$option1的聊天记录","k_0t0131u":"群资料信息","k_18ok8xz":"消息接收方式","k_03ax3ks":"群资料","k_0sqvoqo":"将 $option1 设置为管理员","k_1gbg1v8":"将 $option1 取消管理员","k_17k64g4":"群聊创建成功!","k_05mn217":"暂未安装表情包插件,如需使用表情相关功能,请根据本文档安装:https://cloud.tencent.com/document/product/269/70746","k_14j17nz":"暂无表情包","k_0fvjexh":"正在下载中","k_1cdagzz":"已加入待下载队列,其他文件下载中","k_0g4vojc":"开始下载","k_1g32es3":"[调皮]@2x.png","k_1g8qorz":"[爱你]@2x.png","k_1g4hmx6":"[爱情]@2x.png","k_1g6b558":"[爱心]@2x.png","k_1g3m4su":"[傲慢]@2x.png","k_1g2jym7":"[白眼]@2x.png","k_0cgkxuw":"[棒棒糖]@2x.png","k_1g48br2":"[抱抱]@2x.png","k_1g49ol8":"[抱拳]@2x.png","k_1g0ras3":"[爆筋]@2x.png","k_1ghy881":"[鄙视]@2x.png","k_1g86bmv":"[闭嘴]@2x.png","k_1g1xs1p":"[鞭炮]@2x.png","k_1g8i6ri":"[便便]@2x.png","k_1g2u5kf":"[擦汗]@2x.png","k_1g60uwh":"[彩带]@2x.png","k_1g1o0d0":"[彩球]@2x.png","k_1g6a6yq":"[菜刀]@2x.png","k_1g6vqo2":"[差劲]@2x.png","k_1g0kvjc":"[钞票]@2x.png","k_1g65x7e":"[车厢]@2x.png","k_0e1tjol":"[打哈欠]@2x.png","k_1g65n58":"[大兵]@2x.png","k_1g7se7o":"[大哭]@2x.png","k_1g03868":"[蛋糕]@2x.png","k_1h8nm66":"[刀]@2x.png","k_1g3dlpi":"[得意]@2x.png","k_1g3u434":"[灯泡]@2x.png","k_1giuqs7":"[凋谢]@2x.png","k_1g8r0r9":"[多云]@2x.png","k_1g7k6i1":"[发呆]@2x.png","k_1g44zsp":"[发抖]@2x.png","k_1g5l96i":"[飞机]@2x.png","k_1g7wsqj":"[飞吻]@2x.png","k_1g49luq":"[奋斗]@2x.png","k_1gixbsm":"[风车]@2x.png","k_1g6cqbq":"[尴尬]@2x.png","k_1g6jbw5":"[勾引]@2x.png","k_1g3lwo1":"[鼓掌]@2x.png","k_1g13nkj":"[害羞]@2x.png","k_1g0mt47":"[憨笑]@2x.png","k_0bxujkf":"[红灯笼]@2x.png","k_0hhaeh8":"[红双喜]@2x.png","k_1g0jnts":"[坏笑]@2x.png","k_1g46g9c":"[挥手]@2x.png","k_1g4vi9g":"[回头]@2x.png","k_1gf7hes":"[饥饿]@2x.png","k_1g6mvsm":"[激动]@2x.png","k_1gku5mf":"[街舞]@2x.png","k_1g4hidg":"[惊恐]@2x.png","k_1gjbrtu":"[惊讶]@2x.png","k_1g6sand":"[咖啡]@2x.png","k_1g4s8rj":"[磕头]@2x.png","k_1g1wn34":"[可爱]@2x.png","k_1g3l0wd":"[可怜]@2x.png","k_1ggaon9":"[抠鼻]@2x.png","k_1ggvcb0":"[骷髅]@2x.png","k_1h8yqjt":"[酷]@2x.png","k_0jac97i":"[快哭了]@2x.png","k_1h8oiby":"[困]@2x.png","k_1g0s5hg":"[蜡烛]@2x.png","k_1g1iuer":"[篮球]@2x.png","k_1g2xjfi":"[冷汗]@2x.png","k_0s5oyqw":"[礼品袋]@2x.png","k_1g1qqvf":"[礼物]@2x.png","k_1g2slew":"[流汗]@2x.png","k_1g3z9xx":"[流泪]@2x.png","k_1g6pabn":"[麻将]@2x.png","k_0pkaxul":"[麦克风]@2x.png","k_1g7m0zj":"[猫咪]@2x.png","k_0ibvtpo":"[么么哒]@2x.png","k_1g1hoh1":"[玫瑰]@2x.png","k_1gfzeow":"[米饭]@2x.png","k_1g5l15p":"[面条]@2x.png","k_1g2hfa6":"[奶瓶]@2x.png","k_1gix9pj":"[难过]@2x.png","k_1giqn6g":"[闹钟]@2x.png","k_1h8kd64":"[怒]@2x.png","k_1g0vui9":"[怄火]@2x.png","k_1g1jsj7":"[皮球]@2x.png","k_1ghdluw":"[啤酒]@2x.png","k_1gl6ec7":"[瓢虫]@2x.png","k_1g7gg5p":"[撇嘴]@2x.png","k_1g8psin":"[乒乓]@2x.png","k_1gjzu3p":"[汽车]@2x.png","k_1h8mr0k":"[强]@2x.png","k_1g45y2n":"[敲打]@2x.png","k_1gkaxsl":"[青蛙]@2x.png","k_0jcfnoo":"[糗大了]@2x.png","k_1g4njy1":"[拳头]@2x.png","k_1h8mqr3":"[弱]@2x.png","k_1h926fg":"[色]@2x.png","k_1g6rtbq":"[沙发]@2x.png","k_1giirh6":"[删除]@2x.png","k_1g14ny9":"[闪电]@2x.png","k_1g6bmsr":"[胜利]@2x.png","k_1g1rytx":"[示爱]@2x.png","k_1g52fbz":"[手枪]@2x.png","k_1h90dam":"[衰]@2x.png","k_1gigiae":"[睡觉]@2x.png","k_1gijchz":"[太阳]@2x.png","k_1g1sgji":"[跳绳]@2x.png","k_1gjwuri":"[跳跳]@2x.png","k_1g0juhk":"[偷笑]@2x.png","k_1h8nzla":"[吐]@2x.png","k_1g6cv0i":"[委屈]@2x.png","k_1g46l5g":"[握手]@2x.png","k_1g2pgkd":"[西瓜]@2x.png","k_1ging9p":"[下雨]@2x.png","k_1h8nzil":"[吓]@2x.png","k_1g7q7wr":"[献吻]@2x.png","k_1gl6uum":"[香蕉]@2x.png","k_1g23fys":"[象棋]@2x.png","k_0j75rdh":"[心碎了]@2x.png","k_1g6ajj2":"[信封]@2x.png","k_1g21prz":"[熊猫]@2x.png","k_1h8octi":"[嘘]@2x.png","k_1h91zox":"[药]@2x.png","k_1ghttfl":"[疑问]@2x.png","k_1ghk7sz":"[阴险]@2x.png","k_0gl37zz":"[右车头]@2x.png","k_0ifkj1p":"[右哼哼]@2x.png","k_0g1yh2e":"[右太极]@2x.png","k_1g9dkfc":"[雨伞]@2x.png","k_1g8jl88":"[月亮]@2x.png","k_1h8lhqj":"[晕]@2x.png","k_1gi9x2q":"[再见]@2x.png","k_1g6dwwv":"[炸弹]@2x.png","k_1fzmkfi":"[折磨]@2x.png","k_1g6jbiw":"[纸巾]@2x.png","k_1ggjnwu":"[咒骂]@2x.png","k_1g4qlq8":"[猪头]@2x.png","k_1g1lqzz":"[抓狂]@2x.png","k_1g80j3u":"[转圈]@2x.png","k_1g0z55s":"[龇牙]@2x.png","k_1g3ju6v":"[钻戒]@2x.png","k_0gl51l6":"[左车头]@2x.png","k_0iflllk":"[左哼哼]@2x.png","k_0g1y3ir":"[左太极]@2x.png","k_026hiq5":"消息列表加载中","k_003tu8k":"爱你","k_003myvp":"傲慢","k_003kddw":"白眼","k_039yfhv":"棒棒糖","k_003nu3p":"抱抱","k_003nijr":"抱拳","k_003mg88":"爆筋","k_002v17e":"鄙视","k_003qhy4":"闭嘴","k_003l5fq":"鞭炮","k_003uacl":"便便","k_003oq1g":"擦汗","k_003qvey":"彩带","k_003jci7":"彩球","k_003pyu1":"菜刀","k_003q97d":"差劲","k_003po5d":"车厢","k_03eadb2":"打哈欠","k_003pnuf":"大兵","k_003kg57":"蛋糕","k_003mxkt":"得意","k_003onu3":"灯泡","k_002uv8s":"凋谢","k_003kqy0":"调皮","k_003tyum":"多云","k_003pv9u":"发呆","k_036o6mu":"发抖t","k_003nogx":"飞机","k_003q7wg":"飞吻","k_003m0jd":"奋斗","k_002ult9":"风车","k_003r8gt":"尴尬","k_003qy4u":"勾引","k_003mnoa":"鼓掌","k_003lmw8":"害羞","k_003mb30":"憨笑","k_03bj41g":"红灯笼","k_03dxw2f":"红双喜","k_003mk57":"坏笑","k_003nmvf":"挥手","k_003r2i7":"回头","k_002s6f3":"饥饿","k_003qd0t":"激动","k_002vgi4":"街舞","k_003nz33":"惊恐","k_002wh4p":"惊讶","k_003ozpu":"咖啡","k_003qvs4":"磕头","k_003l3wb":"可爱","k_003nuwm":"可怜","k_002rw1q":"抠鼻","k_002tujb":"骷髅","k_00030eq":"酷","k_03i8ath":"快哭了","k_000421h":"困","k_003l5i7":"蜡烛","k_003j72g":"篮球","k_003ofwl":"冷汗","k_02mw65v":"礼品袋","k_003ku40":"礼物","k_003ookz":"流汗","k_003on72":"流泪","k_003rjy0":"麻将","k_003q2f8":"猫咪","k_03et393":"么么哒","k_003j7j2":"玫瑰","k_002sr0b":"米饭","k_003nnza":"面条","k_003jef9":"奶瓶","k_002umn0":"难过","k_002rjib":"闹钟","k_0003zcn":"怒","k_003jzwq":"怄火","k_003j4js":"皮球","k_002r5ir":"啤酒","k_002ubu4":"瓢虫","k_003ppo6":"撇嘴","k_003ty3o":"乒乓","k_002vxwe":"汽车","k_00043hb":"强","k_003nmbo":"敲打","k_002tfhq":"青蛙","k_03i7lrn":"糗大了","k_003r03m":"拳头","k_00043h0":"弱","k_000345z":"色","k_003qmp9":"沙发","k_003it8a":"闪电","k_003pxow":"胜利","k_003kw8e":"示爱","k_003n99g":"手枪","k_00035cl":"衰","k_002vl3h":"睡觉","k_002rgqk":"太阳","k_003m9d1":"跳绳","k_002vobp":"跳跳","k_003mkoz":"偷笑","k_00041px":"吐","k_003rjh5":"委屈","k_003j36u":"西瓜","k_002re92":"下雨","k_00041py":"吓","k_003q06o":"献吻","k_002ubjp":"香蕉","k_003o2tr":"象棋","k_03ie6pa":"心碎了","k_003rao5":"信封","k_003l3us":"熊猫","k_000424d":"嘘","k_00033yi":"药","k_002qtyy":"疑问","k_002qe0o":"阴险","k_03gu7us":"右车头","k_03ere8m":"右哼哼","k_003uqk3":"雨伞","k_003tzdv":"月亮","k_0003z00":"晕","k_002vdrd":"再见","k_003ra1w":"炸弹","k_003lcad":"折磨","k_003q7sz":"纸巾","k_002thn9":"咒骂","k_003qx7f":"猪头","k_003l044":"抓狂","k_003qg4h":"转圈","k_003kb97":"龇牙","k_03gu53l":"左车头","k_03erd1f":"左哼哼","k_003nyvl":"爱情","k_003r85z":"爱心","k_003mk8j":"钞票","k_003pwfj":"大哭","k_00042w5":"刀","k_003nmtr":"握手","k_03c529p":"右太极","k_003n4mk":"钻戒","k_03c5488":"左太极","k_1llp7tu":"该用户不存在","k_0tbyqyb":"加载中…","k_0td1p3f":"保存中…","k_1klqdh1":"仅限汉字、英文、数字和下划线","k_03el5lp":"未填写","k_1ui0gai":"搜索指定内容"} \ No newline at end of file diff --git a/lib/tencent_cloud_chat_uikit.dart b/lib/tencent_cloud_chat_uikit.dart index a6b7ccd..4c8ec65 100644 --- a/lib/tencent_cloud_chat_uikit.dart +++ b/lib/tencent_cloud_chat_uikit.dart @@ -8,6 +8,9 @@ export 'data_services/core/core_services_implements.dart'; export 'package:tencent_im_base/theme/tui_theme.dart'; export 'package:tencent_im_base/theme/color.dart'; +// Sticker +export 'package:tim_ui_kit_sticker_plugin/tim_ui_kit_sticker_plugin.dart'; + // Widgets export 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitConversation/tim_uikit_conversation.dart'; export 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/tim_uikit_chat.dart'; @@ -47,6 +50,9 @@ export 'package:tencent_cloud_chat_uikit/ui/controller/tim_uikit_profile_control export 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/tim_uikit_chat_config.dart'; export 'package:permission_handler/permission_handler.dart'; +// Utils +export 'package:tencent_cloud_chat_uikit/ui/utils/common_utils.dart'; + class TIMUIKitCore { static CoreServicesImpl getInstance() { setupServiceLocator(); diff --git a/lib/ui/constants/emoji.dart b/lib/ui/constants/emoji.dart deleted file mode 100644 index 7406cc4..0000000 --- a/lib/ui/constants/emoji.dart +++ /dev/null @@ -1,139 +0,0 @@ -List> emojiData = [ - {"name": "GRINNING FACE WITH SMILING EYES", "unicode": 128513}, - {"name": "FACE WITH TEARS OF JOY", "unicode": 128514}, - {"name": "SMILING FACE WITH OPEN MOUTH", "unicode": 128515}, - {"name": "SMILING FACE WITH OPEN MOUTH AND SMILING EYES", "unicode": 128516}, - {"name": "SMILING FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128517}, - { - "name": "SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES", - "unicode": 128518 - }, - {"name": "WINKING FACE", "unicode": 128521}, - {"name": "SMILING FACE WITH SMILING EYES", "unicode": 128522}, - {"name": "FACE SAVOURING DELICIOUS FOOD", "unicode": 128523}, - {"name": "RELIEVED FACE", "unicode": 128524}, - {"name": "SMILING FACE WITH HEART-SHAPED EYES", "unicode": 128525}, - {"name": "SMIRKING FACE", "unicode": 128527}, - {"name": "UNAMUSED FACE", "unicode": 128530}, - {"name": "FACE WITH COLD SWEAT", "unicode": 128531}, - {"name": "PENSIVE FACE", "unicode": 128532}, - {"name": "CONFOUNDED FACE", "unicode": 128534}, - {"name": "FACE THROWING A KISS", "unicode": 128536}, - {"name": "KISSING FACE WITH CLOSED EYES", "unicode": 128538}, - {"name": "FACE WITH STUCK-OUT TONGUE AND WINKING EYE", "unicode": 128540}, - { - "name": "FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES", - "unicode": 128541 - }, - {"name": "DISAPPOINTED FACE", "unicode": 128542}, - {"name": "ANGRY FACE", "unicode": 128544}, - {"name": "POUTING FACE", "unicode": 128545}, - {"name": "CRYING FACE", "unicode": 128546}, - {"name": "PERSEVERING FACE", "unicode": 128547}, - {"name": "FACE WITH LOOK OF TRIUMPH", "unicode": 128548}, - {"name": "DISAPPOINTED BUT RELIEVED FACE", "unicode": 128549}, - {"name": "FEARFUL FACE", "unicode": 128552}, - {"name": "WEARY FACE", "unicode": 128553}, - {"name": "SLEEPY FACE", "unicode": 128554}, - {"name": "TIRED FACE", "unicode": 128555}, - {"name": "LOUDLY CRYING FACE", "unicode": 128557}, - {"name": "FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128560}, - {"name": "FACE SCREAMING IN FEAR", "unicode": 128561}, - {"name": "ASTONISHED FACE", "unicode": 128562}, - {"name": "FLUSHED FACE", "unicode": 128563}, - {"name": "DIZZY FACE", "unicode": 128565}, - {"name": "FACE WITH MEDICAL MASK", "unicode": 128567}, - {"name": "GRINNING CAT FACE WITH SMILING EYES", "unicode": 128568}, - {"name": "CAT FACE WITH TEARS OF JOY", "unicode": 128569}, - {"name": "SMILING CAT FACE WITH OPEN MOUTH", "unicode": 128570}, - {"name": "SMILING CAT FACE WITH HEART-SHAPED EYES", "unicode": 128571}, - {"name": "CAT FACE WITH WRY SMILE", "unicode": 128572}, - {"name": "KISSING CAT FACE WITH CLOSED EYES", "unicode": 128573}, - {"name": "POUTING CAT FACE", "unicode": 128574}, - {"name": "CRYING CAT FACE", "unicode": 128575}, - {"name": "WEARY CAT FACE", "unicode": 128576}, - {"name": "FACE WITH NO GOOD GESTURE", "unicode": 128581}, - {"name": "FACE WITH OK GESTURE", "unicode": 128582}, - {"name": "PERSON BOWING DEEPLY", "unicode": 128583}, - {"name": "SEE-NO-EVIL MONKEY", "unicode": 128584}, - {"name": "HEAR-NO-EVIL MONKEY", "unicode": 128585}, - {"name": "SPEAK-NO-EVIL MONKEY", "unicode": 128586}, - {"name": "HAPPY PERSON RAISING ONE HAND", "unicode": 128587}, - {"name": "PERSON RAISING BOTH HANDS IN CELEBRATION", "unicode": 128588}, - {"name": "PERSON FROWNING", "unicode": 128589}, - {"name": "PERSON WITH POUTING FACE", "unicode": 128590}, - {"name": "PERSON WITH FOLDED HANDS", "unicode": 128591}, - {"name": "BLACK SCISSORS", "unicode": 9986}, - {"name": "WHITE HEAVY CHECK MARK", "unicode": 9989}, - {"name": "AIRPLANE", "unicode": 9992}, - {"name": "ENVELOPE", "unicode": 9993}, - {"name": "RAISED FIST", "unicode": 9994}, - {"name": "RAISED HAND", "unicode": 9995}, - {"name": "VICTORY HAND", "unicode": 9996}, - {"name": "PENCIL", "unicode": 9999}, - {"name": "BLACK NIB", "unicode": 10002}, - {"name": "HEAVY CHECK MARK", "unicode": 10004}, - {"name": "HEAVY MULTIPLICATION X", "unicode": 10006}, - {"name": "SPARKLES", "unicode": 10024}, - {"name": "EIGHT SPOKED ASTERISK", "unicode": 10035}, - {"name": "EIGHT POINTED BLACK STAR", "unicode": 10036}, - {"name": "SNOWFLAKE", "unicode": 10052}, - {"name": "SPARKLE", "unicode": 10055}, - {"name": "CROSS MARK", "unicode": 10060}, - {"name": "NEGATIVE SQUARED CROSS MARK", "unicode": 10062}, - {"name": "BLACK QUESTION MARK ORNAMENT", "unicode": 10067}, - {"name": "WHITE QUESTION MARK ORNAMENT", "unicode": 10068}, - {"name": "WHITE EXCLAMATION MARK ORNAMENT", "unicode": 10069}, - {"name": "HEAVY EXCLAMATION MARK SYMBOL", "unicode": 10071}, - {"name": "HEAVY BLACK HEART", "unicode": 10084}, - {"name": "HEAVY PLUS SIGN", "unicode": 10133}, - {"name": "HEAVY MINUS SIGN", "unicode": 10134}, - {"name": "HEAVY DIVISION SIGN", "unicode": 10135}, - {"name": "BLACK RIGHTWARDS ARROW", "unicode": 10145}, - {"name": "CURLY LOOP", "unicode": 10160}, - {"name": "ROCKET", "unicode": 128640}, - {"name": "RAILWAY CAR", "unicode": 128643}, - {"name": "HIGH-SPEED TRAIN", "unicode": 128644}, - {"name": "HIGH-SPEED TRAIN WITH BULLET NOSE", "unicode": 128645}, - {"name": "METRO", "unicode": 128647}, - {"name": "STATION", "unicode": 128649}, - {"name": "BUS", "unicode": 128652}, - {"name": "BUS STOP", "unicode": 128655}, - {"name": "AMBULANCE", "unicode": 128657}, - {"name": "FIRE ENGINE", "unicode": 128658}, - {"name": "POLICE CAR", "unicode": 128659}, - {"name": "TAXI", "unicode": 128661}, - {"name": "AUTOMOBILE", "unicode": 128663}, - {"name": "RECREATIONAL VEHICLE", "unicode": 128665}, - {"name": "DELIVERY TRUCK", "unicode": 128666}, - {"name": "SHIP", "unicode": 128674}, - {"name": "SPEEDBOAT", "unicode": 128676}, - {"name": "HORIZONTAL TRAFFIC LIGHT", "unicode": 128677}, - {"name": "CONSTRUCTION SIGN", "unicode": 128679}, - {"name": "POLICE CARS REVOLVING LIGHT", "unicode": 128680}, - {"name": "TRIANGULAR FLAG ON POST", "unicode": 128681}, - {"name": "DOOR", "unicode": 128682}, - {"name": "NO ENTRY SIGN", "unicode": 128683}, - {"name": "SMOKING SYMBOL", "unicode": 128684}, - {"name": "NO SMOKING SYMBOL", "unicode": 128685}, - {"name": "BICYCLE", "unicode": 128690}, - {"name": "PEDESTRIAN", "unicode": 128694}, - {"name": "MENS SYMBOL", "unicode": 128697}, - {"name": "WOMENS SYMBOL", "unicode": 128698}, - {"name": "RESTROOM", "unicode": 128699}, - {"name": "BABY SYMBOL", "unicode": 128700}, - {"name": "TOILET", "unicode": 128701}, - {"name": "WATER CLOSET", "unicode": 128702}, - {"name": "BATH", "unicode": 128704}, - {"name": "CIRCLED LATIN CAPITAL LETTER M", "unicode": 9410}, - {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER A", "unicode": 127344}, - {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER B", "unicode": 127345}, - {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER O", "unicode": 127358}, - {"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER P", "unicode": 127359}, - {"name": "NEGATIVE SQUARED AB", "unicode": 127374}, - {"name": "SQUARED CL", "unicode": 127377}, - {"name": "SQUARED COOL", "unicode": 127378}, - {"name": "SQUARED FREE", "unicode": 127379}, - {"name": "SQUARED ID", "unicode": 127380}, - {"name": "SQUARED NEW", "unicode": 127381}, -]; diff --git a/lib/ui/controller/tim_uikit_profile_controller.dart b/lib/ui/controller/tim_uikit_profile_controller.dart index 8c1ea90..9fbf53c 100644 --- a/lib/ui/controller/tim_uikit_profile_controller.dart +++ b/lib/ui/controller/tim_uikit_profile_controller.dart @@ -52,9 +52,10 @@ class TIMUIKitProfileController { String title, String tips, void Function(String) onSubmitted, + TUITheme theme ) { TextInputBottomSheet.showTextInputBottomSheet( - context, title, tips, onSubmitted); + context, title, tips, onSubmitted, theme); } /// Load the profile data diff --git a/lib/ui/utils/common_utils.dart b/lib/ui/utils/common_utils.dart new file mode 100644 index 0000000..734f01e --- /dev/null +++ b/lib/ui/utils/common_utils.dart @@ -0,0 +1,7 @@ +class TencentUtils{ + static bool isTextNotEmpty(String? text){ + return text != null && text.isNotEmpty; + } + + +} \ No newline at end of file diff --git a/lib/ui/utils/constant_data.dart b/lib/ui/utils/constant_data.dart deleted file mode 100644 index a0e6c20..0000000 --- a/lib/ui/utils/constant_data.dart +++ /dev/null @@ -1,153 +0,0 @@ -import 'custom_emoji_face_data_class.dart'; - -class ConstData { - static final List emojiList = [ - CustomEmojiFaceData( - name: '4349', - icon: "[调皮]@2x.png", - isEmoji: true, - list: [ - "[爱你]@2x.png", - "[爱情]@2x.png", - "[爱心]@2x.png", - "[傲慢]@2x.png", - "[白眼]@2x.png", - "[棒棒糖]@2x.png", - "[抱抱]@2x.png", - "[抱拳]@2x.png", - "[爆筋]@2x.png", - "[鄙视]@2x.png", - "[闭嘴]@2x.png", - "[鞭炮]@2x.png", - "[便便]@2x.png", - "[擦汗]@2x.png", - "[彩带]@2x.png", - "[彩球]@2x.png", - "[菜刀]@2x.png", - "[差劲]@2x.png", - "[钞票]@2x.png", - "[车厢]@2x.png", - "[打哈欠]@2x.png", - "[大兵]@2x.png", - "[大哭]@2x.png", - "[蛋糕]@2x.png", - "[刀]@2x.png", - "[得意]@2x.png", - "[灯泡]@2x.png", - "[凋谢]@2x.png", - "[调皮]@2x.png", - "[多云]@2x.png", - "[发呆]@2x.png", - "[发抖]@2x.png", - "[飞机]@2x.png", - "[飞吻]@2x.png", - "[奋斗]@2x.png", - "[风车]@2x.png", - "[尴尬]@2x.png", - "[勾引]@2x.png", - "[鼓掌]@2x.png", - "[害羞]@2x.png", - "[憨笑]@2x.png", - "[红灯笼]@2x.png", - "[红双喜]@2x.png", - "[坏笑]@2x.png", - "[挥手]@2x.png", - "[回头]@2x.png", - "[饥饿]@2x.png", - "[激动]@2x.png", - "[街舞]@2x.png", - "[惊恐]@2x.png", - "[惊讶]@2x.png", - "[咖啡]@2x.png", - "[磕头]@2x.png", - "[可爱]@2x.png", - "[可怜]@2x.png", - "[抠鼻]@2x.png", - "[骷髅]@2x.png", - "[酷]@2x.png", - "[快哭了]@2x.png", - "[困]@2x.png", - "[蜡烛]@2x.png", - "[篮球]@2x.png", - "[冷汗]@2x.png", - "[礼品袋]@2x.png", - "[礼物]@2x.png", - "[流汗]@2x.png", - "[流泪]@2x.png", - "[麻将]@2x.png", - "[麦克风]@2x.png", - "[猫咪]@2x.png", - "[么么哒]@2x.png", - "[玫瑰]@2x.png", - "[米饭]@2x.png", - "[面条]@2x.png", - "[奶瓶]@2x.png", - "[难过]@2x.png", - "[闹钟]@2x.png", - "[怒]@2x.png", - "[怄火]@2x.png", - "[皮球]@2x.png", - "[啤酒]@2x.png", - "[瓢虫]@2x.png", - "[撇嘴]@2x.png", - "[乒乓]@2x.png", - "[汽车]@2x.png", - "[强]@2x.png", - "[敲打]@2x.png", - "[青蛙]@2x.png", - "[糗大了]@2x.png", - "[拳头]@2x.png", - "[弱]@2x.png", - "[色]@2x.png", - "[沙发]@2x.png", - "[删除]@2x.png", - "[闪电]@2x.png", - "[胜利]@2x.png", - "[示爱]@2x.png", - "[手枪]@2x.png", - "[衰]@2x.png", - "[睡觉]@2x.png", - "[太阳]@2x.png", - "[跳绳]@2x.png", - "[跳跳]@2x.png", - "[偷笑]@2x.png", - "[吐]@2x.png", - "[委屈]@2x.png", - "[握手]@2x.png", - "[西瓜]@2x.png", - "[下雨]@2x.png", - "[吓]@2x.png", - "[献吻]@2x.png", - "[香蕉]@2x.png", - "[象棋]@2x.png", - "[心碎了]@2x.png", - "[信封]@2x.png", - "[熊猫]@2x.png", - "[嘘]@2x.png", - "[药]@2x.png", - "[疑问]@2x.png", - "[阴险]@2x.png", - "[右车头]@2x.png", - "[右哼哼]@2x.png", - "[右太极]@2x.png", - "[雨伞]@2x.png", - "[月亮]@2x.png", - "[晕]@2x.png", - "[再见]@2x.png", - "[炸弹]@2x.png", - "[折磨]@2x.png", - "[纸巾]@2x.png", - "[咒骂]@2x.png", - "[猪头]@2x.png", - "[抓狂]@2x.png", - "[转圈]@2x.png", - "[龇牙]@2x.png", - "[钻戒]@2x.png", - "[左车头]@2x.png", - "[左哼哼]@2x.png", - "[左太极]@2x.png", - "[NO]@2x.png", - "[OK]@2x.png", - ]) - ]; -} diff --git a/lib/ui/utils/custom_emoji_face_data_class.dart b/lib/ui/utils/custom_emoji_face_data_class.dart deleted file mode 100644 index ccf53a7..0000000 --- a/lib/ui/utils/custom_emoji_face_data_class.dart +++ /dev/null @@ -1,19 +0,0 @@ -class CustomEmojiFaceData { - CustomEmojiFaceData( - {required this.name, - required this.icon, - required this.list, - this.isEmoji = false}); - - late String name; - late String icon; - late List list; - late bool isEmoji; - - CustomEmojiFaceData.fromJson(Map json) { - name = json['name']; - icon = json['icon']; - list = json['list']; - isEmoji = json['isEmoji'] ?? false; - } -} diff --git a/lib/ui/utils/message.dart b/lib/ui/utils/message.dart index d5f89bd..a5b509b 100644 --- a/lib/ui/utils/message.dart +++ b/lib/ui/utils/message.dart @@ -212,72 +212,7 @@ class MessageUtils { } static String handleCustomMessageString(V2TimMessage message) { - final customElem = message.customElem; - final callingMessage = CallingMessage.getCallMessage(customElem); - if (callingMessage != null) { - // 如果是结束消息 - final isCallEnd = CallingMessage.isCallEndExist(callingMessage); - String? option2 = ""; - if (isCallEnd) { - option2 = CallingMessage.getShowTime(callingMessage.callEnd!); - } - return isCallEnd - ? (TIM_t_para("通话时间:{{option2}}", "通话时间:$option2")(option2: option2)) - : (CallingMessage.getActionType(callingMessage.actionType!)); - } else { - return TIM_t("自定义消息"); - } - } - - static handleCustomMessage(V2TimMessage message, context) { - // 这个函数应该返回String,目前已经切走用不上了,但是不敢删QAQ,就这么留着吧。 - final customElem = message.customElem; - final callingMessage = CallingMessage.getCallMessage(customElem); - if (callingMessage != null) { - // 如果是结束消息 - final isCallEnd = CallingMessage.isCallEndExist(callingMessage); - - final isVoiceCall = callingMessage.callType == 1; - - String? option2 = ""; - if (isCallEnd) { - option2 = CallingMessage.getShowTime(callingMessage.callEnd!); - } - - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.only(right: 4), - child: Image.asset( - isVoiceCall ? "images/voice_call.png" : "images/video_call.png", - package: 'tencent_cloud_chat_uikit', - height: 16, - width: 16, - ), - ), - isCallEnd - ? Text(TIM_t_para("通话时间:{{option2}}", "通话时间:$option2")( - option2: option2)) - : Text( - CallingMessage.getActionType(callingMessage.actionType!)), - // if (isFromSelf) - // Padding( - // padding: const EdgeInsets.only(left: 4), - // child: Image.asset( - // isVoiceCall - // ? "images/voice_call.png" - // : "images/video_call_self.png", - // package: 'tencent_cloud_chat_uikit', - // height: 16, - // width: 16, - // ), - // ), - ], - ); - } else { - return const Text("[自定义]"); - } + return TIM_t("消息"); } static Widget wrapMessageTips(Widget child, TUITheme? theme) { diff --git a/lib/ui/utils/permission.dart b/lib/ui/utils/permission.dart index 68770f3..2c70b92 100644 --- a/lib/ui/utils/permission.dart +++ b/lib/ui/utils/permission.dart @@ -12,7 +12,6 @@ import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart'; import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart'; - class PermissionRequestInfo extends StatefulWidget { final Function removeOverLay; final int permissionType; @@ -54,6 +53,8 @@ class _PermissionRequestInfo extends TIMUIKitState @override Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { + final theme = value.theme; + final permission = { 1: { "name": TIM_t("相机"), @@ -79,7 +80,7 @@ class _PermissionRequestInfo extends TIMUIKitState child: Opacity( opacity: 0.7, child: Container( - color: Colors.black, + color: theme.black, padding: const EdgeInsets.symmetric(horizontal: 40), child: Column( crossAxisAlignment: CrossAxisAlignment.center, @@ -103,15 +104,14 @@ class _PermissionRequestInfo extends TIMUIKitState TIM_t_para(" 申请获取{{option2}}", " 申请获取$option2")( option2: option2) + TIM_t("权限"), - style: const TextStyle(color: Colors.white, fontSize: 18), + style: TextStyle(color: theme.white, fontSize: 18), ), const SizedBox( height: 20, ), Text( permission?["text"] ?? "", - style: - const TextStyle(color: Colors.white70, fontSize: 16), + style: TextStyle(color: theme.white, fontSize: 16), ) ], ), @@ -204,14 +204,22 @@ class Permissions { return _prefix + appName + _postfixList[value]; } - static Future checkPermission(BuildContext context, int value, - [bool isShowPermissionPage = true]) async { + static Future checkPermission( + BuildContext context, + int value, [ + TUITheme? theme, + bool isShowPermissionPage = true, + ]) async { final status = await Permission.byValue(value).status; if (status.isGranted || status.isLimited) { return true; } - final bool? shouldRequestPermission = - await showPermissionConfirmDialog(context, value, isShowPermissionPage); + final bool? shouldRequestPermission = await showPermissionConfirmDialog( + context, + value, + theme, + isShowPermissionPage, + ); if (shouldRequestPermission != null && shouldRequestPermission) { return await Permission.byValue(value).request().isGranted; } @@ -247,12 +255,8 @@ class Permissions { } static Future showPermissionConfirmDialog(BuildContext context, value, - [bool isShowPermissionPage = true]) async { - final platformUtils = PlatformUtils(); - // 第一次直接走系统文案 - if (!await checkPermissionSetBefore(value)) { + [TUITheme? theme, bool isShowPermissionPage = true]) async { await setLocalPermission(value); - if (platformUtils.isAndroid && isShowPermissionPage) { showPermissionRequestInfoDialog(context, value); } return true; @@ -303,7 +307,9 @@ class Permissions { Expanded( child: TextButton( child: Text(TIM_t("以后再说"), - style: const TextStyle(color: Colors.black)), + style: TextStyle( + color: theme?.black ?? Colors.black, + )), onPressed: closeDialog, // 关闭对话框 ), ), @@ -311,7 +317,9 @@ class Permissions { Expanded( child: TextButton( child: Text(TIM_t("去开启"), - style: const TextStyle(color: Colors.black)), + style: TextStyle( + color: theme?.black ?? Colors.black, + )), onPressed: getPermission, ), ) diff --git a/lib/ui/views/TIMUIKitAddFriend/tim_uikit_add_friend.dart b/lib/ui/views/TIMUIKitAddFriend/tim_uikit_add_friend.dart index 2264ddb..3ba37fc 100644 --- a/lib/ui/views/TIMUIKitAddFriend/tim_uikit_add_friend.dart +++ b/lib/ui/views/TIMUIKitAddFriend/tim_uikit_add_friend.dart @@ -84,8 +84,7 @@ class _TIMUIKitAddFriendState extends TIMUIKitState { model: _selfInfoViewModel))); }, child: Container( - color: Colors.white, - padding: const EdgeInsets.all(12), + padding: const EdgeInsets.symmetric(vertical: 12), child: Row( // crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -122,8 +121,12 @@ class _TIMUIKitAddFriendState extends TIMUIKitState { final noResult = searchResult == null || searchResult.isEmpty; if (noResult) { return [ - Center( - child: Text(TIM_t("用户不存在")), + Container( + margin: const EdgeInsets.only(top: 20), + child: Center( + child: Text(TIM_t("该用户不存在"), + style: TextStyle(color: theme.weakTextColor, fontSize: 14)), + ), ) ]; } @@ -161,23 +164,20 @@ class _TIMUIKitAddFriendState extends TIMUIKitState { @override Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { final TUITheme theme = value.theme; - return MultiProvider( providers: [ ChangeNotifierProvider.value(value: _selfInfoViewModel), ], builder: (BuildContext context, Widget? w) { - final selfInfoModel = Provider.of(context); - final userID = selfInfoModel.loginInfo?.userID ?? ""; - String option2 = userID; return Column( children: [ Padding( - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), child: Row( children: [ Expanded( child: TextField( + autofocus: true, focusNode: _focusNode, controller: _controller, onChanged: (value) { @@ -210,45 +210,24 @@ class _TIMUIKitAddFriendState extends TIMUIKitState { ), ), contentPadding: EdgeInsets.zero, - hintStyle: const TextStyle( - color: Color(0xffAEA4A3), + hintStyle: TextStyle( + color: theme.weakTextColor, ), - fillColor: Colors.white, + fillColor: theme.inputFillColor, filled: true, hintText: TIM_t("搜索用户 ID")), )), - AnimatedContainer( - duration: const Duration(milliseconds: 200), - width: isFocused ? 50 : 0, - child: TextButton( - onPressed: () { - final searchParams = _controller.text; - if (searchParams.trim().isNotEmpty) { - searchFriend(searchParams); - showResult = true; - setState(() {}); - } - }, - child: Text( - TIM_t("搜索"), - softWrap: false, - style: const TextStyle(color: Colors.black), - )), - ) ], ), ), - if (!isFocused) - Center( - child: Text( - TIM_t_para("我的用户ID: {{option2}}", "我的用户ID: $option2")( - option2: option2)), - ), if (showResult) Expanded( - child: SingleChildScrollView( - child: Column( - children: _searchResultBuilder(searchResult, theme), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: SingleChildScrollView( + child: Column( + children: _searchResultBuilder(searchResult, theme), + ), ), ), ) diff --git a/lib/ui/views/TIMUIKitAddFriend/tim_uikit_send_application.dart b/lib/ui/views/TIMUIKitAddFriend/tim_uikit_send_application.dart index cc1e61c..883dbc7 100644 --- a/lib/ui/views/TIMUIKitAddFriend/tim_uikit_send_application.dart +++ b/lib/ui/views/TIMUIKitAddFriend/tim_uikit_send_application.dart @@ -6,7 +6,6 @@ import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_inf import 'package:tencent_cloud_chat_uikit/data_services/friendShip/friendship_services.dart'; import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart'; - import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; @@ -58,9 +57,9 @@ class _SendApplicationState extends TIMUIKitState { appBar: AppBar( title: Text( TIM_t("添加好友"), - style: const TextStyle(color: Colors.white, fontSize: 17), + style: TextStyle(color: theme.white, fontSize: 17), ), - shadowColor: Colors.white, + shadowColor: theme.white, flexibleSpace: Container( decoration: BoxDecoration( gradient: LinearGradient(colors: [ @@ -69,8 +68,8 @@ class _SendApplicationState extends TIMUIKitState { ]), ), ), - iconTheme: const IconThemeData( - color: Colors.white, + iconTheme: IconThemeData( + color: theme.white, ), ), body: SingleChildScrollView( @@ -78,7 +77,7 @@ class _SendApplicationState extends TIMUIKitState { crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - color: Colors.white, + color: theme.white, padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), margin: const EdgeInsets.only(bottom: 12), child: Row( @@ -130,18 +129,18 @@ class _SendApplicationState extends TIMUIKitState { Container( margin: const EdgeInsets.only(top: 6, bottom: 12), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - color: Colors.white, + color: theme.white, child: TextField( - // minLines: 1, - maxLines: 4, - controller: _verficationController, - keyboardType: TextInputType.multiline, - decoration: const InputDecoration( - border: InputBorder.none, - hintStyle: TextStyle( - color: Color(0xFFAEA4A3), - ), - hintText: '')), + // minLines: 1, + maxLines: 4, + controller: _verficationController, + keyboardType: TextInputType.multiline, + decoration: InputDecoration( + border: InputBorder.none, + hintStyle: TextStyle(color: theme.textgrey), + hintText: '', + ), + ), ), Padding( padding: const EdgeInsets.only(left: 16.0), @@ -151,7 +150,7 @@ class _SendApplicationState extends TIMUIKitState { ), ), Container( - color: Colors.white, + color: theme.white, padding: const EdgeInsets.symmetric(horizontal: 16), margin: const EdgeInsets.only(top: 6), child: Row( @@ -164,14 +163,16 @@ class _SendApplicationState extends TIMUIKitState { SizedBox( width: 50, child: TextField( - controller: _nickNameController, - decoration: const InputDecoration( - contentPadding: EdgeInsets.zero, - border: InputBorder.none, - hintStyle: TextStyle( - color: Color(0xFFAEA4A3), - ), - hintText: '')), + controller: _nickNameController, + decoration: InputDecoration( + contentPadding: EdgeInsets.zero, + border: InputBorder.none, + hintStyle: TextStyle( + color: theme.textgrey, + ), + hintText: '', + ), + ), ) ], ), @@ -181,7 +182,7 @@ class _SendApplicationState extends TIMUIKitState { ), if (widget.isShowDefaultGroup == true) Container( - color: Colors.white, + color: theme.white, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( @@ -201,7 +202,7 @@ class _SendApplicationState extends TIMUIKitState { ), ), Container( - color: Colors.white, + color: theme.white, width: double.infinity, margin: const EdgeInsets.only(top: 10), child: TextButton( diff --git a/lib/ui/views/TIMUIKitAddGroup/tim_uikit_add_group.dart b/lib/ui/views/TIMUIKitAddGroup/tim_uikit_add_group.dart index a575db6..4a96136 100644 --- a/lib/ui/views/TIMUIKitAddGroup/tim_uikit_add_group.dart +++ b/lib/ui/views/TIMUIKitAddGroup/tim_uikit_add_group.dart @@ -88,8 +88,7 @@ class _TIMUIKitAddGroupState extends TIMUIKitState { ))); }, child: Container( - color: Colors.white, - padding: const EdgeInsets.all(12), + padding: const EdgeInsets.symmetric(vertical: 12), child: Row( // crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -106,9 +105,6 @@ class _TIMUIKitAddGroupState extends TIMUIKitState { showName, style: const TextStyle(fontSize: 18), ), - // const SizedBox( - // height: 4, - // ), Text( "ID: $groupID", style: TextStyle(fontSize: 12, color: theme.weakTextColor), @@ -130,8 +126,12 @@ class _TIMUIKitAddGroupState extends TIMUIKitState { final noResult = searchResult != null && searchResult.isEmpty; if (noResult) { return [ - Center( - child: Text(TIM_t("该群聊不存在")), + Container( + margin: const EdgeInsets.only(top: 20), + child: Center( + child: Text(TIM_t("该群聊不存在"), + style: TextStyle(color: theme.weakTextColor, fontSize: 14)), + ), ) ]; } @@ -221,11 +221,12 @@ class _TIMUIKitAddGroupState extends TIMUIKitState { return Column( children: [ Padding( - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), child: Row( children: [ Expanded( child: TextField( + autofocus: true, focusNode: _focusNode, controller: _controller, onChanged: (value) { @@ -258,39 +259,24 @@ class _TIMUIKitAddGroupState extends TIMUIKitState { ), ), contentPadding: EdgeInsets.zero, - hintStyle: const TextStyle( - color: Color(0xffAEA4A3), + hintStyle: TextStyle( + color: theme.weakTextColor, ), - fillColor: Colors.white, + fillColor: theme.inputFillColor, filled: true, hintText: TIM_t("搜索群ID")), )), - AnimatedContainer( - duration: const Duration(milliseconds: 200), - width: isFocused ? 50 : 0, - child: TextButton( - onPressed: () { - final searchParams = _controller.text; - if (searchParams.trim().isNotEmpty) { - searchGroup(searchParams); - showResult = true; - setState(() {}); - } - }, - child: Text( - TIM_t("搜索"), - softWrap: false, - style: const TextStyle(color: Colors.black), - )), - ) ], ), ), if (showResult) Expanded( - child: SingleChildScrollView( - child: Column( - children: _searchResultBuilder(groupResult, theme), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: SingleChildScrollView( + child: Column( + children: _searchResultBuilder(groupResult, theme), + ), ), ), ) diff --git a/lib/ui/views/TIMUIKitAddGroup/tim_uikit_send_application.dart b/lib/ui/views/TIMUIKitAddGroup/tim_uikit_send_application.dart index 49fbba9..178c192 100644 --- a/lib/ui/views/TIMUIKitAddGroup/tim_uikit_send_application.dart +++ b/lib/ui/views/TIMUIKitAddGroup/tim_uikit_send_application.dart @@ -6,7 +6,6 @@ import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implem import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart'; import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart'; - import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; @@ -79,9 +78,9 @@ class _SendJoinGroupApplicationState appBar: AppBar( title: Text( TIM_t("进群申请"), - style: const TextStyle(color: Colors.white, fontSize: 17), + style: TextStyle(color: theme.white, fontSize: 17), ), - shadowColor: Colors.white, + shadowColor: theme.white, flexibleSpace: Container( decoration: BoxDecoration( gradient: LinearGradient(colors: [ @@ -90,8 +89,8 @@ class _SendJoinGroupApplicationState ]), ), ), - iconTheme: const IconThemeData( - color: Colors.white, + iconTheme: IconThemeData( + color: theme.white, ), ), body: SingleChildScrollView( @@ -99,7 +98,7 @@ class _SendJoinGroupApplicationState crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - color: Colors.white, + color: theme.white, padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), margin: const EdgeInsets.only(bottom: 12), child: Row( @@ -151,20 +150,20 @@ class _SendJoinGroupApplicationState Container( margin: const EdgeInsets.only(top: 6, bottom: 12), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - color: Colors.white, + color: theme.white, child: TextField( maxLines: 4, controller: _verficationController, keyboardType: TextInputType.multiline, - decoration: const InputDecoration( + decoration: InputDecoration( border: InputBorder.none, hintStyle: TextStyle( - color: Color(0xFFAEA4A3), + color: theme.textgrey, ), hintText: '')), ), Container( - color: Colors.white, + color: theme.white, width: double.infinity, margin: const EdgeInsets.only(top: 10), child: TextButton( diff --git a/lib/ui/views/TIMUIKitBlackList/tim_uikit_black_list.dart b/lib/ui/views/TIMUIKitBlackList/tim_uikit_black_list.dart index 9bc10fe..bb97ccd 100644 --- a/lib/ui/views/TIMUIKitBlackList/tim_uikit_black_list.dart +++ b/lib/ui/views/TIMUIKitBlackList/tim_uikit_black_list.dart @@ -58,7 +58,7 @@ class _TIMUIKitBlackListState extends TIMUIKitState { .deleteFromBlockList([friendInfo.userID]); }, backgroundColor: theme.cautionColor ?? CommonColor.cautionColor, - foregroundColor: Colors.white, + foregroundColor: theme.white, label: TIM_t("删除"), autoClose: true, ) @@ -93,7 +93,7 @@ class _TIMUIKitBlackListState extends TIMUIKitState { CommonColor.weakDividerColor))), child: Text( showName, - style: const TextStyle(color: Colors.black, fontSize: 18), + style: TextStyle(color: theme.black, fontSize: 18), ), )) ], diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list.dart b/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list.dart index 39ded93..bcfeb9f 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list.dart @@ -1,3 +1,4 @@ + import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list_item.dart b/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list_item.dart index c31dfe8..d3759a3 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list_item.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list_item.dart @@ -581,7 +581,10 @@ class _TIMUIKItHistoryMessageListItemState ? (model.chatConfig.timeDividerConfig?.timestampParser!(timeStamp))! : TimeAgo().getTimeForMessage(timeStamp), style: widget.themeData?.timelineTextStyle ?? - TextStyle(fontSize: 12, color: theme.weakTextColor), + TextStyle( + fontSize: 12, + color: theme.chatTimeDividerTextColor, + ), ), ); } @@ -589,8 +592,13 @@ class _TIMUIKItHistoryMessageListItemState bool isRevokable(int timestamp) => (DateTime.now().millisecondsSinceEpoch / 1000).ceil() - timestamp < 120; - _onLongPress(c, V2TimMessage message, TUIChatSeparateViewModel model, - TapDownDetails? details) { + _onLongPress( + c, + V2TimMessage message, + TUIChatSeparateViewModel model, + TUITheme theme, + TapDownDetails? details, + ) { if (tooltip != null && tooltip!.isOpen) { tooltip!.close(); return; @@ -600,7 +608,12 @@ class _TIMUIKItHistoryMessageListItemState final screenHeight = MediaQuery.of(context).size.height; if (context.size!.height + 180 > screenHeight && !PlatformUtils().isWeb) { initTools( - context: c, isLongMessage: true, model: model, details: details); + context: c, + isLongMessage: true, + model: model, + details: details, + theme: theme, + ); if (widget.onScrollToIndexBegin != null) { widget.onScrollToIndexBegin!(message); } @@ -608,7 +621,12 @@ class _TIMUIKItHistoryMessageListItemState tooltip!.show(c); }); } else { - initTools(context: c, model: model, details: details); + initTools( + context: c, + model: model, + details: details, + theme: theme, + ); tooltip!.show(c, targetCenter: details?.globalPosition); } } @@ -633,6 +651,7 @@ class _TIMUIKItHistoryMessageListItemState {BuildContext? context, bool isLongMessage = false, required TUIChatSeparateViewModel model, + TUITheme? theme, TapDownDetails? details}) { final isSelf = widget.message.isSelf ?? false; double arrowTipDistance = 30; @@ -688,8 +707,8 @@ class _TIMUIKItHistoryMessageListItemState right: right, left: left, hasArrow: hasArrow, - borderColor: Colors.white, - backgroundColor: Colors.white, + borderColor: theme?.white ?? Colors.white, + backgroundColor: theme?.white ?? Colors.white, shadowColor: Colors.black26, hasShadow: true, borderWidth: 1.0, @@ -967,7 +986,8 @@ class _TIMUIKItHistoryMessageListItemState child: Text( isPeerRead ? TIM_t("已读") : TIM_t("未读"), style: TextStyle( - color: theme.weakTextColor, + color: theme + .chatMessageItemUnreadStatusTextColor, fontSize: 12), ), ), @@ -1024,7 +1044,12 @@ class _TIMUIKItHistoryMessageListItemState if (PlatformUtils().isWeb) { if (widget.allowLongPress) { _onLongPress( - context, message, model, details); + context, + message, + model, + theme, + details, + ); } if (widget.onLongPress != null) { widget.onLongPress!(context, message); @@ -1034,7 +1059,12 @@ class _TIMUIKItHistoryMessageListItemState onLongPress: () { if (widget.allowLongPress) { _onLongPress( - context, message, model, null); + context, + message, + model, + theme, + null, + ); } if (widget.onLongPress != null) { widget.onLongPress!(context, message); diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_message_tooltip.dart b/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_message_tooltip.dart index 2d9d5a6..6df2446 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_message_tooltip.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_message_tooltip.dart @@ -5,6 +5,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; +import 'package:tencent_cloud_chat_uikit/ui/utils/message.dart'; import 'package:tencent_im_base/tencent_im_base.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart'; @@ -93,6 +94,10 @@ class TIMUIKitMessageTooltipState final shouldShowRevokeAction = isCanRevoke && (widget.message.isSelf ?? false) && widget.message.status != MessageStatus.V2TIM_MSG_STATUS_SEND_FAIL; + final shouldShowReplyAction = !(widget.message.customElem?.data != null && + MessageUtils.isCallingData(widget.message.customElem!.data!)); + final shouldShowForwardAction = !(widget.message.customElem?.data != null && + MessageUtils.isCallingData(widget.message.customElem!.data!)); final tooltipsConfig = widget.toolTipsConfig; final defaultTipsList = [ { @@ -100,6 +105,7 @@ class TIMUIKitMessageTooltipState "id": "copyMessage", "icon": "images/copy_message.png" }, + if(shouldShowForwardAction) { "label": TIM_t("转发"), "id": "forwardMessage", @@ -110,6 +116,7 @@ class TIMUIKitMessageTooltipState "id": "multiSelect", "icon": "images/multi_message.png" }, + if (shouldShowReplyAction) { "label": TIM_t("引用"), "id": "replyMessage", diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitAppBar/tim_uikit_appbar.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitAppBar/tim_uikit_appbar.dart index a62e19c..6690568 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitAppBar/tim_uikit_appbar.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitAppBar/tim_uikit_appbar.dart @@ -173,7 +173,7 @@ class _TIMUIKitAppBarState extends TIMUIKitState { final TUIChatSeparateViewModel chatVM = Provider.of(context); return AppBar( - backgroundColor: setAppbar?.backgroundColor, + backgroundColor: setAppbar?.backgroundColor ?? theme.chatHeaderBgColor, actionsIconTheme: setAppbar?.actionsIconTheme, foregroundColor: setAppbar?.foregroundColor, elevation: setAppbar?.elevation, @@ -189,15 +189,18 @@ class _TIMUIKitAppBarState extends TIMUIKitState { toolbarTextStyle: setAppbar?.toolbarTextStyle, textTheme: setAppbar?.textTheme, flexibleSpace: setAppbar?.backgroundColor == null - ? setAppbar?.flexibleSpace ?? - Container( - decoration: BoxDecoration( - gradient: LinearGradient(colors: [ - theme.lightPrimaryColor ?? CommonColor.lightPrimaryColor, - theme.primaryColor ?? CommonColor.primaryColor - ]), - ), - ) + ? theme.chatHeaderBgColor != null + ? setAppbar?.flexibleSpace ?? + Container( + decoration: BoxDecoration( + gradient: LinearGradient(colors: [ + theme.lightPrimaryColor ?? + CommonColor.lightPrimaryColor, + theme.primaryColor ?? CommonColor.primaryColor + ]), + ), + ) + : null : null, iconTheme: setAppbar?.iconTheme ?? const IconThemeData( diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_detail.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_detail.dart index 43fba23..4b73b59 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_detail.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_detail.dart @@ -5,7 +5,6 @@ import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart'; import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart'; - import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart'; class TIMUIKitMessageReactionDetail extends StatefulWidget { @@ -99,7 +98,7 @@ class TIMUIKitMessageReactionDetailState padding: const EdgeInsets.only(top: 20, bottom: 20, right: 28), child: Text( showName, - style: const TextStyle(color: Colors.black, fontSize: 18), + style: TextStyle(color: theme.black, fontSize: 18), ), )), ], diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_select_emoji.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_select_emoji.dart index 0a3706e..9adbd8b 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_select_emoji.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_select_emoji.dart @@ -3,7 +3,8 @@ import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart'; import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart'; import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/message_reaction_emoji.dart'; -import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_emoji_panel.dart'; +import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_emoji_panel.dart' + as emoji; import 'package:tencent_cloud_chat_uikit/ui/widgets/emoji.dart'; import 'package:tencent_cloud_chat_uikit/ui/widgets/extended_wrap/extended_wrap.dart'; @@ -64,7 +65,7 @@ class TIMUIKitMessageReactionEmojiSelectPanelState onTap: () { widget.onSelect(item.unicode); }, - child: EmojiItem( + child: emoji.EmojiItem( name: item.name, unicode: item.unicode, ), diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_file_elem.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_file_elem.dart index ce90e9f..aafa006 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_file_elem.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_file_elem.dart @@ -16,7 +16,6 @@ import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart'; import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart'; - import 'package:tencent_cloud_chat_uikit/ui/utils/permission.dart'; import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart'; @@ -167,15 +166,17 @@ class _TIMUIKitFileElemState extends TIMUIKitState { return res; } - downloadFile() async { - if (!await Permissions.checkPermission(context, Permission.storage.value)) { + downloadFile(TUITheme theme) async { + if (!await Permissions.checkPermission( + context, Permission.storage.value, theme)) { return; } await model.downloadFile(); } tryOpenFile(context, theme) async { - if (!await Permissions.checkPermission(context, Permission.storage.value)) { + if (!await Permissions.checkPermission( + context, Permission.storage.value, theme)) { return; } showOpenFileConfirmDialog(context, filePath, theme); @@ -252,7 +253,7 @@ class _TIMUIKitFileElemState extends TIMUIKitState { } else { await addUrlToWaitingPath(); } - await downloadFile(); + await downloadFile(theme); }, child: Container( width: 237, diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_image_elem.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_image_elem.dart index 13db4c7..990f298 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_image_elem.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_image_elem.dart @@ -2,8 +2,8 @@ import 'dart:async'; import 'dart:convert'; -import 'package:http/http.dart' as http; import 'package:crypto/crypto.dart'; +import 'package:http/http.dart' as http; import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart'; import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart'; import 'package:universal_html/html.dart' as html; @@ -11,7 +11,6 @@ import 'dart:io'; import 'dart:math'; import 'dart:typed_data'; import 'package:cached_network_image/cached_network_image.dart'; -import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -35,8 +34,6 @@ import 'package:tencent_cloud_chat_uikit/ui/widgets/toast.dart'; import 'package:transparent_image/transparent_image.dart'; import 'package:image_gallery_saver/image_gallery_saver.dart'; - - class TIMUIKitImageElem extends StatefulWidget { final V2TimMessage message; final bool isShowJump; @@ -85,7 +82,7 @@ class _TIMUIKitImageElem extends TIMUIKitState { borderRadius: const BorderRadius.all(Radius.circular(5)), border: Border.all( width: 1, - color: Colors.black12, + color: theme?.black ?? Colors.white, )), height: 100, child: Center( @@ -112,7 +109,12 @@ class _TIMUIKitImageElem extends TIMUIKitState { } //保存网络图片到本地 - _saveImageToLocal(context, String imageUrl, {bool isAsset = true}) async { + Future _saveImageToLocal( + context, + String imageUrl, { + bool isAsset = true, + TUITheme? theme, + }) async { if (PlatformUtils().isWeb) { download(imageUrl) async { final http.Response r = await http.get(Uri.parse(imageUrl)); @@ -131,12 +133,12 @@ class _TIMUIKitImageElem extends TIMUIKitState { if (PlatformUtils().isIOS) { if (!await Permissions.checkPermission( - context, Permission.photosAddOnly.value, false)) { + context, Permission.photosAddOnly.value, theme!, false)) { return; } } else { if (!await Permissions.checkPermission( - context, Permission.storage.value)) { + context, Permission.storage.value, theme!)) { return; } } @@ -225,6 +227,7 @@ class _TIMUIKitImageElem extends TIMUIKitState { infoCode: 6660407)); } } + return; } getImgWidthAndHeight( @@ -236,34 +239,44 @@ class _TIMUIKitImageElem extends TIMUIKitState { return {height: curHeight, width: curWidth}; } - void _saveImg() { + Future _saveImg(TUITheme theme) async { String? path = widget.message.imageElem!.path; if (path != null && PlatformUtils().isWeb ? true : File(path!).existsSync()) { - _saveImageToLocal(context, path, isAsset: true); + return await _saveImageToLocal(context, path, isAsset: true, theme: theme); } else { String imgUrl = getBigPicUrl(); if (widget.message.imageElem!.imageList![0]!.localUrl != '' && widget.message.imageElem!.imageList![0]!.localUrl != null) { File f = File(widget.message.imageElem!.imageList![0]!.localUrl!); if (f.existsSync()) { - _saveImageToLocal( - context, widget.message.imageElem!.imageList![0]!.localUrl!, - isAsset: true); - return; + return await _saveImageToLocal( + context, + widget.message.imageElem!.imageList![0]!.localUrl!, + isAsset: true, + theme: theme, + ); } } if (widget.message.imageElem!.path != '' && widget.message.imageElem!.path != null) { File f = File(widget.message.imageElem!.path!); if (f.existsSync()) { - _saveImageToLocal(context, widget.message.imageElem!.path!, - isAsset: true); - return; + return await _saveImageToLocal( + context, + widget.message.imageElem!.path!, + isAsset: true, + theme: theme, + ); } } - _saveImageToLocal(context, imgUrl, isAsset: false); + return await _saveImageToLocal( + context, + imgUrl, + isAsset: false, + theme: theme, + ); } } @@ -278,7 +291,7 @@ class _TIMUIKitImageElem extends TIMUIKitState { Widget errorPage(theme) => Container( height: MediaQuery.of(context).size.height, - color: Colors.black, + color: theme.black, child: GestureDetector( onTap: () { Navigator.of(context).pop(); @@ -328,7 +341,9 @@ class _TIMUIKitImageElem extends TIMUIKitState { imageProvider: FileImage(File(imgPath)), heroTag: heroTag, messageID: widget.message.msgID, - downloadFn: () => _saveImg()), + downloadFn: () async { + return await _saveImg(theme!); + }), ), ); }, @@ -386,8 +401,7 @@ class _TIMUIKitImageElem extends TIMUIKitState { void setOnlineImageRatio() { if (networkImagePositionRadio == null) { V2TimImage? smallImg = getImageFromList(V2TimImageTypesEnum.small); - V2TimImage? originalImg = - getImageFromList(V2TimImageTypesEnum.original); + V2TimImage? originalImg = getImageFromList(V2TimImageTypesEnum.original); Image image = Image.network(smallImg?.url ?? originalImg?.url ?? ""); image.image @@ -434,7 +448,9 @@ class _TIMUIKitImageElem extends TIMUIKitState { ), heroTag: heroTag, messageID: widget.message.msgID, - downloadFn: () => _saveImg())), + downloadFn: () async { + return await _saveImg(theme!); + })), ); }, child: Container( @@ -444,7 +460,8 @@ class _TIMUIKitImageElem extends TIMUIKitState { tag: heroTag, child: PlatformUtils().isWeb ? Image.network( - path ?? smallImg?.url ?? originalImg!.url!, fit: BoxFit.contain) + path ?? smallImg?.url ?? originalImg!.url!, + fit: BoxFit.contain) : // Image.network(smallImg?.url ?? ""), CachedNetworkImage( @@ -539,8 +556,7 @@ class _TIMUIKitImageElem extends TIMUIKitState { final heroTag = "${widget.message.msgID ?? widget.message.id ?? widget.message.timestamp ?? DateTime.now().millisecondsSinceEpoch}${widget.isFrom}"; - V2TimImage? originalImg = - getImageFromList(V2TimImageTypesEnum.original); + V2TimImage? originalImg = getImageFromList(V2TimImageTypesEnum.original); V2TimImage? smallImg = getImageFromList(V2TimImageTypesEnum.small); return TIMUIKitMessageReactionWrapper( chatModel: widget.chatModel, diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_text_elem.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_text_elem.dart index 1ad6163..78122b2 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_text_elem.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_text_elem.dart @@ -192,7 +192,7 @@ class _TIMUIKitTextElemState extends TIMUIKitState { } final defaultStyle = widget.isFromSelf ? theme.lightPrimaryMaterialColor.shade50 - : theme.weakBackgroundColor; + : theme.chatMessageItemFromOthersBgColor; final backgroundColor = isShowJumpState ? const Color.fromRGBO(245, 166, 35, 1) : (widget.backgroundColor ?? defaultStyle); diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/intl_camer_picker.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/intl_camer_picker.dart index bc6ba22..85bf61d 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/intl_camer_picker.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/intl_camer_picker.dart @@ -22,6 +22,16 @@ class IntlCameraPickerTextDelegate extends CameraPickerTextDelegate { @override String get loadFailed => TIM_t('加载失败'); + /// Default loading string for the dialog. + /// 加载中弹窗的默认文字 + @override + String get loading => TIM_t('加载中…'); + + /// Saving string for the dialog. + /// 保存中弹窗的默认文字 + @override + String get saving => TIM_t('保存中…'); + /// Semantics fields. /// /// Fields below are only for semantics usage. For customizable these fields, diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/emoji_text.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/emoji_text.dart index 0756ce8..2f0592b 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/emoji_text.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/emoji_text.dart @@ -1,7 +1,6 @@ - import 'package:flutter/material.dart'; -import 'package:tencent_cloud_chat_uikit/ui/utils/constant_data.dart'; import 'package:tencent_extended_text/extended_text.dart'; +import 'package:tim_ui_kit_sticker_plugin/constant/emoji.dart'; ///emoji/image text class EmojiText extends SpecialText { @@ -18,7 +17,7 @@ class EmojiText extends SpecialText { InlineSpan finishText() { final String key = toString(); - if (EmojiUitl( + if (EmojiUtil( isUseDefaultEmoji: isUseDefaultEmoji, customEmojiStickerList: customEmojiStickerList) .instance @@ -34,7 +33,7 @@ class EmojiText extends SpecialText { if (isUseDefaultEmoji == true) { return ImageSpan( AssetImage( - EmojiUitl( + EmojiUtil( isUseDefaultEmoji: isUseDefaultEmoji, customEmojiStickerList: customEmojiStickerList) .instance @@ -48,7 +47,7 @@ class EmojiText extends SpecialText { margin: const EdgeInsets.all(0)); } else { return ImageSpan( - AssetImage(EmojiUitl( + AssetImage(EmojiUtil( isUseDefaultEmoji: isUseDefaultEmoji, customEmojiStickerList: customEmojiStickerList) .instance @@ -66,29 +65,27 @@ class EmojiText extends SpecialText { } } -class EmojiUitl { - EmojiUitl( +class EmojiUtil { + EmojiUtil( {this.isUseDefaultEmoji = false, this.customEmojiStickerList = const []}); - EmojiUitl._(this.isUseDefaultEmoji, this.customEmojiStickerList) { - RegExp exp = RegExp(r"([\u4e00-\u9fa5]+|[a-zA-Z]+)"); + EmojiUtil._(this.isUseDefaultEmoji, this.customEmojiStickerList) { if (isUseDefaultEmoji == true) { for (int i = 0; i < ConstData.emojiList.length; i++) { for (int j = 0; j < ConstData.emojiList[i].list.length; j++) { - var emojiPngNameMatch = - exp.firstMatch(ConstData.emojiList[i].list[j]); - String? emojiName = emojiPngNameMatch![0]; + String? emojiName = ConstData.emojiList[i].list[j].split('.png')[0]; _emojiMap['[$emojiName]'] = - '$_emojiFilePath/${ConstData.emojiList[i].name}/[$emojiName]@2x.png'; + '$_emojiFilePath/${ConstData.emojiList[i].name}/$emojiName.png'; + _emojiMap['[${ConstData.emojiMapList[emojiName]}]'] = + '$_emojiFilePath/${ConstData.emojiList[i].name}/$emojiName.png'; } } } else { for (int i = 0; i < customEmojiStickerList.length; i++) { for (int j = 0; j < customEmojiStickerList[i].list.length; j++) { - var emojiPngNameMatch = - exp.firstMatch(customEmojiStickerList[i].list[j]); - String? emojiName = emojiPngNameMatch![0]; + String? emojiName = + customEmojiStickerList[i].list[j].split('.png')[0]; _emojiMap['[$emojiName]'] = - '$_emojiFilePath/${customEmojiStickerList[i].name}/[$emojiName]@2x.png'; + '$_emojiFilePath/${customEmojiStickerList[i].name}/$emojiName.png'; } } } @@ -101,7 +98,7 @@ class EmojiUitl { final String _emojiFilePath = 'assets/custom_face_resource'; // EmojiUitl? _instance; - static EmojiUitl? _instance; - EmojiUitl get instance => - _instance ??= EmojiUitl._(isUseDefaultEmoji, customEmojiStickerList); + static EmojiUtil? _instance; + EmojiUtil get instance => + _instance ??= EmojiUtil._(isUseDefaultEmoji, customEmojiStickerList); } diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_more_panel.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_more_panel.dart index 3374e54..b0ce36d 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_more_panel.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_more_panel.dart @@ -31,7 +31,6 @@ import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; // ignore: unnecessary_import import 'dart:typed_data'; - import 'package:universal_html/html.dart' as html; class MorePanelConfig { @@ -91,7 +90,7 @@ class _MorePanelState extends TIMUIKitState { String? fileName; File? tempFile; - List itemList(TUIChatSeparateViewModel model) { + List itemList(TUIChatSeparateViewModel model, TUITheme theme) { final config = widget.morePanelConfig ?? MorePanelConfig(); return [ if (!PlatformUtils().isWeb) @@ -99,7 +98,7 @@ class _MorePanelState extends TIMUIKitState { id: "screen", title: TIM_t("拍摄"), onTap: (c) { - _onFeatureTap("screen", c, model); + _onFeatureTap("screen", c, model, theme); }, icon: Container( height: 64, @@ -120,7 +119,12 @@ class _MorePanelState extends TIMUIKitState { id: "photo", title: TIM_t("照片"), onTap: (c) { - _onFeatureTap("photo", c, model); + _onFeatureTap( + "photo", + c, + model, + theme, + ); }, icon: Container( height: 64, @@ -141,7 +145,12 @@ class _MorePanelState extends TIMUIKitState { id: "image", title: TIM_t("图片"), onTap: (c) { - _onFeatureTap("image", c, model); + _onFeatureTap( + "image", + c, + model, + theme, + ); }, icon: Container( height: 64, @@ -162,7 +171,12 @@ class _MorePanelState extends TIMUIKitState { id: "video", title: TIM_t("视频"), onTap: (c) { - _onFeatureTap("video", c, model); + _onFeatureTap( + "video", + c, + model, + theme, + ); }, icon: Container( height: 64, @@ -178,7 +192,12 @@ class _MorePanelState extends TIMUIKitState { id: "file", title: TIM_t("文件"), onTap: (c) { - _onFeatureTap("file", c, model); + _onFeatureTap( + "file", + c, + model, + theme, + ); }, icon: Container( height: 64, @@ -255,12 +274,15 @@ class _MorePanelState extends TIMUIKitState { context); } - _sendImageMessage(TUIChatSeparateViewModel model) async { + _sendImageMessage(TUIChatSeparateViewModel model, TUITheme theme) async { try { final bool isAndroid = PlatformUtils().isAndroid; if (!PlatformUtils().isWeb && - !await Permissions.checkPermission(context, - isAndroid ? Permission.storage.value : Permission.photos.value)) { + !await Permissions.checkPermission( + context, + isAndroid ? Permission.storage.value : Permission.photos.value, + theme, + )) { return; } final convID = widget.conversationID; @@ -291,11 +313,17 @@ class _MorePanelState extends TIMUIKitState { } } - _sendImageFromCamera(TUIChatSeparateViewModel model) async { + _sendImageFromCamera( + TUIChatSeparateViewModel model, + TUITheme theme, + ) async { try { if (PlatformUtils().isIOS && !await Permissions.checkPermission( - context, Permission.camera.value)) { + context, + Permission.camera.value, + theme, + )) { return; } final convID = widget.conversationID; @@ -386,9 +414,16 @@ class _MorePanelState extends TIMUIKitState { } } - _sendFile(TUIChatSeparateViewModel model) async { + _sendFile( + TUIChatSeparateViewModel model, + TUITheme theme, + ) async { if (!kIsWeb && - !await Permissions.checkPermission(context, Permission.storage.value)) { + !await Permissions.checkPermission( + context, + Permission.storage.value, + theme, + )) { return; } try { @@ -436,16 +471,20 @@ class _MorePanelState extends TIMUIKitState { } _onFeatureTap( - String id, BuildContext context, TUIChatSeparateViewModel model) async { + String id, + BuildContext context, + TUIChatSeparateViewModel model, + TUITheme theme, + ) async { switch (id) { case "photo": - _sendImageMessage(model); + _sendImageMessage(model, theme); break; case "screen": - _sendImageFromCamera(model); + _sendImageFromCamera(model, theme); break; case "file": - _sendFile(model); + _sendFile(model, theme); break; case "image": // only for web @@ -478,37 +517,37 @@ class _MorePanelState extends TIMUIKitState { child: Wrap( spacing: (screenWidth - (23 * 2) - 64 * 4) / 3, runSpacing: 20, - children: itemList(model) + children: itemList(model, theme) .map((item) => InkWell( - onTap: () { - if (item.onTap != null) { - item.onTap!(context); - } - }, - child: widget.morePanelConfig?.actionBuilder != null - ? widget.morePanelConfig?.actionBuilder!(item) - : SizedBox( - height: 94, - width: 64, - child: Column( - children: [ - Container( - height: 64, - width: 64, - margin: const EdgeInsets.only(bottom: 4), - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(5))), - child: item.icon, - ), - Text( - item.title, - style: TextStyle( - fontSize: 12, color: theme.darkTextColor), - ) - ], - ), - ))) + onTap: () { + if (item.onTap != null) { + item.onTap!(context); + } + }, + child: widget.morePanelConfig?.actionBuilder != null + ? widget.morePanelConfig?.actionBuilder!(item) + : SizedBox( + height: 94, + width: 64, + child: Column( + children: [ + Container( + height: 64, + width: 64, + margin: const EdgeInsets.only(bottom: 4), + decoration: const BoxDecoration( + borderRadius: + BorderRadius.all(Radius.circular(5))), + child: item.icon, + ), + Text( + item.title, + style: TextStyle( + fontSize: 12, color: theme.darkTextColor), + ) + ], + ), + ))) .toList(), ), ), diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_send_sound_message.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_send_sound_message.dart index d203a3b..beb95ce 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_send_sound_message.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_send_sound_message.dart @@ -291,7 +291,10 @@ class _SendSoundMessageState extends TIMUIKitState { onTapDown: (detail) async { if (!isInit) { bool hasMicrophonePermission = await Permissions.checkPermission( - context, Permission.microphone.value); + context, + Permission.microphone.value, + theme, + ); if (!hasMicrophonePermission) { return; } diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field.dart index 7ba1631..a38fae2 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field.dart @@ -1,7 +1,8 @@ import 'dart:async'; +import 'dart:math'; -import 'package:tencent_cloud_chat_uikit/ui/utils/constant_data.dart'; -import 'package:tencent_cloud_chat_uikit/ui/utils/custom_emoji_face_data_class.dart'; +import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_setting_model.dart'; +import 'package:tencent_cloud_chat_uikit/ui/utils/optimize_utils.dart'; import 'package:tencent_extended_text_field/extended_text_field.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -16,7 +17,6 @@ import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_conversa import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart'; import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart'; import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart'; - import 'package:tencent_cloud_chat_uikit/ui/utils/message.dart'; import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart'; import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_at_text.dart'; @@ -24,6 +24,7 @@ import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_send_sound_message.dart'; import 'package:tencent_cloud_chat_uikit/ui/utils/permission.dart'; +import 'package:tencent_keyboard_visibility/tencent_keyboard_visibility.dart'; import 'special_text/DefaultSpecialTextSpanBuilder.dart'; enum MuteStatus { none, me, all } @@ -53,13 +54,13 @@ class TIMUIKitInputTextField extends StatefulWidget { /// show send emoji icon final bool showSendEmoji; - /// show more pannel - final bool showMorePannel; + /// show more panel + final bool showMorePanel; /// background color final Color? backgroundColor; - /// controll input field behavior + /// control input field behavior final TIMUIKitInputTextFieldController? controller; /// on text changed @@ -72,7 +73,7 @@ class TIMUIKitInputTextField extends StatefulWidget { final List customEmojiStickerList; - /// sticker panel customiziation + /// sticker panel customization final Widget Function( {void Function() sendTextMessage, void Function(int index, String data) sendFaceMessage, @@ -93,7 +94,7 @@ class TIMUIKitInputTextField extends StatefulWidget { this.customStickerPanel, this.showSendAudio = true, this.showSendEmoji = true, - this.showMorePannel = true, + this.showMorePanel = true, this.backgroundColor, this.controller, this.onChanged, @@ -108,6 +109,7 @@ class TIMUIKitInputTextField extends StatefulWidget { class _InputTextFieldState extends TIMUIKitState { final TUIChatGlobalModel globalModel = serviceLocator(); + final TUISettingModel settingModel = serviceLocator(); bool showMore = false; bool showMoreButton = true; bool showSendSoundText = false; @@ -116,7 +118,10 @@ class _InputTextFieldState extends TIMUIKitState { late FocusNode focusNode; String zeroWidthSpace = '\ufeff'; String lastText = ""; - double lastkeyboardHeight = 0; + String languageType = ""; + double? bottomPadding; + Function? setKeyboardHeight; + int? currentCursor; Map memberInfoMap = {}; @@ -128,21 +133,6 @@ class _InputTextFieldState extends TIMUIKitState { int latestSendEditStatusTime = DateTime.now().millisecondsSinceEpoch; - listenKeyBoardStatus() { - final currentKeyboardHeight = MediaQuery.of(context).viewInsets.bottom; - // 键盘弹出 - if (currentKeyboardHeight - lastkeyboardHeight > 0) { - // 保证弹出时showKeyboard为true - setState(() { - showKeyboard = true; - }); - - /// 键盘收回 - } else if (currentKeyboardHeight - lastkeyboardHeight < 0) {} - - lastkeyboardHeight = MediaQuery.of(context).viewInsets.bottom; - } - Widget _getBottomContainer() { if (showEmojiPanel) { return widget.customStickerPanel != null @@ -155,26 +145,27 @@ class _InputTextFieldState extends TIMUIKitState { backSpaceText(); }, addText: (int unicode) { - final oldText = textEditingController.text; final newText = String.fromCharCode(unicode); - textEditingController.text = "$oldText$newText"; + addStickerToText(newText); // handleSetDraftText(); }, addCustomEmojiText: ((String singleEmojiName) { - RegExp exp = RegExp(r"([\u4e00-\u9fa5]+|[a-zA-Z]+)"); - var emojiPngNameMatch = exp.firstMatch(singleEmojiName); - String? emojiName = emojiPngNameMatch![0]; - final oldText = textEditingController.text; + String? emojiName = singleEmojiName.split('.png')[0]; + if (widget.isUseDefaultEmoji && + languageType == 'zh' && + ConstData.emojiMapList[emojiName] != null && + ConstData.emojiMapList[emojiName] != '') { + emojiName = ConstData.emojiMapList[emojiName]; + } final newText = '[$emojiName]'; - textEditingController.text = "$oldText$newText"; + addStickerToText(newText); setSendButton(); }), defaultCustomEmojiStickerList: widget.isUseDefaultEmoji ? ConstData.emojiList : []) : EmojiPanel(onTapEmoji: (unicode) { - final oldText = textEditingController.text; final newText = String.fromCharCode(unicode); - textEditingController.text = "$oldText$newText"; + addStickerToText(newText); setSendButton(); // handleSetDraftText(); }, onSubmitted: () { @@ -191,29 +182,49 @@ class _InputTextFieldState extends TIMUIKitState { conversationType: widget.conversationType); } - return Container(); + return const SizedBox(height: 0); + } + + void addStickerToText(String sticker){ + final oldText = textEditingController.text; + if(currentCursor != null && currentCursor! > -1){ + final firstString = oldText.substring(0, currentCursor); + final secondString = oldText.substring(currentCursor!); + currentCursor = currentCursor! + sticker.length; + textEditingController.text = "$firstString$sticker$secondString"; + }else{ + textEditingController.text = "$oldText$sticker"; + } } double _getBottomHeight() { - listenKeyBoardStatus(); - // if (showKeyboard) { - // // return MediaQuery.of(context).viewInsets.bottom; - // return 0; - // } else - if (showMore || showEmojiPanel) { - return 248.0; - } - // 在文本框多行拓展时增加保护区高度 - else if (textEditingController.text.length >= 46 && showKeyboard == false) { - return 25; + if (showKeyboard) { + final currentKeyboardHeight = MediaQuery.of(context).viewInsets.bottom; + double originHeight = settingModel.keyboardHeight; + if (currentKeyboardHeight != 0) { + if (currentKeyboardHeight >= originHeight) { + originHeight = currentKeyboardHeight; + } + if (setKeyboardHeight != null) { + setKeyboardHeight!(currentKeyboardHeight); + } + } + final height = originHeight != 0 ? originHeight : currentKeyboardHeight; + return height; + } else if (showMore || showEmojiPanel) { + return 248.0 + (bottomPadding ?? 0.0); + } else if (textEditingController.text.length >= 46 && + showKeyboard == false) { + return 25 + (bottomPadding ?? 0.0); } else { - return 0; + return bottomPadding ?? 0; } } _openMore() { if (!showMore) { focusNode.unfocus(); + currentCursor = null; } setState(() { showKeyboard = false; @@ -224,6 +235,8 @@ class _InputTextFieldState extends TIMUIKitState { } _openEmojiPanel() { + _onCursorChange(); + showKeyboard = showEmojiPanel; if (showEmojiPanel) { focusNode.requestFocus(); } else { @@ -231,7 +244,6 @@ class _InputTextFieldState extends TIMUIKitState { } setState(() { - showKeyboard = showEmojiPanel; showMore = false; showSendSoundText = false; showEmojiPanel = !showEmojiPanel; @@ -294,10 +306,7 @@ class _InputTextFieldState extends TIMUIKitState { onTap: () { widget.model.repliedMessage = null; }, - child: Icon( - Icons.clear, - color: hexToColor("8f959e"), - size: 18), + child: Icon(Icons.clear, color: hexToColor("8f959e"), size: 18), ) ], ), @@ -334,11 +343,6 @@ class _InputTextFieldState extends TIMUIKitState { // handleSetDraftText(); } setSendButton(); - - // if (originalText.isNotEmpty) { - // text = originalText.characters.skipLast(1); - // textEditingController.text = "$text"; - // } } // 和onSubmitted一样,只是保持焦点的不同 @@ -416,6 +420,7 @@ class _InputTextFieldState extends TIMUIKitState { context); } textEditingController.clear(); + currentCursor = null; if (showKeyboard) { focusNode.requestFocus(); } @@ -450,6 +455,7 @@ class _InputTextFieldState extends TIMUIKitState { _hideAllPanel() { focusNode.unfocus(); + currentCursor == null; if (showKeyboard != false || showMore != false || showEmojiPanel != false) { setState(() { showKeyboard = false; @@ -461,17 +467,13 @@ class _InputTextFieldState extends TIMUIKitState { void onModelChanged() { if (widget.model.repliedMessage != null) { + showKeyboard = true; focusNode.requestFocus(); _addDeleteTag(); - setState(() { - showKeyboard = true; - }); } else {} if (widget.model.editRevokedMsg != "") { + showKeyboard = true; focusNode.requestFocus(); - setState(() { - showKeyboard = true; - }); textEditingController.clear(); textEditingController.text = widget.model.editRevokedMsg; textEditingController.selection = TextSelection.fromPosition(TextPosition( @@ -488,6 +490,11 @@ class _InputTextFieldState extends TIMUIKitState { TextPosition(offset: textEditingController.text.length)); } + _onCursorChange() { + final selection = textEditingController.selection; + currentCursor = selection.baseOffset; + } + _handleSoftKeyBoardDelete() { if (widget.model.repliedMessage != null) { widget.model.repliedMessage = null; @@ -622,6 +629,11 @@ class _InputTextFieldState extends TIMUIKitState { if (widget.initText != null) { textEditingController.text = widget.initText!; } + final AppLocale appLocale = I18nUtils.findDeviceLocale(); + languageType = + (appLocale == AppLocale.zhHans || appLocale == AppLocale.zhHant) + ? 'zh' + : 'en'; } @override @@ -697,7 +709,13 @@ class _InputTextFieldState extends TIMUIKitState { final theme = value.theme; final TUIChatSeparateViewModel model = Provider.of(context); + + setKeyboardHeight ??= OptimizeUtils.debounce((height) { + settingModel.keyboardHeight = height; + }, const Duration(seconds: 1)); + _getMuteType(model); + final debounceFunc = _debounce((value) { if (isWebDevice() || isAndroidDevice()) { if (value.isEmpty && showMoreButton != true) { @@ -721,6 +739,12 @@ class _InputTextFieldState extends TIMUIKitState { } }, const Duration(milliseconds: 80)); + final MediaQueryData data = MediaQuery.of(context); + EdgeInsets padding = data.padding; + if (bottomPadding == null || padding.bottom > bottomPadding!) { + bottomPadding = padding.bottom; + } + return Selector( builder: ((context, value, child) { String? getForbiddenText() { @@ -742,188 +766,201 @@ class _InputTextFieldState extends TIMUIKitState { _buildRepliedMessage(value), Container( color: widget.backgroundColor ?? hexToColor("f5f5f6"), - child: SafeArea( - child: Column( - children: [ - Container( - padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 16), - constraints: const BoxConstraints(minHeight: 50), - child: Row( - children: [ - if (forbiddenText != null) - Expanded( - child: Container( - height: 35, - color: theme.weakBackgroundColor, - alignment: Alignment.center, - child: Text( - TIM_t(forbiddenText), - textAlign: TextAlign.center, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - color: theme.weakTextColor, - ), - ), - )), - if (!PlatformUtils().isWeb && - widget.showSendAudio && - forbiddenText == null) - InkWell( - onTap: () async { - if (showSendSoundText) { - focusNode.requestFocus(); - setState(() { - showKeyboard = true; - }); - } - if (await Permissions.checkPermission( - context, Permission.microphone.value)) { - setState(() { - showEmojiPanel = false; - showMore = false; - showSendSoundText = !showSendSoundText; - }); - } - }, - child: SvgPicture.asset( - showSendSoundText - ? 'images/keyboard.svg' - : 'images/voice.svg', - package: 'tencent_cloud_chat_uikit', - color: const Color.fromRGBO(68, 68, 68, 1), - height: 28, - width: 28, + child: Column( + children: [ + Container( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 16), + constraints: const BoxConstraints(minHeight: 50), + child: Row( + children: [ + if (forbiddenText != null) + Expanded( + child: Container( + height: 35, + color: theme.weakBackgroundColor, + alignment: Alignment.center, + child: Text( + TIM_t(forbiddenText), + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + color: theme.weakTextColor, ), ), - if (forbiddenText == null) - const SizedBox( - width: 10, + )), + if (!PlatformUtils().isWeb && + widget.showSendAudio && + forbiddenText == null) + InkWell( + onTap: () async { + if (showSendSoundText) { + showKeyboard = true; + focusNode.requestFocus(); + } + if (await Permissions.checkPermission( + context, + Permission.microphone.value, + theme, + )) { + setState(() { + showEmojiPanel = false; + showKeyboard = false; + showMore = false; + showSendSoundText = !showSendSoundText; + }); + } + }, + child: SvgPicture.asset( + showSendSoundText + ? 'images/keyboard.svg' + : 'images/voice.svg', + package: 'tencent_cloud_chat_uikit', + color: const Color.fromRGBO(68, 68, 68, 1), + height: 28, + width: 28, ), - if (forbiddenText == null) - Expanded( - child: showSendSoundText - ? SendSoundMessage( - onDownBottom: goDownBottom, - conversationID: widget.conversationID, - conversationType: - widget.conversationType) - : ExtendedTextField( - // selectionControls: - // _defaultTextSelectionControls, - maxLines: 4, - minLines: 1, - focusNode: focusNode, - onChanged: debounceFunc, - onTap: () { - goDownBottom(); - setState(() { + ), + if (forbiddenText == null) + const SizedBox( + width: 10, + ), + if (forbiddenText == null) + Expanded( + child: showSendSoundText + ? SendSoundMessage( + onDownBottom: goDownBottom, + conversationID: widget.conversationID, + conversationType: widget.conversationType) + : KeyboardVisibility( + child: ExtendedTextField( + maxLines: 4, + minLines: 1, + focusNode: focusNode, + onChanged: debounceFunc, + onTap: () { showKeyboard = true; - showEmojiPanel = false; - showMore = false; + goDownBottom(); + setState(() { + showEmojiPanel = false; + showMore = false; + }); + }, + keyboardType: TextInputType.multiline, + textInputAction: + PlatformUtils().isAndroid + ? TextInputAction.newline + : TextInputAction.send, + onEditingComplete: onSubmitted, + textAlignVertical: + TextAlignVertical.top, + decoration: InputDecoration( + border: InputBorder.none, + hintStyle: const TextStyle( + // fontSize: 10, + color: Color(0xffAEA4A3), + ), + fillColor: Colors.white, + filled: true, + isDense: true, + hintText: widget.hintText ?? ''), + controller: textEditingController, + specialTextSpanBuilder: PlatformUtils().isWeb + ? null + : DefaultSpecialTextSpanBuilder( + isUseDefaultEmoji: + widget.isUseDefaultEmoji, + customEmojiStickerList: widget + .customEmojiStickerList, + showAtBackground: true, + ) + ), + onChanged: (bool visibility) { + if (showKeyboard != visibility && + visibility == false) { + setState(() { + showKeyboard = visibility; }); - }, - keyboardType: TextInputType.multiline, - textInputAction: - PlatformUtils().isAndroid - ? TextInputAction.newline - : TextInputAction.send, - onEditingComplete: onSubmitted, - textAlignVertical: - TextAlignVertical.center, - decoration: InputDecoration( - border: InputBorder.none, - hintStyle: const TextStyle( - // fontSize: 10, - color: Color(0xffAEA4A3), - ), - fillColor: Colors.white, - filled: true, - isDense: true, - hintText: widget.hintText ?? ''), - controller: textEditingController, - specialTextSpanBuilder: - DefaultSpecialTextSpanBuilder( - isUseDefaultEmoji: - widget.isUseDefaultEmoji, - customEmojiStickerList: - widget.customEmojiStickerList, - showAtBackground: true, - )), + } + }), + ), + if (forbiddenText == null) + const SizedBox( + width: 10, + ), + if (widget.showSendEmoji && forbiddenText == null) + InkWell( + onTap: () { + _openEmojiPanel(); + goDownBottom(); + }, + child: PlatformUtils().isWeb + ? Icon( + showEmojiPanel + ? Icons.keyboard_alt_outlined + : Icons.mood_outlined, + color: hexToColor("5c6168"), + size: 32) + : SvgPicture.asset( + showEmojiPanel + ? 'images/keyboard.svg' + : 'images/face.svg', + package: 'tencent_cloud_chat_uikit', + color: + const Color.fromRGBO(68, 68, 68, 1), + height: 28, + width: 28, + ), + ), + if (forbiddenText == null) + const SizedBox( + width: 10, + ), + if (widget.showMorePanel && + forbiddenText == null && + showMoreButton) + InkWell( + onTap: () { + // model.sendCustomMessage(data: "a", convID: model.currentSelectedConv, convType: model.currentSelectedConvType == 1 ? ConvType.c2c : ConvType.group); + _openMore(); + goDownBottom(); + }, + child: PlatformUtils().isWeb + ? Icon(Icons.add_circle_outline_outlined, + color: hexToColor("5c6168"), size: 32) + : SvgPicture.asset( + 'images/add.svg', + package: 'tencent_cloud_chat_uikit', + color: + const Color.fromRGBO(68, 68, 68, 1), + height: 28, + width: 28, + ), + ), + if ((isAndroidDevice() || isWebDevice()) && + !showMoreButton) + SizedBox( + height: 32.0, + child: ElevatedButton( + onPressed: onSubmitted, + child: Text(TIM_t("发送")), ), - if (forbiddenText == null) - const SizedBox( - width: 10, - ), - if (widget.showSendEmoji && forbiddenText == null) - InkWell( - onTap: () { - _openEmojiPanel(); - goDownBottom(); - }, - child: kIsWeb - ? Icon( - showEmojiPanel - ? Icons.keyboard_alt_outlined - : Icons.mood_outlined, - color: hexToColor("5c6168"), - size: 32) - : SvgPicture.asset( - showEmojiPanel - ? 'images/keyboard.svg' - : 'images/face.svg', - package: 'tencent_cloud_chat_uikit', - color: - const Color.fromRGBO(68, 68, 68, 1), - height: 28, - width: 28, - ), - ), - if (forbiddenText == null) - const SizedBox( - width: 10, - ), - if (widget.showMorePannel && - forbiddenText == null && - showMoreButton) - InkWell( - onTap: () { - // model.sendCustomMessage(data: "a", convID: model.currentSelectedConv, convType: model.currentSelectedConvType == 1 ? ConvType.c2c : ConvType.group); - _openMore(); - goDownBottom(); - }, - child: kIsWeb - ? Icon(Icons.add_circle_outline_outlined, - color: hexToColor("5c6168"), size: 32) - : SvgPicture.asset( - 'images/add.svg', - package: 'tencent_cloud_chat_uikit', - color: - const Color.fromRGBO(68, 68, 68, 1), - height: 28, - width: 28, - ), - ), - if ((isAndroidDevice() || isWebDevice()) && - !showMoreButton) - SizedBox( - height: 32.0, - child: ElevatedButton( - onPressed: onSubmitted, - child: Text(TIM_t("发送")), - ), - ), - ], - ), + ), + ], ), - AnimatedContainer( - duration: const Duration(milliseconds: 150), - height: _getBottomHeight(), - child: _getBottomContainer(), - ) - ], - ), + ), + AnimatedContainer( + duration: Duration( + milliseconds: + (showKeyboard && PlatformUtils().isAndroid) + ? 200 + : 340), + curve: Curves.fastOutSlowIn, + height: max(_getBottomHeight(), 0.0), + child: _getBottomContainer(), + ), + ], ), ) ], diff --git a/lib/ui/views/TIMUIKitChat/tim_uikit_chat.dart b/lib/ui/views/TIMUIKitChat/tim_uikit_chat.dart index 6d530f8..ad300f1 100644 --- a/lib/ui/views/TIMUIKitChat/tim_uikit_chat.dart +++ b/lib/ui/views/TIMUIKitChat/tim_uikit_chat.dart @@ -16,7 +16,6 @@ import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart'; import 'package:tencent_cloud_chat_uikit/ui/constants/history_message_constant.dart'; import 'package:tencent_cloud_chat_uikit/ui/controller/tim_uikit_chat_controller.dart'; -import 'package:tencent_cloud_chat_uikit/ui/utils/custom_emoji_face_data_class.dart'; import 'package:tencent_cloud_chat_uikit/ui/utils/frame.dart'; import 'package:tencent_cloud_chat_uikit/ui/utils/optimize_utils.dart'; import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/tim_uikit_multi_select_panel.dart'; @@ -318,6 +317,7 @@ class _TUIChatState extends TIMUIKitState { textFieldController.hideAllPanel(); }, child: Scaffold( + resizeToAvoidBottomInset: false, appBar: TIMUIKitAppBar( showTotalUnReadCount: widget.showTotalUnReadCount, config: widget.appBarConfig, @@ -395,7 +395,7 @@ class _TUIChatState extends TIMUIKitState { conversationType: widget.conversationType, initText: widget.draftText, hintText: widget.textFieldHintText, - showMorePannel: + showMorePanel: widget.config?.isAllowShowMorePanel ?? true, showSendAudio: diff --git a/lib/ui/views/TIMUIKitChat/tim_uikit_multi_select_panel.dart b/lib/ui/views/TIMUIKitChat/tim_uikit_multi_select_panel.dart index c309cea..02dfa76 100644 --- a/lib/ui/views/TIMUIKitChat/tim_uikit_multi_select_panel.dart +++ b/lib/ui/views/TIMUIKitChat/tim_uikit_multi_select_panel.dart @@ -5,7 +5,6 @@ import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart'; - import 'package:tencent_cloud_chat_uikit/ui/widgets/forward_message_screen.dart'; import 'package:tencent_im_base/tencent_im_base.dart'; @@ -50,21 +49,21 @@ class MultiSelectPanel extends TIMUIKitStatelessWidget { children: [ IconButton( icon: Image.asset('images/forward.png', - package: 'tencent_cloud_chat_uikit', color: Colors.white), + package: 'tencent_cloud_chat_uikit', color: theme.white), iconSize: 40, onPressed: () { _handleForwardMessage(context, false, model); }, ), Text(TIM_t("逐条转发"), - style: const TextStyle(color: Colors.white, fontSize: 12)) + style: TextStyle(color: theme.white, fontSize: 12)) ], ), Column( children: [ IconButton( icon: Image.asset('images/merge_forward.png', - package: 'tencent_cloud_chat_uikit', color: Colors.white), + package: 'tencent_cloud_chat_uikit', color: theme.white), iconSize: 40, onPressed: () { _handleForwardMessage(context, true, model); @@ -72,7 +71,7 @@ class MultiSelectPanel extends TIMUIKitStatelessWidget { ), Text( TIM_t("合并转发"), - style: const TextStyle(color: Colors.white, fontSize: 12), + style: TextStyle(color: theme.white, fontSize: 12), ) ], ), @@ -80,7 +79,7 @@ class MultiSelectPanel extends TIMUIKitStatelessWidget { children: [ IconButton( icon: Image.asset('images/delete.png', - package: 'tencent_cloud_chat_uikit', color: Colors.white), + package: 'tencent_cloud_chat_uikit', color: theme.white), iconSize: 40, onPressed: () { showCupertinoModalPopup( @@ -121,7 +120,7 @@ class MultiSelectPanel extends TIMUIKitStatelessWidget { }, ), Text(TIM_t("删除"), - style: const TextStyle(color: Colors.white, fontSize: 12)) + style: TextStyle(color: theme.white, fontSize: 12)) ], ) ], diff --git a/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation.dart b/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation.dart index 5f8c0ef..37d60f9 100644 --- a/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation.dart +++ b/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation.dart @@ -187,8 +187,9 @@ class _TIMUIKitConversationState extends TIMUIKitState { onPressed: (context) { _clearHistory(conversationItem); }, - backgroundColor: theme.primaryColor ?? CommonColor.primaryColor, - foregroundColor: Colors.white, + backgroundColor: theme.conversationItemSliderClearBgColor ?? + CommonColor.primaryColor, + foregroundColor: theme.conversationItemSliderTextColor, label: TIM_t("清除聊天"), spacing: 0, autoClose: true, @@ -197,16 +198,18 @@ class _TIMUIKitConversationState extends TIMUIKitState { onPressed: (context) { _pinConversation(conversationItem); }, - backgroundColor: theme.infoColor ?? CommonColor.infoColor, - foregroundColor: Colors.white, + backgroundColor: + theme.conversationItemSliderPinBgColor ?? CommonColor.infoColor, + foregroundColor: theme.conversationItemSliderTextColor, label: conversationItem.isPinned! ? TIM_t("取消置顶") : TIM_t("置顶"), ), ConversationItemSlidablePanel( onPressed: (context) { _deleteConversation(conversationItem); }, - backgroundColor: Colors.red, - foregroundColor: Colors.white, + backgroundColor: + theme.conversationItemSliderDeleteBgColor ?? Colors.red, + foregroundColor: theme.conversationItemSliderTextColor, label: TIM_t("删除"), ) ]; diff --git a/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation_draft_text.dart b/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation_draft_text.dart index 46a5c94..e7b7d2f 100644 --- a/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation_draft_text.dart +++ b/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation_draft_text.dart @@ -24,14 +24,20 @@ class TIMUIKitDraftText extends TIMUIKitStatelessWidget { Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { final TUITheme theme = value.theme; return Row(children: [ - Text(_getDraftShowText(), style: TextStyle(color: theme.cautionColor)), + Text(_getDraftShowText(), + style: TextStyle( + color: theme.conversationItemDraftTextColor, + )), Expanded( child: Text( draftText, softWrap: true, overflow: TextOverflow.ellipsis, maxLines: 1, - style: TextStyle(height: 1.5, color: theme.weakTextColor, fontSize: 14), + style: TextStyle( + height: 1.5, + color: theme.conversationItemLastMessageTextColor, + fontSize: 14), )), ]); } diff --git a/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation_item.dart b/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation_item.dart index 540ff9d..ae07634 100644 --- a/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation_item.dart +++ b/lib/ui/views/TIMUIKitConversation/tim_uikit_conversation_item.dart @@ -85,13 +85,13 @@ class TIMUIKitConversationItem extends TIMUIKitStatelessWidget { return Text(TimeAgo().getTimeStringForChat(draftTimestamp as int), style: TextStyle( fontSize: 12, - color: theme.weakTextColor, + color: theme.conversationItemTitmeTextColor, )); } else if (lastMsg != null) { return Text(TimeAgo().getTimeStringForChat(lastMsg!.timestamp as int), style: TextStyle( fontSize: 12, - color: theme.weakTextColor, + color: theme.conversationItemTitmeTextColor, )); } } catch (err) {} @@ -105,11 +105,17 @@ class TIMUIKitConversationItem extends TIMUIKitStatelessWidget { return Container( padding: const EdgeInsets.only(top: 6, bottom: 6, left: 16, right: 16), decoration: BoxDecoration( - color: isPined ? theme.weakBackgroundColor : Colors.white, - border: Border( - bottom: BorderSide( - color: theme.weakDividerColor ?? CommonColor.weakDividerColor, - width: 1))), + color: isPined + ? theme.conversationItemPinedBgColor + : theme.conversationItemBgColor, + border: Border( + bottom: BorderSide( + color: theme.conversationItemBorderColor ?? + CommonColor.weakDividerColor, + width: 1, + ), + ), + ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -160,11 +166,12 @@ class TIMUIKitConversationItem extends TIMUIKitStatelessWidget { textAlign: TextAlign.left, overflow: TextOverflow.ellipsis, maxLines: 1, - style: const TextStyle( - height: 1, - color: Colors.black, - fontSize: 18, - fontWeight: FontWeight.w400), + style: TextStyle( + height: 1, + color: theme.conversationItemTitleTextColor, + fontSize: 18, + fontWeight: FontWeight.w400, + ), )), _getTimeStringForChatWidget(context, theme), ], @@ -182,7 +189,7 @@ class TIMUIKitConversationItem extends TIMUIKitStatelessWidget { height: 18, child: Icon( Icons.notifications_off, - color: theme.weakTextColor, + color: theme.conversationItemNoNotificationIconColor, size: 16.0, ), ) diff --git a/lib/ui/views/TIMUIKitGroupProfile/tim_uikit_group_profile.dart b/lib/ui/views/TIMUIKitGroupProfile/tim_uikit_group_profile.dart index ce286e1..751c440 100644 --- a/lib/ui/views/TIMUIKitGroupProfile/tim_uikit_group_profile.dart +++ b/lib/ui/views/TIMUIKitGroupProfile/tim_uikit_group_profile.dart @@ -93,6 +93,14 @@ class _TIMUIKitGroupProfileState extends TIMUIKitState { super.dispose(); } + @override + void didUpdateWidget(covariant TIMUIKitGroupProfile oldWidget) { + super.didUpdateWidget(oldWidget); + if(oldWidget.groupID != widget.groupID){ + model.loadData(widget.groupID); + } + } + final List _defaultWidgetOrder = [ GroupProfileWidgetEnum.detailCard, GroupProfileWidgetEnum.operationDivider, @@ -213,7 +221,7 @@ class _TIMUIKitGroupProfileState extends TIMUIKitState { if (isAdmin || isGroupOwner) { return (customBuilder?.groupManage != null ? customBuilder?.groupManage!(toDefaultManagePage) - : TIMUIKitGroupProfileWidget.groupManage(model))!; + : TIMUIKitGroupProfileWidget.groupManage())!; } else { return Container(); } diff --git a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_ui_group_profile_widget.dart b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_ui_group_profile_widget.dart index 610a1bb..eb06254 100644 --- a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_ui_group_profile_widget.dart +++ b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_ui_group_profile_widget.dart @@ -32,8 +32,8 @@ class TIMUIKitGroupProfileWidget { return GroupProfileNotification(); } - static Widget groupManage(TUIGroupProfileModel model) { - return GroupProfileGroupManage(model); + static Widget groupManage() { + return GroupProfileGroupManage(); } static Widget searchMessage(Function(V2TimConversation?) onJumpToSearch) { diff --git a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_manage.dart b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_manage.dart index 2487a2a..64588eb 100644 --- a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_manage.dart +++ b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_manage.dart @@ -16,8 +16,7 @@ import 'package:tencent_cloud_chat_uikit/ui/widgets/radio_button.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; class GroupProfileGroupManage extends TIMUIKitStatelessWidget { - final TUIGroupProfileModel model; - GroupProfileGroupManage(this.model, {Key? key}) : super(key: key); + GroupProfileGroupManage({Key? key}) : super(key: key); @override Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { @@ -600,24 +599,17 @@ class _GroupProfileAddAdminState extends TIMUIKitState { onTap: () { final isChecked = selectedMemberList.contains(e); if (isChecked) { - selectedMemberList.add(e); - } else { selectedMemberList.remove(e); + } else { + selectedMemberList.add(e); } setState(() {}); }, child: Row( children: [ CheckBoxButton( + onlyShow: true, isChecked: selectedMemberList.contains(e), - onChanged: (value) { - if (value) { - selectedMemberList.add(e); - } else { - selectedMemberList.remove(e); - } - setState(() {}); - }, ), const SizedBox( width: 10, diff --git a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_name_card.dart b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_name_card.dart index 59696aa..de39696 100644 --- a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_name_card.dart +++ b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_name_card.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_group_profile_model.dart'; +import 'package:tencent_cloud_chat_uikit/ui/widgets/text_input_bottom_sheet.dart'; import 'package:tencent_im_base/tencent_im_base.dart'; @@ -35,78 +36,12 @@ class GroupProfileNameCard extends TIMUIKitStatelessWidget { theme.weakDividerColor ?? CommonColor.weakDividerColor))), child: InkWell( onTap: () async { - showModalBottomSheet( - isScrollControlled: true, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - context: context, - builder: (context) { - return Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(10.0), - topRight: Radius.circular(10.0))), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - padding: const EdgeInsets.symmetric(vertical: 20), - child: Text(TIM_t("修改我的群昵称")), - ), - Divider(height: 2, color: theme.weakDividerColor), - Padding( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextField( - controller: controller, - decoration: InputDecoration( - border: InputBorder.none, - fillColor: theme.weakBackgroundColor, - filled: true, - isDense: true, - hintText: ''), - ), - const SizedBox( - height: 10, - ), - Text( - TIM_t("仅限中文、字母、数字和下划线,2-20个字"), - style: TextStyle( - fontSize: 13, color: theme.weakTextColor), - textAlign: TextAlign.left, - ), - const SizedBox( - height: 30, - ), - SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: () { - final text = controller.text.trim(); - model.setNameCard(text); - Navigator.pop(context); - }, - child: Text(TIM_t("确定")), - )), - const SizedBox( - height: 20, - ), - Padding( - padding: EdgeInsets.only( - bottom: - MediaQuery.of(context).viewInsets.bottom), - ) - ], - ), - ) - ], - ), - ); - }); + TextInputBottomSheet.showTextInputBottomSheet( + context, TIM_t("修改我的群昵称"), TIM_t("仅限中文、字母、数字和下划线,2-20个字"), + (String nameCard) async { + final text = nameCard.trim(); + model.setNameCard(text); + }, theme); }, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/lib/ui/views/TIMUIKitProfile/tim_uikit_profile.dart b/lib/ui/views/TIMUIKitProfile/tim_uikit_profile.dart index 6bf6e98..e8d788e 100644 --- a/lib/ui/views/TIMUIKitProfile/tim_uikit_profile.dart +++ b/lib/ui/views/TIMUIKitProfile/tim_uikit_profile.dart @@ -7,7 +7,6 @@ import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_prof import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart'; import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart'; import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart'; - import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitProfile/profile_widget.dart'; import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitProfile/widget/tim_uikit_profile_widget.dart'; @@ -123,6 +122,14 @@ class _TIMUIKitProfileState extends TIMUIKitState { super.dispose(); } + @override + void didUpdateWidget(covariant TIMUIKitProfile oldWidget) { + super.didUpdateWidget(oldWidget); + if(oldWidget.userID != widget.userID){ + _model.loadData(userID: widget.userID, isNeedConversation: !widget.isSelf); + } + } + final List _defaultWidgetOrder = [ ProfileWidgetEnum.userInfoCard, ProfileWidgetEnum.operationDivider, @@ -189,14 +196,14 @@ class _TIMUIKitProfileState extends TIMUIKitState { void handleTapRemarkBar() { _controller.showTextInputBottomSheet( - context, TIM_t("修改备注名"), TIM_t("仅限中字、字母、数字和下划线"), + context, TIM_t("修改备注名"), TIM_t("仅限汉字、英文、数字和下划线"), (String remark) async { final res = await _controller.updateRemarks(widget.userID, remark); if (res.code == 0) { widget.lifeCycle?.didRemarkUpdated(remark); } - }); + }, theme); } void handleAddFriend() async { diff --git a/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_operation_item.dart b/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_operation_item.dart index b0b4821..c3c932d 100644 --- a/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_operation_item.dart +++ b/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_operation_item.dart @@ -37,38 +37,45 @@ class TIMUIKitOperationItem extends TIMUIKitStatelessWidget { final TUITheme theme = value.theme; return Container( - padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), margin: const EdgeInsets.only(bottom: 1), color: Colors.white, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( - child: Container( - margin: const EdgeInsets.only(right: 22), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(operationName), - if (operationDescription != null) - Text( - operationDescription!, - style: - TextStyle(color: theme.weakTextColor, fontSize: 12), - ) - ], - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(operationName), + if (operationDescription != null) + Text( + operationDescription!, + style: + TextStyle(color: theme.weakTextColor, fontSize: 12), + ) + ], ), ), type == "switch" - ? CupertinoSwitch( - value: operationValue ?? false, - onChanged: onSwitchChange, - activeColor: theme.primaryColor, + ? Transform.scale( + scale: 0.8, + child: CupertinoSwitch( + value: operationValue ?? false, + onChanged: onSwitchChange, + activeColor: theme.primaryColor, + ), ) : Row( mainAxisAlignment: MainAxisAlignment.end, children: [ + Transform.scale( + scale: 0, + child: CupertinoSwitch( + value: false, + onChanged: onSwitchChange, + ), + ), ConstrainedBox( constraints: BoxConstraints( maxWidth: MediaQuery.of(context).size.width / 1.6, diff --git a/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_profile_userinfo_card.dart b/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_profile_userinfo_card.dart index 78bf76a..3feccbf 100644 --- a/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_profile_userinfo_card.dart +++ b/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_profile_userinfo_card.dart @@ -45,6 +45,7 @@ class TIMUIKitProfileUserInfoCard extends TIMUIKitStatelessWidget { height: 48, child: Avatar( faceUrl: faceUrl, + isShowBigWhenClick: true, showName: showName ?? "", type: 1, ), @@ -66,9 +67,17 @@ class TIMUIKitProfileUserInfoCard extends TIMUIKitStatelessWidget { ), Container( margin: const EdgeInsets.symmetric(vertical: 4), - child: Text( - "ID: ${userInfo?.userID ?? ""}", - style: TextStyle(fontSize: 13, color: theme.weakTextColor), + child: Row( + children: [ + Text( + "ID: ", + style: TextStyle(fontSize: 13, color: theme.weakTextColor), + ), + SelectableText( + userInfo?.userID ?? "", + style: TextStyle(fontSize: 13, color: theme.weakTextColor), + ), + ], ), ), Text(signatureText, diff --git a/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_profile_widget.dart b/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_profile_widget.dart index e92da05..9904853 100644 --- a/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_profile_widget.dart +++ b/lib/ui/views/TIMUIKitProfile/widget/tim_uikit_profile_widget.dart @@ -146,7 +146,7 @@ class TIMUIKitProfileWidget extends TIMUIKitClass { child: TIMUIKitOperationItem( showArrowRightIcon: false, operationName: TIM_t("账号"), - operationRightWidget: Text(userNum), + operationRightWidget: SelectableText(userNum), ), ); } @@ -165,7 +165,7 @@ class TIMUIKitProfileWidget extends TIMUIKitClass { /// gender static Widget genderBar(int gender) { Map genderMap = { - 0: TIM_t("未知"), + 0: TIM_t("未填写"), 1: TIM_t("男"), 2: TIM_t("女"), }; @@ -181,7 +181,7 @@ class TIMUIKitProfileWidget extends TIMUIKitClass { /// gender static Widget genderBarWithArrow(int gender) { Map genderMap = { - 0: TIM_t("未知"), + 0: TIM_t("未填写"), 1: TIM_t("男"), 2: TIM_t("女"), }; @@ -212,7 +212,7 @@ class TIMUIKitProfileWidget extends TIMUIKitClass { child: TIMUIKitOperationItem( showArrowRightIcon: false, operationName: TIM_t("生日"), - operationRightWidget: Text(TIM_t("未知")), + operationRightWidget: Text(TIM_t("未填写")), ), ); } diff --git a/lib/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_indicator.dart b/lib/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_indicator.dart new file mode 100644 index 0000000..c051934 --- /dev/null +++ b/lib/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_indicator.dart @@ -0,0 +1,113 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; +import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart'; +import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart'; +import 'package:tencent_cloud_chat_uikit/ui/widgets/radio_button.dart'; + +enum SearchType { contact, group, history } + +class TIMUIKitSearchIndicator extends TIMUIKitStatelessWidget { + final List typeList; + final ValueChanged> onChange; + + TIMUIKitSearchIndicator( + {required this.typeList, required this.onChange, Key? key}) + : super(key: key); + + final titleMap = { + SearchType.contact: "联系人", + SearchType.group: "群聊", + SearchType.history: "聊天记录" + }; + + Widget renderItemBox( + IconData icon, SearchType item, bool isSelect, TUITheme theme) { + return InkWell( + onTap: () { + if (isSelect) { + typeList.remove(item); + } else { + typeList.add(item); + } + onChange(typeList); + }, + child: Container( + padding: const EdgeInsets.all(6), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Stack( + children: [ + Padding( + padding: const EdgeInsets.all(6), + child: Icon( + icon, + color: theme.weakTextColor, + size: 30, + ), + ), + if (isSelect) + Positioned( + right: 0, + bottom: 0, + child: Container( + height: 16, + width: 16, + decoration: BoxDecoration(shape: BoxShape.circle, color: theme.primaryColor), + child: const Icon( + Icons.check, + size: 8, + color: Colors.white, + ), + )) + ], + ), + const SizedBox(height: 4), + Text( + TIM_t(titleMap[item]!), + style: TextStyle(color: theme.textColor, fontSize: 13), + ) + ], + ), + ), + ); + } + + @override + Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { + final theme = value.theme; + return Container( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Text(TIM_t("搜索指定内容"), + style: TextStyle(color: theme.weakTextColor, fontSize: 12)), + ) + ], + ), + const SizedBox(height: 1), + Divider(thickness: 0.8, color: theme.weakDividerColor), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + renderItemBox(Icons.person, SearchType.contact, + typeList.contains(SearchType.contact), theme), + renderItemBox(Icons.people, SearchType.group, + typeList.contains(SearchType.group), theme), + renderItemBox(Icons.message, SearchType.history, + typeList.contains(SearchType.history), theme), + ], + ) + ], + ), + ); + } +} diff --git a/lib/ui/views/TIMUIKitSearch/tim_uikit_search.dart b/lib/ui/views/TIMUIKitSearch/tim_uikit_search.dart index d259f27..b022e34 100644 --- a/lib/ui/views/TIMUIKitSearch/tim_uikit_search.dart +++ b/lib/ui/views/TIMUIKitSearch/tim_uikit_search.dart @@ -5,6 +5,7 @@ import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_search_view_model.dart'; import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart'; +import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_indicator.dart'; import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/tim_uikit_search_friend.dart'; import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_input.dart'; import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/tim_uikit_search_group.dart'; @@ -51,6 +52,11 @@ class TIMUIKitSearchState extends TIMUIKitState { late TextEditingController textEditingController = TextEditingController(); final model = serviceLocator(); GlobalKey inputTextField = GlobalKey(); + List searchTypes = [ + SearchType.group, + SearchType.contact, + SearchType.history + ]; @override void initState() { @@ -70,12 +76,12 @@ class TIMUIKitSearchState extends TIMUIKitState { value: serviceLocator()) ], builder: (context, w) { - List? friendResultList = - Provider.of(context).friendList; - List? msgList = - Provider.of(context).msgList; - List? groupList = - Provider.of(context).groupList; + List friendResultList = + Provider.of(context).friendList ?? []; + List msgList = + Provider.of(context).msgList ?? []; + List groupList = + Provider.of(context).groupList ?? []; int totalMsgCount = Provider.of(context).totalMsgCount; return GestureDetector( @@ -105,27 +111,45 @@ class TIMUIKitSearchState extends TIMUIKitState { child: SingleChildScrollView( child: Column( children: [ - TIMUIKitSearchFriend( + if (friendResultList.isEmpty || + !(searchTypes.contains(SearchType.contact)) && + (groupList.isEmpty || + !(searchTypes.contains(SearchType.group))) && + (totalMsgCount == 0 || + !(searchTypes.contains(SearchType.history)))) + TIMUIKitSearchIndicator( + typeList: searchTypes, + onChange: (list) { + setState(() { + searchTypes = list; + }); + }, + ), + if (searchTypes.contains(SearchType.contact)) + TIMUIKitSearchFriend( + onTapConversation: widget.onTapConversation, + friendResultList: friendResultList), + if (searchTypes.contains(SearchType.group)) + TIMUIKitSearchGroup( + groupList: groupList, + onTapConversation: widget.onTapConversation), + if (searchTypes.contains(SearchType.history)) + TIMUIKitSearchMsg( onTapConversation: widget.onTapConversation, - friendResultList: friendResultList ?? []), - TIMUIKitSearchGroup( - groupList: groupList ?? [], - onTapConversation: widget.onTapConversation), - TIMUIKitSearchMsg( - onTapConversation: widget.onTapConversation, - keyword: textEditingController.text, - totalMsgCount: totalMsgCount, - msgList: msgList ?? [], - onEnterConversation: - (V2TimConversation conversation, String keyword) { - if (widget.onEnterSearchInConversation != null) { - widget.onEnterSearchInConversation!( - conversation, keyword); - } else if (widget.onEnterConversation != null) { - widget.onEnterConversation!(conversation, keyword); - } - }, - ) + keyword: textEditingController.text, + totalMsgCount: totalMsgCount, + msgList: msgList, + onEnterConversation: + (V2TimConversation conversation, String keyword) { + if (widget.onEnterSearchInConversation != null) { + widget.onEnterSearchInConversation!( + conversation, keyword); + } else if (widget.onEnterConversation != null) { + widget.onEnterConversation!( + conversation, keyword); + } + }, + ) ], ), )) diff --git a/lib/ui/widgets/avatar.dart b/lib/ui/widgets/avatar.dart index ecc7966..32f3316 100644 --- a/lib/ui/widgets/avatar.dart +++ b/lib/ui/widgets/avatar.dart @@ -1,5 +1,6 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; +import 'package:tencent_cloud_chat_uikit/ui/widgets/image_screen.dart'; import 'package:tencent_im_base/tencent_im_base.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart'; import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart'; @@ -9,22 +10,25 @@ import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; class Avatar extends TIMUIKitStatelessWidget { final String faceUrl; final String showName; - final bool isFromLocal; + final bool isFromLocalAsset; final CoreServicesImpl coreService = serviceLocator(); final BorderRadius? borderRadius; final V2TimUserStatus? onlineStatus; final int? type; // 1 c2c 2 group + final bool isShowBigWhenClick; + Avatar( {Key? key, required this.faceUrl, this.onlineStatus, required this.showName, - this.isFromLocal = false, + this.isShowBigWhenClick = false, + this.isFromLocalAsset = false, this.borderRadius, this.type = 1}) : super(key: key); - Widget _getFaceUrlImageWidget(BuildContext context, TUITheme theme) { + Widget getImageWidget(BuildContext context, TUITheme theme) { Widget defaultAvatar() { if (type == 1) { return Image.asset('images/default_c2c_head.png', @@ -37,7 +41,7 @@ class Avatar extends TIMUIKitStatelessWidget { // final emptyAvatarBuilder = coreService.emptyAvatarBuilder; if (faceUrl != "") { - if (isFromLocal) { + if (isFromLocalAsset) { return Image.asset(faceUrl); } return CachedNetworkImage( @@ -45,33 +49,35 @@ class Avatar extends TIMUIKitStatelessWidget { fadeInDuration: const Duration(milliseconds: 0), errorWidget: (BuildContext context, String c, dynamic s) { return defaultAvatar(); - // if (emptyAvatarBuilder != null) { - // return emptyAvatarBuilder(context); - // } - // return Container( - // alignment: Alignment.center, - // decoration: BoxDecoration( - // color: theme.primaryColor, - // ), - // child: Text( - // showName.length <= 2 ? showName : showName.substring(0, 2), - // style: const TextStyle(color: Colors.white, fontSize: 14), - // ), - // ); }, ); } else { return defaultAvatar(); - // return Container( - // alignment: Alignment.center, - // decoration: BoxDecoration( - // color: theme.primaryColor, - // ), - // child: Text( - // showName.length <= 2 ? showName : showName.substring(0, 2), - // style: const TextStyle(color: Colors.white, fontSize: 14), - // ), - // ); + } + } + + ImageProvider getImageProvider() { + ImageProvider defaultAvatar() { + if (type == 1) { + return Image.asset('images/default_c2c_head.png', + package: 'tencent_cloud_chat_uikit') + .image; + } else { + return Image.asset('images/default_group_head.png', + package: 'tencent_cloud_chat_uikit') + .image; + } + } + + if (faceUrl != "") { + if (isFromLocalAsset) { + return Image.asset(faceUrl).image; + } + return CachedNetworkImageProvider( + faceUrl, + ); + } else { + return defaultAvatar(); } } @@ -83,10 +89,30 @@ class Avatar extends TIMUIKitStatelessWidget { fit: StackFit.expand, clipBehavior: Clip.none, children: [ - ClipRRect( - borderRadius: borderRadius ?? BorderRadius.circular(4.8), - child: _getFaceUrlImageWidget(context, theme), - ), + if (isShowBigWhenClick) + GestureDetector( + onTap: () { + Navigator.of(context).push( + PageRouteBuilder( + opaque: false, // set to false + pageBuilder: (_, __, ___) => ImageScreen( + imageProvider: getImageProvider(), heroTag: faceUrl), + ), + ); + }, + child: Hero( + tag: faceUrl, + child: ClipRRect( + borderRadius: borderRadius ?? BorderRadius.circular(4.8), + child: getImageWidget(context, theme), + ), + ), + ), + if (!isShowBigWhenClick) + ClipRRect( + borderRadius: borderRadius ?? BorderRadius.circular(4.8), + child: getImageWidget(context, theme), + ), if (onlineStatus?.statusType != null && onlineStatus?.statusType != 0) Positioned( bottom: -4, @@ -102,8 +128,8 @@ class Avatar extends TIMUIKitStatelessWidget { width: 2.0, ), color: onlineStatus?.statusType == 1 - ? hexToColor("43db2b") - : hexToColor("b3b8ba"), + ? theme.conversationItemOnlineStatusBgColor + : theme.conversationItemOfflineStatusBgColor, ), child: null, ), diff --git a/lib/ui/widgets/image_screen.dart b/lib/ui/widgets/image_screen.dart index b593dc7..1abfe0d 100644 --- a/lib/ui/widgets/image_screen.dart +++ b/lib/ui/widgets/image_screen.dart @@ -3,6 +3,7 @@ import 'dart:math'; import 'package:extended_image/extended_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:loading_animation_widget/loading_animation_widget.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart'; import 'package:tencent_cloud_chat_uikit/ui/widgets/center_loading.dart'; import 'package:tencent_cloud_chat_uikit/ui/widgets/gestured_image.dart'; @@ -15,15 +16,15 @@ class ImageScreen extends StatefulWidget { const ImageScreen( {required this.imageProvider, required this.heroTag, - required this.downloadFn, - required this.messageID, + this.downloadFn, + this.messageID, Key? key}) : super(key: key); final ImageProvider imageProvider; final String heroTag; final String? messageID; - final void Function() downloadFn; + final Future Function()? downloadFn; @override State createState() { @@ -40,9 +41,10 @@ class _ImageScreenState extends TIMUIKitState double currentScale = 1.0; double fittedScale = 1.0; double initialScale = 1.0; + bool isLoading = false; + GlobalKey slidePagekey = GlobalKey(); - GlobalKey extendedImageGestureKey = GlobalKey(); @@ -84,7 +86,9 @@ class _ImageScreenState extends TIMUIKitState constraints: BoxConstraints.expand( height: MediaQuery.of(context).size.height, ), - child: Stack(children: [ + child: Stack( + alignment: Alignment.center, + children: [ Positioned( top: 0, left: 0, @@ -250,19 +254,42 @@ class _ImageScreenState extends TIMUIKitState iconSize: 30, onPressed: close, )), - Positioned( - right: 10, - bottom: 50, - child: IconButton( - icon: Image.asset( - 'images/download.png', - package: 'tencent_cloud_chat_uikit', + if (widget.downloadFn != null) + Positioned( + right: 10, + bottom: 50, + child: IconButton( + icon: Image.asset( + 'images/download.png', + package: 'tencent_cloud_chat_uikit', + ), + iconSize: 30, + onPressed: () async { + setState(() { + isLoading = true; + }); + await widget.downloadFn!(); + Future.delayed(const Duration(milliseconds: 200),(){ + setState(() { + isLoading = false; + }); + }); + }, ), - iconSize: 30, - onPressed: widget.downloadFn, ), - ), CenterLoading(messageID: widget.messageID), + if (isLoading) + Container( + child: LoadingAnimationWidget.staggeredDotsWave( + size: 35, + color: Colors.white, + ), + padding: const EdgeInsets.all(30), + decoration: const BoxDecoration( + color: Color(0xB22b2b2b), + borderRadius: BorderRadius.all(Radius.circular(20)), + ), + ), ])), ); })); diff --git a/lib/ui/widgets/link_preview/widgets/link_text.dart b/lib/ui/widgets/link_preview/widgets/link_text.dart index 1dd63ac..0d304fe 100644 --- a/lib/ui/widgets/link_preview/widgets/link_text.dart +++ b/lib/ui/widgets/link_preview/widgets/link_text.dart @@ -1,3 +1,4 @@ +import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart'; import 'package:tencent_extended_text/extended_text.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; @@ -70,7 +71,7 @@ class LinkText extends TIMStatelessWidget { String _getContentSpan(String text, BuildContext context) { List _contentList = []; - String contentData = ''; + String contentData = PlatformUtils().isWeb ? '\u200B' : ""; Iterable matches = LinkUtils.urlReg.allMatches(text); diff --git a/lib/ui/widgets/radio_button.dart b/lib/ui/widgets/radio_button.dart index f6fec15..30c1055 100644 --- a/lib/ui/widgets/radio_button.dart +++ b/lib/ui/widgets/radio_button.dart @@ -7,10 +7,14 @@ class CheckBoxButton extends TIMUIKitStatelessWidget { final bool isChecked; final Function(bool isChecked)? onChanged; final bool disabled; + final bool onlyShow; + final double? size; CheckBoxButton( {this.disabled = false, Key? key, + this.size, + this.onlyShow = false, required this.isChecked, this.onChanged}) : super(key: key); @@ -31,22 +35,33 @@ class CheckBoxButton extends TIMUIKitStatelessWidget { const BoxDecoration(shape: BoxShape.circle, color: Colors.grey); } return Center( - child: InkWell( - onTap: () { - if (onChanged != null && !disabled) { - onChanged!(!isChecked); - } - }, - child: Container( - height: 22, - width: 22, - decoration: boxDecoration, - child: const Icon( - Icons.check, - size: 11.0, - color: Colors.white, - ), - ), - )); + child: onlyShow + ? Container( + height: size ?? 22, + width: size ?? 22, + decoration: boxDecoration, + child: Icon( + Icons.check, + size: size != null ? (size! / 2) : 11, + color: Colors.white, + ), + ) + : InkWell( + onTap: () { + if (onChanged != null && !disabled) { + onChanged!(!isChecked); + } + }, + child: Container( + height: size ?? 22, + width: size ?? 22, + decoration: boxDecoration, + child: Icon( + Icons.check, + size: size != null ? (size! / 2) : 11, + color: Colors.white, + ), + ), + )); } } diff --git a/lib/ui/widgets/text_input_bottom_sheet.dart b/lib/ui/widgets/text_input_bottom_sheet.dart index 28802d7..6389d76 100644 --- a/lib/ui/widgets/text_input_bottom_sheet.dart +++ b/lib/ui/widgets/text_input_bottom_sheet.dart @@ -3,7 +3,7 @@ import 'package:tencent_im_base/tencent_im_base.dart'; class TextInputBottomSheet { static showTextInputBottomSheet(BuildContext context, String title, - String tips, Function(String text) onSubmitted) { + String tips, Function(String text) onSubmitted, TUITheme theme) { TextEditingController _selectionController = TextEditingController(); showModalBottomSheet( @@ -13,17 +13,21 @@ class TextInputBottomSheet { return SingleChildScrollView( child: Container( padding: EdgeInsets.only( - top: 12, + top: 16, left: 16, right: 16, - bottom: MediaQuery.of(context).viewInsets.bottom, + bottom: MediaQuery.of(context).viewInsets.bottom + 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ - Text(title, - style: const TextStyle( - fontWeight: FontWeight.w500, fontSize: 15)), + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Text(title, + style: const TextStyle( + fontWeight: FontWeight.w500, fontSize: 16)), + ), + Divider(height: 2, color: theme.weakDividerColor), TextField( controller: _selectionController, ), @@ -35,7 +39,8 @@ class TextInputBottomSheet { height: 40, child: Text( tips, - style: const TextStyle(color: Colors.grey), + style: + const TextStyle(color: Colors.grey, fontSize: 12), ), ) ], @@ -61,9 +66,6 @@ class TextInputBottomSheet { }, child: Text(TIM_t("确定"))), ), - const SizedBox( - height: 40, - ) ], ), )); diff --git a/lib/ui/widgets/unread_message.dart b/lib/ui/widgets/unread_message.dart index 3fa51c8..603eeb9 100644 --- a/lib/ui/widgets/unread_message.dart +++ b/lib/ui/widgets/unread_message.dart @@ -30,12 +30,18 @@ class UnreadMessage extends TIMUIKitStatelessWidget { alignment: Alignment.center, decoration: BoxDecoration( shape: BoxShape.circle, - color: theme.cautionColor ?? CommonColor.cautionColor, + color: theme.conversationItemUnreadCountBgColor ?? + CommonColor.cautionColor, ), child: unreadText != "0" ? Center( - child: Text(unreadText, - style: TextStyle(color: Colors.white, fontSize: fontSize)), + child: Text( + unreadText, + style: TextStyle( + color: theme.conversationItemUnreadCountTextColor, + fontSize: fontSize, + ), + ), ) : null, ); diff --git a/lib/ui/widgets/video_custom_control.dart b/lib/ui/widgets/video_custom_control.dart index 82f23f6..db4ce5c 100644 --- a/lib/ui/widgets/video_custom_control.dart +++ b/lib/ui/widgets/video_custom_control.dart @@ -7,6 +7,7 @@ import 'package:chewie/src/helpers/utils.dart'; import 'package:chewie/src/animated_play_pause.dart'; import 'package:chewie/src/material/material_progress_bar.dart'; import 'package:flutter/material.dart'; +import 'package:loading_animation_widget/loading_animation_widget.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart'; @@ -18,7 +19,7 @@ import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart'; class VideoCustomControls extends StatefulWidget { const VideoCustomControls({required this.downloadFn, Key? key}) : super(key: key); - final void Function() downloadFn; + final Future Function() downloadFn; @override State createState() { @@ -35,6 +36,7 @@ class _VideoCustomControlsState extends TIMUIKitState Timer? _showAfterExpandCollapseTimer; bool _dragging = false; bool _displayTapped = false; + bool isLoading = false; final barHeight = 48.0; final marginSize = 5.0; @@ -72,7 +74,7 @@ class _VideoCustomControlsState extends TIMUIKitState child: AbsorbPointer( absorbing: _hideStuff, child: Stack( - fit: StackFit.expand, + alignment: Alignment.center, children: [ if (_latestValue.isBuffering) const Center( @@ -86,7 +88,19 @@ class _VideoCustomControlsState extends TIMUIKitState _buildVideoControlBar(context), _buildBottomBar() ]), - ) + ), + if (isLoading) + Container( + child: LoadingAnimationWidget.staggeredDotsWave( + size: 35, + color: Colors.white, + ), + padding: const EdgeInsets.all(30), + decoration: const BoxDecoration( + color: Color(0xB22b2b2b), + borderRadius: BorderRadius.all(Radius.circular(20)), + ), + ), ], ), ), @@ -149,7 +163,17 @@ class _VideoCustomControlsState extends TIMUIKitState package: 'tencent_cloud_chat_uikit', ), iconSize: 30, - onPressed: widget.downloadFn, + onPressed: () async { + setState(() { + isLoading = true; + }); + await widget.downloadFn(); + Future.delayed(const Duration(milliseconds: 200),(){ + setState(() { + isLoading = false; + }); + }); + }, ) ], ), diff --git a/lib/ui/widgets/video_screen.dart b/lib/ui/widgets/video_screen.dart index a7fad16..cfd5d33 100644 --- a/lib/ui/widgets/video_screen.dart +++ b/lib/ui/widgets/video_screen.dart @@ -59,7 +59,11 @@ class _VideoScreenState extends TIMUIKitState { } //保存网络视频到本地 - _saveNetworkVideo(context, String videoUrl, {bool isAsset = true}) async { + Future _saveNetworkVideo( + context, + String videoUrl, { + bool isAsset = true, + }) async { if (PlatformUtils().isWeb) { RegExp exp = RegExp(r"((\.){1}[^?]{2,4})"); String? suffix = exp.allMatches(videoUrl).last.group(0); @@ -83,12 +87,16 @@ class _VideoScreenState extends TIMUIKitState { } if (PlatformUtils().isIOS) { if (!await Permissions.checkPermission( - context, Permission.photosAddOnly.value)) { + context, + Permission.photosAddOnly.value, + )) { return; } } else { if (!await Permissions.checkPermission( - context, Permission.storage.value)) { + context, + Permission.storage.value, + )) { return; } } @@ -172,33 +180,44 @@ class _VideoScreenState extends TIMUIKitState { infoCode: 6660403)); } } + return; } - void _saveVideo() { + Future _saveVideo() async { if (PlatformUtils().isWeb) { - _saveNetworkVideo(context, widget.videoElement.videoPath!, - isAsset: true); - return; + return await _saveNetworkVideo( + context, + widget.videoElement.videoPath!, + isAsset: true, + ); } if (widget.videoElement.videoPath != '' && widget.videoElement.videoPath != null) { File f = File(widget.videoElement.videoPath!); if (f.existsSync()) { - _saveNetworkVideo(context, widget.videoElement.videoPath!, - isAsset: true); - return; + return await _saveNetworkVideo( + context, + widget.videoElement.videoPath!, + isAsset: true, + ); } } if (widget.videoElement.localVideoUrl != '' && widget.videoElement.localVideoUrl != null) { File f = File(widget.videoElement.localVideoUrl!); if (f.existsSync()) { - _saveNetworkVideo(context, widget.videoElement.localVideoUrl!, - isAsset: true); - return; + return await _saveNetworkVideo( + context, + widget.videoElement.localVideoUrl!, + isAsset: true, + ); } } - _saveNetworkVideo(context, widget.videoElement.videoUrl!, isAsset: false); + return await _saveNetworkVideo( + context, + widget.videoElement.videoUrl!, + isAsset: false, + ); } double getVideoHeight() { @@ -293,7 +312,9 @@ class _VideoScreenState extends TIMUIKitState { showControlsOnInitialize: false, allowPlaybackSpeedChanging: false, aspectRatio: w == 0 || h == 0 ? null : w / h, - customControls: VideoCustomControls(downloadFn: _saveVideo)); + customControls: VideoCustomControls(downloadFn: () async{ + return await _saveVideo(); + })); setState(() { videoPlayerController = player; chewieController = controller; diff --git a/pubspec.lock b/pubspec.lock index 3cb594a..7cbf479 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -253,13 +253,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.2.4" - dio: - dependency: "direct main" - description: - name: dio - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.6" disk_space: dependency: "direct main" description: @@ -506,13 +499,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.2" - i18n: - dependency: "direct main" - description: - name: i18n - url: "https://pub.dartlang.org" - source: hosted - version: "3.4.1" image_gallery_saver: dependency: "direct main" description: @@ -898,13 +884,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.1" - quick_log: - dependency: transitive - description: - name: quick_log - url: "https://pub.dartlang.org" - source: hosted - version: "5.2.1" quiver: dependency: transitive description: @@ -1003,6 +982,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.3" + shell: + dependency: transitive + description: + name: shell + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" sky_engine: dependency: transitive description: flutter @@ -1077,7 +1063,7 @@ packages: name: tencent_cloud_chat_sdk url: "https://pub.dartlang.org" source: hosted - version: "5.0.4" + version: "5.0.6" tencent_extended_text: dependency: "direct main" description: @@ -1105,14 +1091,21 @@ packages: name: tencent_im_base url: "https://pub.dartlang.org" source: hosted - version: "1.0.7" + version: "1.0.14" tencent_im_sdk_plugin_platform_interface: dependency: transitive description: name: tencent_im_sdk_plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "0.3.9" + version: "0.3.10" + tencent_keyboard_visibility: + dependency: "direct main" + description: + name: tencent_keyboard_visibility + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" tencent_open_file: dependency: "direct main" description: @@ -1133,7 +1126,7 @@ packages: name: tencent_wechat_camera_picker url: "https://pub.dartlang.org" source: hosted - version: "3.6.2+5" + version: "3.6.5" term_glyph: dependency: transitive description: @@ -1141,6 +1134,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.1" + tim_ui_kit_sticker_plugin: + dependency: "direct main" + description: + name: tim_ui_kit_sticker_plugin + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" timing: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 1f4a71b..c1bbc7e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: tencent_cloud_chat_uikit description: UI components library and basic chat business logic for Tencent Cloud Chat service, helping you build In-APP Chat module easily. -version: 1.0.1 +version: 1.1.0 homepage: https://www.tencentcloud.com/products/im?from=pub repository: https://github.com/TencentCloud/tc-chat-uikit-flutter documentation: https://comm.qq.com/im/doc/flutter/en/TUIKit/readme.html @@ -39,17 +39,15 @@ dependencies: image_gallery_saver: ^1.7.1 photo_view: ^0.14.0 fluttertoast: ^8.0.8 - dio: ^4.0.4 path_provider: ^2.0.8 characters: ^1.1.0 - i18n: ^3.4.1 cached_network_image: ^3.2.0 shared_preferences: ^2.0.13 json_annotation: ^4.4.0 js: ^0.6.3 scroll_to_index: ^2.1.1 wechat_assets_picker: ^7.2.0 - tencent_wechat_camera_picker: ^3.6.2+5 + tencent_wechat_camera_picker: ^3.6.5 flutter_easyrefresh: ^2.2.1 flutter_spinkit: ^5.1.0 extended_image: ^6.0.2+1 @@ -64,7 +62,7 @@ dependencies: url_launcher: ^6.1.4 universal_html: ^2.0.8 link_preview_generator: ^1.2.0 - tencent_im_base: ^1.0.7 + tencent_im_base: ^1.0.14 disk_space: ^0.2.1 http: ^0.13.5 crypto: ^3.0.2 @@ -72,6 +70,8 @@ dependencies: flutter_image_compress: ^1.1.3 uuid: ^3.0.6 tencent_open_file: ^4.0.9 + tencent_keyboard_visibility: ^1.0.1 + tim_ui_kit_sticker_plugin: ^1.1.1 dev_dependencies: flutter_lints: ^1.0.0