Update Flutter TUIKit to 1.3.0

This commit is contained in:
anonymous 2023-01-11 15:34:12 +08:00
parent cf7633aa02
commit 1d02ac67c2
14 changed files with 148 additions and 115 deletions

View File

@ -1,3 +1,7 @@
## 1.3.0
* Fix: Group tips not shows the nickname or remarks when transferring group owner.
* Optimize: Remove the confirmation pop-up before opening the file.
## 1.2.0
* Fix: The issue of input area not showing, when switching from recording to keyboard, on `TIMUIKitChat`.

View File

@ -57,8 +57,8 @@
<p align="center">
More languages:
<a href="https://tencentcloud.com/document/product/269/70746?from=pub">简体中文-快速入门</a>
<a href="https://github.com/TencentCloud/tc-chat-uikit-flutter/README_ZH.md?from=pub">简体中文-README</a>
<a href="https://cloud.tencent.com/document/product/269/70747">简体中文-TUIKit介绍</a>
<a href="https://cloud.tencent.com/document/product/269/70746">简体中文-快速集成</a>
</p>
<br>
@ -79,16 +79,7 @@ You can experience our Chat and Voice/Video Call modules via the following demos
**Those following versions of demo has been build by the same Flutter project with our SDKs and extensions.**
<table style="text-align:center; vertical-align:middle; max-width: 800px">
<tr>
<th style="text-align:center;">Mobile APP</th>
<th style="text-align:center;">WEB - H5</th>
</tr>
<tr>
<td><div style="display: flex; justify-content: center; align-items: center; flex-direction: column; padding-top: 10px">[Recommend] iOS/Android APP<img style="max-width:200px; margin: 20px 0 20px 0" src="https://qcloudimg.tencent-cloud.cn/raw/ca2aaff551410c74fce48008c771b9f6.png"/></div></td>
<td><div style="display: flex; justify-content: center; align-items: center; flex-direction: column; padding-top: 10px">Scan for the Web DEMO<img style="max-width:200px; margin: 20px 0 20px 0" src="https://qcloudimg.tencent-cloud.cn/raw/3c79e8bb16dd0eeab35e894a690e0444.png"/></div></td>
</tr>
</table>
![](https://qcloudimg.tencent-cloud.cn/raw/89234f5032d4f6f8d89a8b439ca97ca2.png)
**Also, taking a look of the screenshots of TUIKit from [here](https://www.tencentcloud.com/document/product/1047/50059?from=pub) are suggested.**

View File

@ -970,7 +970,7 @@ packages:
path: ".."
relative: true
source: path
version: "1.2.0"
version: "1.3.0"
tencent_extended_text:
dependency: transitive
description:

View File

@ -3,5 +3,7 @@ class TencentUtils{
return text != null && text.isNotEmpty;
}
static String? checkString(String? text){
return (text != null && text.isEmpty) ? null : text;
}
}

View File

@ -2,12 +2,13 @@
import 'dart:convert';
import 'package:collection/collection.dart';
import 'package:flutter/cupertino.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/common_utils.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/ui/constants/history_message_constant.dart';
import 'package:tencent_cloud_chat_uikit/ui/constants/time.dart';
class MessageUtils {
// CallingData的方式和Trtc的方法一致
static isCallingData(String data) {
@ -36,7 +37,8 @@ class MessageUtils {
return false;
}
static String _getGroupChangeType(V2TimGroupChangeInfo info) {
static Future<String> _getGroupChangeType(V2TimGroupChangeInfo info,
List<V2TimGroupMemberFullInfo?> groupMemberList) async {
int? type = info.type;
var value = info.value;
String s = TIM_t('群资料信息');
@ -58,6 +60,25 @@ class MessageUtils {
break;
case GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_OWNER:
s = TIM_t("群主");
final V2TimGroupMemberFullInfo? groupMemberInfo = groupMemberList
.firstWhereOrNull((element) => element?.userID == value);
if (groupMemberInfo != null) {
value = TencentUtils.checkString(groupMemberInfo.friendRemark) ??
TencentUtils.checkString(groupMemberInfo.nameCard) ??
TencentUtils.checkString(groupMemberInfo.nickName) ??
TencentUtils.checkString(groupMemberInfo.userID);
} else {
final res = await TencentImSDKPlugin.v2TIMManager
.getUsersInfo(userIDList: [value ?? ""]);
if (res.code == 0) {
final List<V2TimUserFullInfo> data = res.data ?? [];
if (data.isNotEmpty) {
final firstPerson = data[0];
value = TencentUtils.checkString(firstPerson.nickName) ??
TencentUtils.checkString(firstPerson.userID);
}
}
}
break;
case GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_SHUT_UP_ALL:
s = TIM_t("全员禁言状态");
@ -73,18 +94,16 @@ class MessageUtils {
final String option8 = s;
if (value != null && value.isNotEmpty) {
return TIM_t_para("{{option8}}为 ", "$option8为 ")(option8: option8) +
' $value';
value;
} else {
return option8;
}
}
static String? _getOpUserNick(V2TimGroupMemberInfo opUser) {
return opUser.friendRemark == null || opUser.friendRemark == ''
? opUser.nickName == null || opUser.nickName == ''
? opUser.userID
: opUser.nickName
: opUser.friendRemark;
return TencentUtils.checkString(opUser.friendRemark) ??
TencentUtils.checkString(opUser.nickName) ??
TencentUtils.checkString(opUser.userID);
}
static String? _getMemberNickName(V2TimGroupMemberInfo e) {
@ -104,7 +123,9 @@ class MessageUtils {
}
}
static String groupTipsMessageAbstract(V2TimGroupTipsElem groupTipsElem) {
static Future<String> groupTipsMessageAbstract(
V2TimGroupTipsElem groupTipsElem,
List<V2TimGroupMemberFullInfo?> groupMemberList) async {
String displayMessage;
final operationType = groupTipsElem.type;
final operationMember = groupTipsElem.opMember;
@ -112,10 +133,14 @@ class MessageUtils {
final opUserNickName = _getOpUserNick(operationMember);
switch (operationType) {
case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_GROUP_INFO_CHANGE:
final groupChangeInfoList = groupTipsElem.groupChangeInfoList;
final String? option7 = opUserNickName ?? "";
var changedInfoString =
groupChangeInfoList!.map((e) => _getGroupChangeType(e!)).join("");
final groupChangeInfoList = groupTipsElem.groupChangeInfoList ?? [];
String changedInfoString = "";
for (V2TimGroupChangeInfo? element in groupChangeInfoList) {
final newText = await _getGroupChangeType(element!, groupMemberList);
changedInfoString +=
(changedInfoString.isEmpty ? "" : " / ") + newText;
}
if (changedInfoString.isEmpty) {
changedInfoString = TIM_t("群资料");
}
@ -220,7 +245,8 @@ class MessageUtils {
margin: const EdgeInsets.symmetric(vertical: 10), child: child);
}
static String getAbstractMessage(V2TimMessage message) {
static Future<String> getAbstractMessage(V2TimMessage message,
List<V2TimGroupMemberFullInfo?> groupMemberList) async {
final msgType = message.elemType;
switch (msgType) {
case MessageElemType.V2TIM_ELEM_TYPE_CUSTOM:
@ -236,7 +262,8 @@ class MessageUtils {
return TIM_t_para("[文件] {{option2}}", "[文件] $option2")(
option2: option2);
case MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS:
return MessageUtils.groupTipsMessageAbstract(message.groupTipsElem!);
return await MessageUtils.groupTipsMessageAbstract(
message.groupTipsElem!, groupMemberList);
case MessageElemType.V2TIM_ELEM_TYPE_IMAGE:
return TIM_t("[图片]");
case MessageElemType.V2TIM_ELEM_TYPE_VIDEO:

View File

@ -534,12 +534,12 @@ class _TIMUIKItHistoryMessageListItemState
}
}
Widget _groupTipsMessageBuilder() {
Widget _groupTipsMessageBuilder(TUIChatSeparateViewModel model) {
final messageItem = widget.message;
return Container(
padding: const EdgeInsets.only(bottom: 20),
child:
TIMUIKitGroupTipsElem(groupTipsElem: messageItem.groupTipsElem!));
TIMUIKitGroupTipsElem(groupTipsElem: messageItem.groupTipsElem!, groupMemberList: model.groupMemberList ?? []));
}
Widget _selfRevokeEditMessageBuilder(theme, model) {
@ -834,9 +834,9 @@ class _TIMUIKItHistoryMessageListItemState
(model.jumpMsgID == message.msgID),
clearJump,
);
return groupTipsMessage ?? _groupTipsMessageBuilder();
return groupTipsMessage ?? _groupTipsMessageBuilder(model);
}
return _groupTipsMessageBuilder();
return _groupTipsMessageBuilder(model);
}
if (isRevokedMsg) {

View File

@ -3,11 +3,9 @@
import 'dart:io';
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/permission.dart';
import 'package:tencent_open_file/tencent_open_file.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
@ -53,42 +51,6 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
bool isDownloading = false;
final TUIChatGlobalModel model = serviceLocator<TUIChatGlobalModel>();
Future<bool?> showOpenFileConfirmDialog(
BuildContext context, String path, TUITheme? theme) async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String option2 = packageInfo.appName;
return showDialog<bool>(
context: context,
builder: (context) {
return CupertinoAlertDialog(
title: Text(widget.fileElem!.fileName!),
content: Text(TIM_t_para("“{{option2}}”暂不可以打开此类文件,你可以使用其他应用打开并预览",
"$option2”暂不可以打开此类文件,你可以使用其他应用打开并预览")(option2: option2)),
actions: <Widget>[
CupertinoDialogAction(
child: Text(TIM_t("取消"),
style: TextStyle(color: theme?.secondaryColor)),
onPressed: () => Navigator.of(context).pop(), //
),
CupertinoDialogAction(
child: Text(TIM_t("用其他应用打开"),
style: TextStyle(color: theme?.primaryColor)),
onPressed: () {
//true
Navigator.of(context).pop();
try {
OpenFile.open(path);
} catch (e) {
print(e);
}
},
),
],
);
},
);
}
@override
void initState() {
super.initState();
@ -177,7 +139,11 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
context, Permission.storage.value, theme)) {
return;
}
showOpenFileConfirmDialog(context, filePath, theme);
try {
OpenFile.open(filePath);
} catch (e) {
print(e);
}
}
@override

View File

@ -1,22 +1,40 @@
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.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/ui/utils/message.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
class TIMUIKitGroupTipsElem extends TIMUIKitStatelessWidget {
class TIMUIKitGroupTipsElem extends StatefulWidget {
final V2TimGroupTipsElem groupTipsElem;
final List<V2TimGroupMemberFullInfo?> groupMemberList;
TIMUIKitGroupTipsElem({Key? key, required this.groupTipsElem})
const TIMUIKitGroupTipsElem({Key? key, required this.groupMemberList, required this.groupTipsElem})
: super(key: key);
@override
State<TIMUIKitGroupTipsElem> createState() => _TIMUIKitGroupTipsElemState();
}
class _TIMUIKitGroupTipsElemState extends TIMUIKitState<TIMUIKitGroupTipsElem> {
String groupTipsAbstractText = "";
@override
void initState() {
super.initState();
getText();
}
void getText() async {
setState(() async {
groupTipsAbstractText =
await MessageUtils.groupTipsMessageAbstract(widget.groupTipsElem, widget.groupMemberList);
});
}
@override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
final TUITheme theme = value.theme;
final groupTipsAbstractText =
MessageUtils.groupTipsMessageAbstract(groupTipsElem);
return MessageUtils.wrapMessageTips(
Text(

View File

@ -1,10 +1,8 @@
import 'dart:async';
import 'dart:math';
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';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
@ -185,14 +183,14 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
return const SizedBox(height: 0);
}
void addStickerToText(String sticker){
void addStickerToText(String sticker) {
final oldText = textEditingController.text;
if(currentCursor != null && currentCursor! > -1){
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{
} else {
textEditingController.text = "$oldText$sticker";
}
}
@ -281,7 +279,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
final haveRepliedMessage = repliedMessage != null;
if (haveRepliedMessage) {
final text =
"${MessageUtils.getDisplayName(widget.model.repliedMessage!)}:${widget.model.abstractMessageBuilder != null ? widget.model.abstractMessageBuilder!(widget.model.repliedMessage!) : MessageUtils.getAbstractMessage(widget.model.repliedMessage!)}";
"${MessageUtils.getDisplayName(widget.model.repliedMessage!)}:${widget.model.abstractMessageBuilder != null ? widget.model.abstractMessageBuilder!(widget.model.repliedMessage!) : MessageUtils.getAbstractMessage(widget.model.repliedMessage!, widget.model.groupMemberList ?? [])}";
return Container(
color: widget.backgroundColor ?? hexToColor("f5f5f6"),
alignment: Alignment.centerLeft,
@ -865,7 +863,8 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
isDense: true,
hintText: widget.hintText ?? ''),
controller: textEditingController,
specialTextSpanBuilder: PlatformUtils().isWeb
specialTextSpanBuilder: PlatformUtils()
.isWeb
? null
: DefaultSpecialTextSpanBuilder(
isUseDefaultEmoji:
@ -873,8 +872,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
customEmojiStickerList: widget
.customEmojiStickerList,
showAtBackground: true,
)
),
)),
onChanged: (bool visibility) {
if (showKeyboard != visibility &&
visibility == false) {

View File

@ -1,40 +1,69 @@
// ignore_for_file: unrelated_type_equality_checks
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/base_widgets/tim_ui_kit_state.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/message.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
class TIMUIKitLastMsg extends TIMUIKitStatelessWidget {
class TIMUIKitLastMsg extends StatefulWidget {
final V2TimMessage? lastMsg;
final List<V2TimGroupAtInfo?> groupAtInfoList;
final BuildContext context;
TIMUIKitLastMsg(
const TIMUIKitLastMsg(
{Key? key,
this.lastMsg,
required this.groupAtInfoList,
required this.context})
: super(key: key);
String _getMsgElem() {
final isRevokedMessage = lastMsg!.status == 6;
if (isRevokedMessage) {
final isSelf = lastMsg!.isSelf ?? false;
final option1 =
isSelf ? TIM_t("") : lastMsg!.nickName ?? lastMsg?.sender;
return TIM_t_para("{{option1}}撤回了一条消息", "$option1撤回了一条消息")(
option1: option1);
}
return _getLastMsgShowText(lastMsg, context);
@override
State<TIMUIKitLastMsg> createState() => _TIMUIKitLastMsgState();
}
class _TIMUIKitLastMsgState extends TIMUIKitState<TIMUIKitLastMsg> {
String groupTipsAbstractText = "";
@override
void initState() {
super.initState();
_getMsgElem();
}
String _getLastMsgShowText(V2TimMessage? message, BuildContext context) {
@override
void didUpdateWidget(covariant TIMUIKitLastMsg oldWidget) {
super.didUpdateWidget(oldWidget);
if ((oldWidget.lastMsg?.msgID != widget.lastMsg?.msgID) ||
(oldWidget.lastMsg?.id != widget.lastMsg?.id)) {
_getMsgElem();
}
}
void _getMsgElem() async {
final isRevokedMessage = widget.lastMsg!.status == 6;
if (isRevokedMessage) {
final isSelf = widget.lastMsg!.isSelf ?? false;
final option1 = isSelf
? TIM_t("")
: widget.lastMsg!.nickName ?? widget.lastMsg?.sender;
setState(() {
groupTipsAbstractText = TIM_t_para(
"{{option1}}撤回了一条消息", "$option1撤回了一条消息")(option1: option1);
});
} else {
setState(() async {
groupTipsAbstractText =
await _getLastMsgShowText(widget.lastMsg, widget.context);
});
}
}
Future<String> _getLastMsgShowText(
V2TimMessage? message, BuildContext context) async {
final msgType = message!.elemType;
switch (msgType) {
case MessageElemType.V2TIM_ELEM_TYPE_CUSTOM:
@ -42,15 +71,16 @@ class TIMUIKitLastMsg extends TIMUIKitStatelessWidget {
case MessageElemType.V2TIM_ELEM_TYPE_SOUND:
return TIM_t("[语音]");
case MessageElemType.V2TIM_ELEM_TYPE_TEXT:
return lastMsg?.textElem?.text ?? "";
return widget.lastMsg?.textElem?.text ?? "";
case MessageElemType.V2TIM_ELEM_TYPE_FACE:
return TIM_t("[表情]");
case MessageElemType.V2TIM_ELEM_TYPE_FILE:
final option1 = lastMsg!.fileElem!.fileName;
final option1 = widget.lastMsg!.fileElem!.fileName;
return TIM_t_para("[文件] {{option1}}", "[文件] $option1")(
option1: option1);
case MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS:
return MessageUtils.groupTipsMessageAbstract(lastMsg!.groupTipsElem!);
return await MessageUtils.groupTipsMessageAbstract(
widget.lastMsg!.groupTipsElem!, []);
case MessageElemType.V2TIM_ELEM_TYPE_IMAGE:
return TIM_t("[图片]");
case MessageElemType.V2TIM_ELEM_TYPE_VIDEO:
@ -65,7 +95,7 @@ class TIMUIKitLastMsg extends TIMUIKitStatelessWidget {
}
Icon? _getIconByMsgStatus(BuildContext context) {
final msgStatus = lastMsg!.status;
final msgStatus = widget.lastMsg!.status;
final theme = Provider.of<TUIThemeViewModel>(context).theme;
if (msgStatus == MessageStatus.V2TIM_MSG_STATUS_SEND_FAIL) {
return Icon(Icons.error, color: theme.cautionColor, size: 16);
@ -78,7 +108,7 @@ class TIMUIKitLastMsg extends TIMUIKitStatelessWidget {
String _getAtMessage() {
String msg = "";
for (var item in groupAtInfoList) {
for (var item in widget.groupAtInfoList) {
if (item!.atType == 1) {
msg = TIM_t("[有人@我] ");
} else {
@ -98,12 +128,12 @@ class TIMUIKitLastMsg extends TIMUIKitStatelessWidget {
margin: const EdgeInsets.only(right: 2),
child: icon,
),
if (groupAtInfoList.isNotEmpty)
if (widget.groupAtInfoList.isNotEmpty)
Text(_getAtMessage(),
style: TextStyle(color: theme.cautionColor, fontSize: 14)),
Expanded(
child: Text(
_getMsgElem(),
groupTipsAbstractText,
softWrap: true,
maxLines: 1,
overflow: TextOverflow.ellipsis,

View File

@ -1,6 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_group_profile_model.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroupProfile/widgets/tim_ui_group_search_msg.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_add_opt.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_detail_card.dart';

View File

@ -1,9 +1,7 @@
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 }

View File

@ -52,7 +52,7 @@ class _ForwardMessageScreenState extends TIMUIKitState<ForwardMessageScreen> {
final sender = (e.nickName != null && e.nickName!.isNotEmpty)
? e.nickName
: e.sender;
return "$sender: ${model.abstractMessageBuilder != null ? model.abstractMessageBuilder!(e) : MessageUtils.getAbstractMessage(e)}";
return "$sender: ${model.abstractMessageBuilder != null ? model.abstractMessageBuilder!(e) : MessageUtils.getAbstractMessage(e, [])}";
}).toList();
}

View File

@ -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.2.0
version: 1.3.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