feat: Upgrade to UIKit 2.3.2
This commit is contained in:
parent
c28e1e9529
commit
038a3d483d
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -1,3 +1,14 @@
|
|||
# 2.3.2
|
||||
|
||||
## Improvements
|
||||
|
||||
* Enhanced message list performance.
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Fixed an issue that prevented the group member addition/removal modal from closing.
|
||||
* Addressed several other bugs.
|
||||
|
||||
# 2.3.1
|
||||
|
||||
## Bug Fixes
|
||||
|
|
|
|||
|
|
@ -706,7 +706,6 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
|
|||
|
||||
Future<void> onMessageDownloadProgressCallback(
|
||||
V2TimMessageDownloadProgress messageProgress) async {
|
||||
outputLogger.i(messageProgress.toJson());
|
||||
final currentProgress = getMessageProgress(messageProgress.msgID);
|
||||
|
||||
if (messageProgress.isFinish && currentProgress < 100) {
|
||||
|
|
@ -1120,9 +1119,7 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
|
|||
listWithTimestamp.add(V2TimMessage.fromJson(item.toJson()));
|
||||
}
|
||||
}
|
||||
final returnValue = listWithTimestamp.reversed.toList();
|
||||
outputLogger.i(returnValue.map((e) => e.toJson()).toList().toString());
|
||||
return returnValue;
|
||||
return listWithTimestamp.reversed.toList();
|
||||
}
|
||||
|
||||
HistoryMessagePosition getMessageListPosition(String? conversationID) {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class TUIKitOutput extends LogOutput {
|
|||
|
||||
Future<String> getPlatformLogPath({String? path}) async {
|
||||
if (TencentUtils.checkString(path) != null) {
|
||||
outputLogger.i("The path to local log: $path");
|
||||
print("The path to local log: $path");
|
||||
return path!;
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ class TUIKitOutput extends LogOutput {
|
|||
"${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}";
|
||||
final logPath = p.join(documentsDirectoryPath, "Documents", ".TencentCloudChat",
|
||||
pkgName, "uikit_log", 'Flutter-TUIKit-$timeName.log');
|
||||
outputLogger.i("The path to local log: $logPath");
|
||||
print("The path to local log: $logPath");
|
||||
|
||||
return logPath;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,15 +7,17 @@ import 'package:provider/provider.dart';
|
|||
import 'package:scroll_to_index/scroll_to_index.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';
|
||||
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/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/utils/logger.dart';
|
||||
// ignore: unused_import
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/optimize_utils.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list_config.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKItMessageList/utils.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/widgets/keepalive_wrapper.dart';
|
||||
import 'package:tencent_im_base/tencent_im_base.dart';
|
||||
|
||||
import 'TIMUIKitTongue/tim_uikit_chat_history_message_list_tongue.dart';
|
||||
import 'TIMUIKitTongue/tim_uikit_chat_history_message_list_tongue_container.dart';
|
||||
|
||||
|
|
@ -73,8 +75,7 @@ class TIMUIKitHistoryMessageList extends StatefulWidget {
|
|||
final V2TimMessage? initFindingMsg;
|
||||
|
||||
/// use for load more message
|
||||
final Future<void> Function(String?, LoadDirection direction, [int?])
|
||||
onLoadMore;
|
||||
final Future<void> Function(String?, LoadDirection direction, [int?]) onLoadMore;
|
||||
|
||||
/// configuration for list view
|
||||
final TIMUIKitHistoryMessageListConfig? mainHistoryListConfig;
|
||||
|
|
@ -104,8 +105,7 @@ class TIMUIKitHistoryMessageList extends StatefulWidget {
|
|||
State<StatefulWidget> createState() => _TIMUIKitHistoryMessageListState();
|
||||
}
|
||||
|
||||
class _TIMUIKitHistoryMessageListState
|
||||
extends TIMUIKitState<TIMUIKitHistoryMessageList> {
|
||||
class _TIMUIKitHistoryMessageListState extends TIMUIKitState<TIMUIKitHistoryMessageList> {
|
||||
V2TimMessage? findingMsg;
|
||||
String findingSeq = "";
|
||||
late TIMUIKitHistoryMessageListController _controller;
|
||||
|
|
@ -116,8 +116,7 @@ class _TIMUIKitHistoryMessageListState
|
|||
void initState() {
|
||||
super.initState();
|
||||
_controller = widget.controller ?? TIMUIKitHistoryMessageListController();
|
||||
_autoScrollController =
|
||||
_controller.scrollController ?? AutoScrollController();
|
||||
_autoScrollController = _controller.scrollController ?? AutoScrollController();
|
||||
_controller.addListener(_controllerListener);
|
||||
initFinding();
|
||||
}
|
||||
|
|
@ -163,18 +162,14 @@ class _TIMUIKitHistoryMessageListState
|
|||
findingMsg = null;
|
||||
findingSeq = "";
|
||||
loadingPlace = LoadingPlace.none;
|
||||
onTIMCallback(TIMCallback(
|
||||
type: TIMCallbackType.INFO,
|
||||
infoRecommendText: TIM_t("无法定位到原消息"),
|
||||
infoCode: 6660401));
|
||||
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("无法定位到原消息"), infoCode: 6660401));
|
||||
}
|
||||
|
||||
_onScrollToIndex(V2TimMessage targetMsg) {
|
||||
// This method called by @ messages or messages been searched, aims to jump to target message
|
||||
loadingPlace = LoadingPlace.top;
|
||||
const int singleLoadAmount = kIsWeb ? 15 : 40;
|
||||
final lastTimestamp =
|
||||
widget.messageList[widget.messageList.length - 1]?.timestamp;
|
||||
final lastTimestamp = widget.messageList[widget.messageList.length - 1]?.timestamp;
|
||||
final msgList = widget.messageList;
|
||||
final targetTimeStamp = targetMsg.timestamp!;
|
||||
|
||||
|
|
@ -184,9 +179,7 @@ class _TIMUIKitHistoryMessageListState
|
|||
int targetIndex = 1;
|
||||
for (int i = msgList.length - 1; i >= 0; i--) {
|
||||
final currentMsg = msgList[i];
|
||||
if (currentMsg?.timestamp == targetTimeStamp &&
|
||||
currentMsg?.elemType != 11 &&
|
||||
currentMsg!.msgID == targetMsg.msgID) {
|
||||
if (currentMsg?.timestamp == targetTimeStamp && currentMsg?.elemType != 11 && currentMsg!.msgID == targetMsg.msgID) {
|
||||
// find the target index by timestamp and msgID
|
||||
isFound = true;
|
||||
targetIndex = -i;
|
||||
|
|
@ -202,10 +195,8 @@ class _TIMUIKitHistoryMessageListState
|
|||
);
|
||||
|
||||
// execute twice for accurate position, as the position located firstly can be wrong
|
||||
_autoScrollController.scrollToIndex(targetIndex,
|
||||
preferPosition: AutoScrollPosition.middle);
|
||||
_autoScrollController.scrollToIndex(targetIndex,
|
||||
preferPosition: AutoScrollPosition.middle);
|
||||
_autoScrollController.scrollToIndex(targetIndex, preferPosition: AutoScrollPosition.middle);
|
||||
_autoScrollController.scrollToIndex(targetIndex, preferPosition: AutoScrollPosition.middle);
|
||||
|
||||
widget.model.jumpMsgID = targetMsg.msgID!;
|
||||
loadingPlace = LoadingPlace.none;
|
||||
|
|
@ -258,8 +249,7 @@ class _TIMUIKitHistoryMessageListState
|
|||
targetIndex,
|
||||
preferPosition: AutoScrollPosition.middle,
|
||||
);
|
||||
_autoScrollController.scrollToIndex(targetIndex,
|
||||
preferPosition: AutoScrollPosition.middle);
|
||||
_autoScrollController.scrollToIndex(targetIndex, preferPosition: AutoScrollPosition.middle);
|
||||
if (targetMsgID != null && targetMsgID != "") {
|
||||
widget.model.jumpMsgID = targetMsgID;
|
||||
}
|
||||
|
|
@ -270,8 +260,7 @@ class _TIMUIKitHistoryMessageListState
|
|||
} else {
|
||||
if (widget.model.haveMoreData) {
|
||||
findingSeq = targetSeq;
|
||||
widget.onLoadMore(_getMessageId(widget.messageList.length - 1),
|
||||
LoadDirection.previous, singleLoadAmount);
|
||||
widget.onLoadMore(_getMessageId(widget.messageList.length - 1), LoadDirection.previous, singleLoadAmount);
|
||||
} else {
|
||||
showCantFindMsg();
|
||||
}
|
||||
|
|
@ -279,8 +268,7 @@ class _TIMUIKitHistoryMessageListState
|
|||
}
|
||||
|
||||
_onScrollToIndexBegin(V2TimMessage targetMsg) {
|
||||
final lastTimestamp =
|
||||
widget.messageList[widget.messageList.length - 1]?.timestamp;
|
||||
final lastTimestamp = widget.messageList[widget.messageList.length - 1]?.timestamp;
|
||||
final msgList = widget.messageList;
|
||||
final int targetTimeStamp = targetMsg.timestamp!;
|
||||
|
||||
|
|
@ -289,9 +277,7 @@ class _TIMUIKitHistoryMessageListState
|
|||
int targetIndex = 1;
|
||||
for (int i = msgList.length - 1; i >= 0; i--) {
|
||||
final currentMsg = msgList[i];
|
||||
if (currentMsg?.timestamp == targetTimeStamp &&
|
||||
currentMsg?.elemType != 11 &&
|
||||
currentMsg!.msgID == targetMsg.msgID) {
|
||||
if (currentMsg?.timestamp == targetTimeStamp && currentMsg?.elemType != 11 && currentMsg!.msgID == targetMsg.msgID) {
|
||||
isFound = true;
|
||||
targetIndex = -i;
|
||||
break;
|
||||
|
|
@ -310,11 +296,8 @@ class _TIMUIKitHistoryMessageListState
|
|||
if (receivedMessageListCount == 0) {
|
||||
return [];
|
||||
}
|
||||
final haveTimeStampMessage =
|
||||
widget.messageList[receivedMessageListCount]?.elemType == 11;
|
||||
final endPoint = haveTimeStampMessage
|
||||
? receivedMessageListCount + 1
|
||||
: receivedMessageListCount;
|
||||
final haveTimeStampMessage = widget.messageList[receivedMessageListCount]?.elemType == 11;
|
||||
final endPoint = haveTimeStampMessage ? receivedMessageListCount + 1 : receivedMessageListCount;
|
||||
return widget.messageList.sublist(0, endPoint).reversed.toList();
|
||||
}
|
||||
|
||||
|
|
@ -333,19 +316,14 @@ class _TIMUIKitHistoryMessageListState
|
|||
final receivedNewMessageList = globalModel.receivedMessageListCount;
|
||||
final shouldShowUnreadMessage = receivedNewMessageList > 0;
|
||||
final unreadMessageList = _getReceivedMessageList(receivedNewMessageList);
|
||||
final readMessageList = messageList
|
||||
.sublist(unreadMessageList.length, messageList.length)
|
||||
.toList();
|
||||
final readMessageList = messageList.sublist(unreadMessageList.length, messageList.length).toList();
|
||||
|
||||
final throttleFunction =
|
||||
OptimizeUtils.multiThrottle((index, LoadDirection direction) async {
|
||||
final msgID =
|
||||
TIMUIKitChatUtils.getMessageIDWithinIndex(readMessageList, index);
|
||||
final throttleFunction = OptimizeUtils.multiThrottle((index, LoadDirection direction) async {
|
||||
final msgID = TIMUIKitChatUtils.getMessageIDWithinIndex(readMessageList, index);
|
||||
await widget.onLoadMore(msgID, direction);
|
||||
}, 20);
|
||||
|
||||
final throttleFunctionWithMsgID =
|
||||
OptimizeUtils.multiThrottle((msgID, LoadDirection direction) async {
|
||||
final throttleFunctionWithMsgID = OptimizeUtils.multiThrottle((msgID, LoadDirection direction) async {
|
||||
await widget.onLoadMore(msgID, direction);
|
||||
}, 200);
|
||||
|
||||
|
|
@ -368,63 +346,43 @@ class _TIMUIKitHistoryMessageListState
|
|||
center: shouldShowUnreadMessage ? centerKey : null,
|
||||
key: widget.mainHistoryListConfig?.key,
|
||||
primary: widget.mainHistoryListConfig?.primary,
|
||||
physics: (widget.isAllowScroll == false)
|
||||
? const NeverScrollableScrollPhysics()
|
||||
: widget.mainHistoryListConfig?.physics,
|
||||
physics: (widget.isAllowScroll == false) ? const NeverScrollableScrollPhysics() : widget.mainHistoryListConfig?.physics,
|
||||
// padding: widget.mainHistoryListConfig?.padding ?? EdgeInsets.zero,
|
||||
// itemExtent: widget.mainHistoryListConfig?.itemExtent,
|
||||
// prototypeItem: widget.mainHistoryListConfig?.prototypeItem,
|
||||
cacheExtent: widget.mainHistoryListConfig?.cacheExtent ?? 1500,
|
||||
semanticChildCount:
|
||||
widget.mainHistoryListConfig?.semanticChildCount,
|
||||
dragStartBehavior:
|
||||
widget.mainHistoryListConfig?.dragStartBehavior ??
|
||||
DragStartBehavior.start,
|
||||
keyboardDismissBehavior:
|
||||
widget.mainHistoryListConfig?.keyboardDismissBehavior ??
|
||||
ScrollViewKeyboardDismissBehavior.manual,
|
||||
semanticChildCount: widget.mainHistoryListConfig?.semanticChildCount,
|
||||
dragStartBehavior: widget.mainHistoryListConfig?.dragStartBehavior ?? DragStartBehavior.start,
|
||||
keyboardDismissBehavior: widget.mainHistoryListConfig?.keyboardDismissBehavior ?? ScrollViewKeyboardDismissBehavior.manual,
|
||||
restorationId: widget.mainHistoryListConfig?.restorationId,
|
||||
clipBehavior:
|
||||
widget.mainHistoryListConfig?.clipBehavior ?? Clip.hardEdge,
|
||||
clipBehavior: widget.mainHistoryListConfig?.clipBehavior ?? Clip.hardEdge,
|
||||
reverse: true,
|
||||
shrinkWrap: !shouldShowUnreadMessage,
|
||||
controller: _autoScrollController,
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding:
|
||||
widget.mainHistoryListConfig?.padding ?? EdgeInsets.zero,
|
||||
padding: widget.mainHistoryListConfig?.padding ?? EdgeInsets.zero,
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(BuildContext context, int index) {
|
||||
final messageItem = unreadMessageList[index];
|
||||
if (index == unreadMessageList.length - 1 &&
|
||||
widget.model.haveMoreLatestData == true) {
|
||||
throttleFunctionWithMsgID(
|
||||
messageItem?.msgID ?? "",
|
||||
LoadDirection.latest);
|
||||
if (index == unreadMessageList.length - 1 && widget.model.haveMoreLatestData == true) {
|
||||
throttleFunctionWithMsgID(messageItem?.msgID ?? "", LoadDirection.latest);
|
||||
}
|
||||
outputLogger.i("Rendering a unread message: ${getMessageIdentifier(messageItem, 0)}, message Type: ${messageItem?.elemType}");
|
||||
return AutoScrollTag(
|
||||
controller: _autoScrollController,
|
||||
index: -index,
|
||||
key: ValueKey(
|
||||
getMessageIdentifier(messageItem, index)),
|
||||
key: ValueKey(getMessageIdentifier(messageItem, index)),
|
||||
highlightColor: Colors.black.withOpacity(0.1),
|
||||
child: KeepAliveWrapper(
|
||||
keepAlive: messageItem?.elemType ==
|
||||
MessageElemType.V2TIM_ELEM_TYPE_SOUND,
|
||||
child: Container(
|
||||
child:
|
||||
_getMessageItemBuilder(messageItem))),
|
||||
child: KeepAliveWrapper(keepAlive: messageItem?.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND, child: Container(child: _getMessageItemBuilder(messageItem))),
|
||||
);
|
||||
},
|
||||
childCount: unreadMessageList.length,
|
||||
findChildIndexCallback: (Key key) {
|
||||
final ValueKey<String> valueKey =
|
||||
key as ValueKey<String>;
|
||||
final ValueKey<String> valueKey = key as ValueKey<String>;
|
||||
final String data = valueKey.value;
|
||||
final int index = unreadMessageList.indexWhere(
|
||||
(element) =>
|
||||
getMessageIdentifier(element, 0) == data);
|
||||
final int index = unreadMessageList.indexWhere((element) => getMessageIdentifier(element, 0) == data);
|
||||
return index != -1 ? index : null;
|
||||
})),
|
||||
),
|
||||
|
|
@ -433,8 +391,7 @@ class _TIMUIKitHistoryMessageListState
|
|||
key: centerKey,
|
||||
),
|
||||
SliverPadding(
|
||||
padding:
|
||||
widget.mainHistoryListConfig?.padding ?? EdgeInsets.zero,
|
||||
padding: widget.mainHistoryListConfig?.padding ?? EdgeInsets.zero,
|
||||
sliver: Selector<TUIChatSeparateViewModel, bool>(
|
||||
selector: (context, model) {
|
||||
return model.haveMoreData;
|
||||
|
|
@ -449,64 +406,41 @@ class _TIMUIKitHistoryMessageListState
|
|||
final messageItem = readMessageList[index];
|
||||
if (index == readMessageList.length - 1) {
|
||||
if (haveMoreData) {
|
||||
throttleFunction(
|
||||
index, LoadDirection.previous);
|
||||
throttleFunction(index, LoadDirection.previous);
|
||||
return Column(
|
||||
children: [
|
||||
LoadingAnimationWidget
|
||||
.staggeredDotsWave(
|
||||
color: theme.weakTextColor ??
|
||||
Colors.grey,
|
||||
LoadingAnimationWidget.staggeredDotsWave(
|
||||
color: theme.weakTextColor ?? Colors.grey,
|
||||
size: 28,
|
||||
),
|
||||
AutoScrollTag(
|
||||
controller: _autoScrollController,
|
||||
index: -index,
|
||||
key: ValueKey(getMessageIdentifier(
|
||||
messageItem, index)),
|
||||
highlightColor:
|
||||
Colors.black.withOpacity(0.1),
|
||||
child: KeepAliveWrapper(
|
||||
keepAlive: messageItem
|
||||
?.elemType ==
|
||||
MessageElemType
|
||||
.V2TIM_ELEM_TYPE_SOUND,
|
||||
child: Container(
|
||||
child: _getMessageItemBuilder(
|
||||
messageItem))),
|
||||
key: ValueKey(getMessageIdentifier(messageItem, index)),
|
||||
highlightColor: Colors.black.withOpacity(0.1),
|
||||
child: KeepAliveWrapper(keepAlive: messageItem?.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND, child: Container(child: _getMessageItemBuilder(messageItem))),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
if (index == 0 &&
|
||||
widget.model.haveMoreLatestData == true &&
|
||||
globalModel.receivedMessageListCount < 10) {
|
||||
if (index == 0 && widget.model.haveMoreLatestData == true && globalModel.receivedMessageListCount < 10) {
|
||||
throttleFunction(index, LoadDirection.latest);
|
||||
}
|
||||
outputLogger.i("Rendering a read message: ${getMessageIdentifier(messageItem, 0)}, message Type: ${messageItem?.elemType}");
|
||||
return AutoScrollTag(
|
||||
controller: _autoScrollController,
|
||||
index: -index,
|
||||
key: ValueKey(
|
||||
getMessageIdentifier(messageItem, index)),
|
||||
key: ValueKey(getMessageIdentifier(messageItem, index)),
|
||||
highlightColor: Colors.black.withOpacity(0.1),
|
||||
child: KeepAliveWrapper(
|
||||
keepAlive: messageItem?.elemType ==
|
||||
MessageElemType.V2TIM_ELEM_TYPE_SOUND,
|
||||
child: Container(
|
||||
child: _getMessageItemBuilder(
|
||||
messageItem))),
|
||||
child: KeepAliveWrapper(keepAlive: messageItem?.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND, child: Container(child: _getMessageItemBuilder(messageItem))),
|
||||
);
|
||||
},
|
||||
childCount: readMessageList.length,
|
||||
findChildIndexCallback: (Key key) {
|
||||
final ValueKey<String> valueKey =
|
||||
key as ValueKey<String>;
|
||||
final ValueKey<String> valueKey = key as ValueKey<String>;
|
||||
final String data = valueKey.value;
|
||||
final int index = readMessageList.indexWhere(
|
||||
(element) =>
|
||||
getMessageIdentifier(element, 0) ==
|
||||
data);
|
||||
final int index = readMessageList.indexWhere((element) => getMessageIdentifier(element, 0) == data);
|
||||
return index > -1 ? index : null;
|
||||
}));
|
||||
},
|
||||
|
|
@ -539,17 +473,14 @@ class TIMUIKitHistoryMessageListSelector extends TIMUIKitStatelessWidget {
|
|||
final Widget Function(BuildContext, List<V2TimMessage?>, Widget?) builder;
|
||||
final String conversationID;
|
||||
|
||||
TIMUIKitHistoryMessageListSelector(
|
||||
{Key? key, required this.builder, required this.conversationID})
|
||||
: super(key: key);
|
||||
TIMUIKitHistoryMessageListSelector({Key? key, required this.builder, required this.conversationID}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
return Selector<TUIChatGlobalModel, List<V2TimMessage?>>(
|
||||
builder: builder,
|
||||
shouldRebuild: (previous, next) {
|
||||
final isEquals =
|
||||
const DeepCollectionEquality.unordered().equals(previous, next);
|
||||
final isEquals = const DeepCollectionEquality.unordered().equals(previous, next);
|
||||
return !isEquals;
|
||||
},
|
||||
selector: (context, model) {
|
||||
|
|
|
|||
|
|
@ -1,26 +1,27 @@
|
|||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:diff_match_patch/diff_match_patch.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_setting_model.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/emoji_text.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field_layout/narrow.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:scroll_to_index/scroll_to_index.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';
|
||||
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/business_logic/view_models/tui_conversation_view_model.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_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/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/utils/screen_utils.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/emoji_text.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_at_text.dart';
|
||||
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_text_field_layout/narrow.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field_layout/wide.dart';
|
||||
|
||||
enum MuteStatus { none, me, all }
|
||||
|
|
@ -141,8 +142,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
double inputWidth = 900;
|
||||
Map<String, V2TimGroupMemberFullInfo> mentionedMembersMap = {};
|
||||
late TextEditingController textEditingController;
|
||||
final TUIConversationViewModel conversationModel =
|
||||
serviceLocator<TUIConversationViewModel>();
|
||||
final TUIConversationViewModel conversationModel = serviceLocator<TUIConversationViewModel>();
|
||||
final TUISelfInfoViewModel selfModel = serviceLocator<TUISelfInfoViewModel>();
|
||||
MuteStatus muteStatus = MuteStatus.none;
|
||||
bool _isComposingText = false;
|
||||
|
|
@ -154,56 +154,38 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
// Keep using original scheme.
|
||||
return;
|
||||
}
|
||||
final stickerConfig =
|
||||
widget.model.chatConfig.stickerPanelConfig ?? StickerPanelConfig();
|
||||
final stickerConfig = widget.model.chatConfig.stickerPanelConfig ?? StickerPanelConfig();
|
||||
if (stickerConfig.useTencentCloudChatStickerPackage) {
|
||||
final tccEmojiSet = TUIKitStickerConstData.emojiList
|
||||
.firstWhere((element) => element.name == "tcc1");
|
||||
final tccEmojiSet = TUIKitStickerConstData.emojiList.firstWhere((element) => element.name == "tcc1");
|
||||
stickerPackageList.add(CustomStickerPackage(
|
||||
name: tccEmojiSet.name,
|
||||
baseUrl: "assets/custom_face_resource/${tccEmojiSet.name}",
|
||||
isEmoji: tccEmojiSet.isEmoji,
|
||||
isDefaultEmoji: true,
|
||||
stickerList: tccEmojiSet.list
|
||||
.asMap()
|
||||
.keys
|
||||
.map((idx) =>
|
||||
CustomSticker(index: idx, name: tccEmojiSet.list[idx]))
|
||||
.toList(),
|
||||
stickerList: tccEmojiSet.list.asMap().keys.map((idx) => CustomSticker(index: idx, name: tccEmojiSet.list[idx])).toList(),
|
||||
menuItem: CustomSticker(
|
||||
index: 0,
|
||||
name: tccEmojiSet.icon,
|
||||
)));
|
||||
}
|
||||
if (stickerConfig.useQQStickerPackage) {
|
||||
final qqEmojiSet = TUIKitStickerConstData.emojiList
|
||||
.firstWhere((element) => element.name == "4349");
|
||||
final qqEmojiSet = TUIKitStickerConstData.emojiList.firstWhere((element) => element.name == "4349");
|
||||
stickerPackageList.add(CustomStickerPackage(
|
||||
name: qqEmojiSet.name,
|
||||
baseUrl: "assets/custom_face_resource/${qqEmojiSet.name}",
|
||||
isEmoji: qqEmojiSet.isEmoji,
|
||||
isDefaultEmoji: true,
|
||||
stickerList: qqEmojiSet.list
|
||||
.asMap()
|
||||
.keys
|
||||
.map((idx) =>
|
||||
CustomSticker(index: idx, name: qqEmojiSet.list[idx]))
|
||||
.toList(),
|
||||
stickerList: qqEmojiSet.list.asMap().keys.map((idx) => CustomSticker(index: idx, name: qqEmojiSet.list[idx])).toList(),
|
||||
menuItem: CustomSticker(
|
||||
index: 0,
|
||||
name: qqEmojiSet.icon,
|
||||
)));
|
||||
}
|
||||
if (stickerConfig.unicodeEmojiList.isNotEmpty) {
|
||||
final defEmojiList =
|
||||
TUIKitStickerConstData.defaultUnicodeEmojiList.map((emojiItem) {
|
||||
return CustomSticker(
|
||||
index: 0, name: emojiItem.toString(), unicode: emojiItem);
|
||||
final defEmojiList = TUIKitStickerConstData.defaultUnicodeEmojiList.map((emojiItem) {
|
||||
return CustomSticker(index: 0, name: emojiItem.toString(), unicode: emojiItem);
|
||||
}).toList();
|
||||
stickerPackageList.add(CustomStickerPackage(
|
||||
name: "defaultEmoji",
|
||||
stickerList: defEmojiList,
|
||||
menuItem: defEmojiList[0]));
|
||||
stickerPackageList.add(CustomStickerPackage(name: "defaultEmoji", stickerList: defEmojiList, menuItem: defEmojiList[0]));
|
||||
}
|
||||
stickerPackageList.addAll(stickerConfig.customStickerPackages);
|
||||
|
||||
|
|
@ -253,9 +235,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
textEditingController.text = text;
|
||||
|
||||
if (TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop) {
|
||||
textEditingController.selection = TextSelection.fromPosition(
|
||||
TextPosition(
|
||||
offset: currentCursor ?? textEditingController.text.length));
|
||||
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: currentCursor ?? textEditingController.text.length));
|
||||
focusNode.requestFocus();
|
||||
}
|
||||
}
|
||||
|
|
@ -263,9 +243,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
|
||||
void addStickerToText(String sticker) {
|
||||
final currentText = textEditingController.text;
|
||||
if (currentCursor != null &&
|
||||
currentCursor! > -1 &&
|
||||
currentCursor! < currentText.length + 1) {
|
||||
if (currentCursor != null && currentCursor! > -1 && currentCursor! < currentText.length + 1) {
|
||||
final firstString = currentText.substring(0, currentCursor);
|
||||
final secondString = currentText.substring(currentCursor!);
|
||||
currentCursor = currentCursor! + sticker.length;
|
||||
|
|
@ -276,8 +254,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
}
|
||||
|
||||
if (TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop) {
|
||||
textEditingController.selection = TextSelection.fromPosition(TextPosition(
|
||||
offset: currentCursor ?? textEditingController.text.length));
|
||||
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: currentCursor ?? textEditingController.text.length));
|
||||
focusNode.requestFocus();
|
||||
}
|
||||
}
|
||||
|
|
@ -286,23 +263,13 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
return text.replaceAll(RegExp(r'\ufeff'), "");
|
||||
}
|
||||
|
||||
Future handleSetDraftText(
|
||||
{String? id, ConvType? convType, String? groupID}) async {
|
||||
Future handleSetDraftText({String? id, ConvType? convType, String? groupID}) async {
|
||||
String text = textEditingController.text;
|
||||
String convID = id ?? widget.conversationID;
|
||||
final isTopic = convID.contains("@TOPIC#");
|
||||
String conversationID = isTopic
|
||||
? convID
|
||||
: ((convType ?? widget.conversationType) == ConvType.c2c
|
||||
? "c2c_$convID"
|
||||
: "group_$convID");
|
||||
String conversationID = isTopic ? convID : ((convType ?? widget.conversationType) == ConvType.c2c ? "c2c_$convID" : "group_$convID");
|
||||
String draftText = _filterU200b(text);
|
||||
return await conversationModel.setConversationDraft(
|
||||
groupID: groupID ?? widget.groupID,
|
||||
isTopic: isTopic,
|
||||
isAllowWeb: widget.model.chatConfig.isUseDraftOnWeb,
|
||||
conversationID: conversationID,
|
||||
draftText: draftText);
|
||||
return await conversationModel.setConversationDraft(groupID: groupID ?? widget.groupID, isTopic: isTopic, isAllowWeb: widget.model.chatConfig.isUseDraftOnWeb, conversationID: conversationID, draftText: draftText);
|
||||
}
|
||||
|
||||
// 和onSubmitted一样,只是保持焦点的不同
|
||||
|
|
@ -350,21 +317,9 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
}
|
||||
|
||||
if (widget.model.repliedMessage != null) {
|
||||
MessageUtils.handleMessageError(
|
||||
widget.model.sendFaceMessage(
|
||||
index: index,
|
||||
data: data,
|
||||
convID: widget.conversationID,
|
||||
convType: convType),
|
||||
context);
|
||||
MessageUtils.handleMessageError(widget.model.sendFaceMessage(index: index, data: data, convID: widget.conversationID, convType: convType), context);
|
||||
} else {
|
||||
MessageUtils.handleMessageError(
|
||||
widget.model.sendFaceMessage(
|
||||
index: index,
|
||||
data: data,
|
||||
convID: widget.conversationID,
|
||||
convType: convType),
|
||||
context);
|
||||
MessageUtils.handleMessageError(widget.model.sendFaceMessage(index: index, data: data, convID: widget.conversationID, convType: convType), context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -384,24 +339,11 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
final convType = widget.conversationType;
|
||||
if (text.isNotEmpty && text != zeroWidthSpace) {
|
||||
if (widget.model.repliedMessage != null) {
|
||||
MessageUtils.handleMessageError(
|
||||
widget.model.sendReplyMessage(
|
||||
text: text,
|
||||
convID: widget.conversationID,
|
||||
convType: convType,
|
||||
atUserIDList: getUserIdFromMemberInfoMap()),
|
||||
context);
|
||||
MessageUtils.handleMessageError(widget.model.sendReplyMessage(text: text, convID: widget.conversationID, convType: convType, atUserIDList: getUserIdFromMemberInfoMap()), context);
|
||||
} else if (mentionedMembersMap.isNotEmpty) {
|
||||
widget.model.sendTextAtMessage(
|
||||
text: text,
|
||||
convType: widget.conversationType,
|
||||
convID: widget.conversationID,
|
||||
atUserList: getUserIdFromMemberInfoMap());
|
||||
widget.model.sendTextAtMessage(text: text, convType: widget.conversationType, convID: widget.conversationID, atUserList: getUserIdFromMemberInfoMap());
|
||||
} else {
|
||||
MessageUtils.handleMessageError(
|
||||
widget.model.sendTextMessage(
|
||||
text: text, convID: widget.conversationID, convType: convType),
|
||||
context);
|
||||
MessageUtils.handleMessageError(widget.model.sendTextMessage(text: text, convID: widget.conversationID, convType: convType), context);
|
||||
}
|
||||
textEditingController.clear();
|
||||
currentCursor = null;
|
||||
|
|
@ -414,8 +356,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
}
|
||||
|
||||
void goDownBottom() {
|
||||
if (globalModel.getMessageListPosition(widget.conversationID) ==
|
||||
HistoryMessagePosition.notShowLatest) {
|
||||
if (globalModel.getMessageListPosition(widget.conversationID) == HistoryMessagePosition.notShowLatest) {
|
||||
return;
|
||||
}
|
||||
Future.delayed(const Duration(milliseconds: 50), () {
|
||||
|
|
@ -444,18 +385,14 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
}
|
||||
|
||||
String _getShowName(V2TimGroupMemberFullInfo? item) {
|
||||
return TencentUtils.checkStringWithoutSpace(item?.nameCard) ??
|
||||
TencentUtils.checkStringWithoutSpace(item?.nickName) ??
|
||||
TencentUtils.checkStringWithoutSpace(item?.userID) ??
|
||||
"";
|
||||
return TencentUtils.checkStringWithoutSpace(item?.nameCard) ?? TencentUtils.checkStringWithoutSpace(item?.nickName) ?? TencentUtils.checkStringWithoutSpace(item?.userID) ?? "";
|
||||
}
|
||||
|
||||
mentionMemberInMessage(String? userID, String? nickName) {
|
||||
if (TencentUtils.checkString(userID) == null) {
|
||||
focusNode.requestFocus();
|
||||
} else {
|
||||
final memberInfo = widget.model.groupMemberList
|
||||
?.firstWhereOrNull((element) => element?.userID == userID) ??
|
||||
final memberInfo = widget.model.groupMemberList?.firstWhereOrNull((element) => element?.userID == userID) ??
|
||||
V2TimGroupMemberFullInfo(
|
||||
userID: userID ?? "",
|
||||
nickName: nickName,
|
||||
|
|
@ -466,8 +403,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
//please do not delete space
|
||||
focusNode.requestFocus();
|
||||
textEditingController.text = text;
|
||||
textEditingController.selection =
|
||||
TextSelection.fromPosition(TextPosition(offset: text.length));
|
||||
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: text.length));
|
||||
lastText = text;
|
||||
_isComposingText = false;
|
||||
narrowTextFieldKey.currentState?.showKeyboard = true;
|
||||
|
|
@ -495,16 +431,10 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
maxLines: null,
|
||||
);
|
||||
textPainter.layout(maxWidth: inputWidth);
|
||||
final TextPosition lastLineOffset = textPainter
|
||||
.getPositionForOffset(Offset(textPainter.width, textPainter.height));
|
||||
final Offset caretPosition =
|
||||
textPainter.getOffsetForCaret(lastLineOffset, Rect.zero);
|
||||
final TextPosition lastLineOffset = textPainter.getPositionForOffset(Offset(textPainter.width, textPainter.height));
|
||||
final Offset caretPosition = textPainter.getOffsetForCaret(lastLineOffset, Rect.zero);
|
||||
final dx = min(inputWidth - 180, caretPosition.dx + 16);
|
||||
final dy = max(
|
||||
24,
|
||||
21 * widget.model.chatConfig.desktopMessageInputFieldLines -
|
||||
caretPosition.dy)
|
||||
.toDouble();
|
||||
final dy = max(24, 21 * widget.model.chatConfig.desktopMessageInputFieldLines - caretPosition.dy).toDouble();
|
||||
|
||||
return Offset(dx, dy);
|
||||
}
|
||||
|
|
@ -541,19 +471,13 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
mentionedMembersMap = map;
|
||||
}
|
||||
|
||||
(int, String, bool)? findChangedCharacter(
|
||||
String originalString, String newString) {
|
||||
(int, String, bool)? findChangedCharacter(String originalString, String newString) {
|
||||
if (newString.length < originalString.length) {
|
||||
final originalStringLength = originalString.length;
|
||||
final newStringLength = newString.length;
|
||||
for (int i = 0; i < newString.length; ++i) {
|
||||
if (originalString[originalStringLength - i - 1] !=
|
||||
newString[newStringLength - i - 1]) {
|
||||
return (
|
||||
newStringLength - i,
|
||||
originalString[originalStringLength - i - 1],
|
||||
false
|
||||
);
|
||||
if (originalString[originalStringLength - i - 1] != newString[newStringLength - i - 1]) {
|
||||
return (newStringLength - i, originalString[originalStringLength - i - 1], false);
|
||||
}
|
||||
}
|
||||
return (newString.length, originalString[newString.length], false);
|
||||
|
|
@ -572,11 +496,8 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
_handleAtText(String text, TUIChatSeparateViewModel model) async {
|
||||
final text = textEditingController.text;
|
||||
final String originalText = lastText;
|
||||
String? groupID = widget.conversationType == ConvType.group
|
||||
? widget.conversationID
|
||||
: null;
|
||||
final isDesktopScreen =
|
||||
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||
String? groupID = widget.conversationType == ConvType.group ? widget.conversationID : null;
|
||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||
|
||||
if (groupID == null) {
|
||||
lastText = text;
|
||||
|
|
@ -596,11 +517,9 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
String atTag = originalText.substring(atIndex, spaceIndex);
|
||||
String deletedChar = originalText[diffIndex];
|
||||
if (shouldRemoveAtTag(atTag, deletedChar)) {
|
||||
final newText = originalText.substring(0, atIndex) +
|
||||
originalText.substring(spaceIndex + 1);
|
||||
final newText = originalText.substring(0, atIndex) + originalText.substring(spaceIndex + 1);
|
||||
textEditingController.text = newText;
|
||||
textEditingController.selection =
|
||||
TextSelection.collapsed(offset: atIndex);
|
||||
textEditingController.selection = TextSelection.collapsed(offset: atIndex);
|
||||
lastText = newText;
|
||||
updateMentionedMap();
|
||||
return;
|
||||
|
|
@ -610,13 +529,10 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
}
|
||||
|
||||
final int selfRole = widget.model.selfMemberInfo?.role ?? 0;
|
||||
final bool canAtAll =
|
||||
(selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN ||
|
||||
selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
|
||||
final bool canAtAll = (selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN || selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
|
||||
|
||||
if (isDesktopScreen) {
|
||||
(int, String, bool)? changedCharacterRecord =
|
||||
findChangedCharacter(originalText, text);
|
||||
(int, String, bool)? changedCharacterRecord = findChangedCharacter(originalText, text);
|
||||
int? changedTextPosition = changedCharacterRecord?.$1;
|
||||
String? changedCharacter = changedCharacterRecord?.$2;
|
||||
bool isAdded = changedCharacterRecord?.$3 ?? false;
|
||||
|
|
@ -625,13 +541,10 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
int? atPlace;
|
||||
|
||||
if (changedTextPosition != null) {
|
||||
subText = isAdded == true
|
||||
? text.substring(0, changedTextPosition + 1)
|
||||
: text.substring(0, changedTextPosition);
|
||||
subText = isAdded == true ? text.substring(0, changedTextPosition + 1) : text.substring(0, changedTextPosition);
|
||||
atPlace = subText.lastIndexOf('@');
|
||||
if (atPlace != -1) {
|
||||
keyword = text.substring(
|
||||
atPlace + 1, changedTextPosition + (isAdded ? 1 : 0));
|
||||
keyword = text.substring(atPlace + 1, changedTextPosition + (isAdded ? 1 : 0));
|
||||
}
|
||||
} else {
|
||||
atPlace = -1;
|
||||
|
|
@ -644,28 +557,21 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
model.atPositionY = atPosition.dy;
|
||||
isAddingAtSearchWords = true;
|
||||
}
|
||||
List<V2TimGroupMemberFullInfo> showAtMemberList = (model
|
||||
.groupMemberList ??
|
||||
[])
|
||||
List<V2TimGroupMemberFullInfo> showAtMemberList = (model.groupMemberList ?? [])
|
||||
.where((element) {
|
||||
final showName = (TencentUtils.checkStringWithoutSpace(
|
||||
element?.friendRemark) ??
|
||||
final showName = (TencentUtils.checkStringWithoutSpace(element?.friendRemark) ??
|
||||
TencentUtils.checkStringWithoutSpace(element?.nameCard) ??
|
||||
TencentUtils.checkStringWithoutSpace(element?.nickName) ??
|
||||
TencentUtils.checkStringWithoutSpace(element?.userID) ??
|
||||
"")
|
||||
.toLowerCase();
|
||||
keyword ??= "";
|
||||
return element != null &&
|
||||
showName.contains(keyword!.toLowerCase()) &&
|
||||
TencentUtils.checkString(showName) != null &&
|
||||
element.userID != widget.model.selfMemberInfo?.userID;
|
||||
return element != null && showName.contains(keyword!.toLowerCase()) && TencentUtils.checkString(showName) != null && element.userID != widget.model.selfMemberInfo?.userID;
|
||||
})
|
||||
.whereType<V2TimGroupMemberFullInfo>()
|
||||
.toList();
|
||||
|
||||
showAtMemberList.sort(
|
||||
(V2TimGroupMemberFullInfo userA, V2TimGroupMemberFullInfo userB) {
|
||||
showAtMemberList.sort((V2TimGroupMemberFullInfo userA, V2TimGroupMemberFullInfo userB) {
|
||||
final isUserAIsGroupAdmin = userA.role == 300;
|
||||
final isUserAIsGroupOwner = userA.role == 400;
|
||||
|
||||
|
|
@ -688,11 +594,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
|
||||
keyword ??= "";
|
||||
if (canAtAll && showAtMemberList.isNotEmpty && keyword!.isEmpty) {
|
||||
showAtMemberList = [
|
||||
V2TimGroupMemberFullInfo(
|
||||
userID: "__kImSDK_MesssageAtALL__", nickName: TIM_t("所有人")),
|
||||
...showAtMemberList
|
||||
];
|
||||
showAtMemberList = [V2TimGroupMemberFullInfo(userID: "__kImSDK_MesssageAtALL__", nickName: TIM_t("所有人")), ...showAtMemberList];
|
||||
}
|
||||
|
||||
model.activeAtIndex = 0;
|
||||
|
|
@ -704,18 +606,11 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
model.showAtMemberList = [];
|
||||
isAddingAtSearchWords = false;
|
||||
}
|
||||
} else if (textLength > 0 &&
|
||||
text[textLength - 1] == "@" &&
|
||||
lastText.length < textLength) {
|
||||
} else if (textLength > 0 && text[textLength - 1] == "@" && lastText.length < textLength) {
|
||||
V2TimGroupMemberFullInfo? memberInfo = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => AtText(
|
||||
groupMemberList: model.groupMemberList,
|
||||
groupInfo: model.groupInfo,
|
||||
groupID: groupID,
|
||||
canAtAll: canAtAll,
|
||||
groupType: widget.groupType),
|
||||
builder: (context) => AtText(groupMemberList: model.groupMemberList, groupInfo: model.groupInfo, groupID: groupID, canAtAll: canAtAll, groupType: widget.groupType),
|
||||
),
|
||||
);
|
||||
final showName = _getShowName(memberInfo);
|
||||
|
|
@ -730,22 +625,17 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
|
||||
void replaceAtTag(String selectedMember) {
|
||||
int cursorPosition = textEditingController.selection.baseOffset;
|
||||
int atIndex =
|
||||
textEditingController.text.lastIndexOf('@', cursorPosition - 1);
|
||||
int atIndex = textEditingController.text.lastIndexOf('@', cursorPosition - 1);
|
||||
if (atIndex >= 0) {
|
||||
String beforeAt = textEditingController.text.substring(0, atIndex);
|
||||
String afterAt = textEditingController.text.substring(cursorPosition);
|
||||
textEditingController.text =
|
||||
beforeAt + '@' + selectedMember + ' ' + afterAt;
|
||||
textEditingController.selection =
|
||||
TextSelection.collapsed(offset: atIndex + selectedMember.length + 2);
|
||||
textEditingController.text = beforeAt + '@' + selectedMember + ' ' + afterAt;
|
||||
textEditingController.selection = TextSelection.collapsed(offset: atIndex + selectedMember.length + 2);
|
||||
lastText = beforeAt + '@' + selectedMember + ' ' + afterAt;
|
||||
}
|
||||
}
|
||||
|
||||
void handleAtMember(
|
||||
{V2TimGroupMemberFullInfo? memberInfo,
|
||||
bool? isAddToCursorPosition = false}) {
|
||||
void handleAtMember({V2TimGroupMemberFullInfo? memberInfo, bool? isAddToCursorPosition = false}) {
|
||||
if (memberInfo != null) {
|
||||
final String showName = _getShowName(memberInfo);
|
||||
mentionedMembersMap["@$showName"] = memberInfo;
|
||||
|
|
@ -759,24 +649,17 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
KeyEventResult handleDesktopKeyEvent(FocusNode node, RawKeyEvent event) {
|
||||
final activeIndex = widget.model.activeAtIndex;
|
||||
final showMemberList = widget.model.showAtMemberList;
|
||||
final isPressEnter = (event.physicalKey == PhysicalKeyboardKey.enter) ||
|
||||
(event.physicalKey == PhysicalKeyboardKey.numpadEnter);
|
||||
final isPressEnter = (event.physicalKey == PhysicalKeyboardKey.enter) || (event.physicalKey == PhysicalKeyboardKey.numpadEnter);
|
||||
if (event.runtimeType == RawKeyDownEvent) {
|
||||
if (event.physicalKey == PhysicalKeyboardKey.backspace) {
|
||||
if (textEditingController.text.isEmpty && lastText.isEmpty) {
|
||||
widget.model.repliedMessage = null;
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
} else if ((event.isShiftPressed ||
|
||||
event.isAltPressed ||
|
||||
event.isControlPressed ||
|
||||
event.isMetaPressed) &&
|
||||
isPressEnter) {
|
||||
} else if ((event.isShiftPressed || event.isAltPressed || event.isControlPressed || event.isMetaPressed) && isPressEnter) {
|
||||
final offset = textEditingController.selection.baseOffset;
|
||||
textEditingController.text =
|
||||
'${lastText.substring(0, offset)}\n${lastText.substring(offset)}';
|
||||
textEditingController.selection =
|
||||
TextSelection.fromPosition(TextPosition(offset: offset + 1));
|
||||
textEditingController.text = '${lastText.substring(0, offset)}\n${lastText.substring(offset)}';
|
||||
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: offset + 1));
|
||||
lastText = textEditingController.text;
|
||||
|
||||
return KeyEventResult.handled;
|
||||
|
|
@ -786,34 +669,26 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
onSubmitted();
|
||||
} else {
|
||||
isAddingAtSearchWords = false;
|
||||
final V2TimGroupMemberFullInfo? memberInfo =
|
||||
showMemberList[activeIndex];
|
||||
final V2TimGroupMemberFullInfo? memberInfo = showMemberList[activeIndex];
|
||||
if (memberInfo != null) {
|
||||
handleAtMember(
|
||||
memberInfo: memberInfo, isAddToCursorPosition: true);
|
||||
handleAtMember(memberInfo: memberInfo, isAddToCursorPosition: true);
|
||||
}
|
||||
}
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.isKeyPressed(LogicalKeyboardKey.arrowUp) &&
|
||||
isAddingAtSearchWords &&
|
||||
showMemberList.isNotEmpty) {
|
||||
if (event.isKeyPressed(LogicalKeyboardKey.arrowUp) && isAddingAtSearchWords && showMemberList.isNotEmpty) {
|
||||
final newIndex = max(activeIndex - 1, 0);
|
||||
widget.model.activeAtIndex = newIndex;
|
||||
widget.atMemberPanelScroll?.scrollToIndex(newIndex,
|
||||
preferPosition: AutoScrollPosition.middle);
|
||||
widget.atMemberPanelScroll?.scrollToIndex(newIndex, preferPosition: AutoScrollPosition.middle);
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
|
||||
if (event.isKeyPressed(LogicalKeyboardKey.arrowDown) &&
|
||||
isAddingAtSearchWords &&
|
||||
showMemberList.isNotEmpty) {
|
||||
if (event.isKeyPressed(LogicalKeyboardKey.arrowDown) && isAddingAtSearchWords && showMemberList.isNotEmpty) {
|
||||
final newIndex = min(activeIndex + 1, showMemberList.length - 1);
|
||||
widget.model.activeAtIndex = newIndex;
|
||||
widget.atMemberPanelScroll?.scrollToIndex(newIndex,
|
||||
preferPosition: AutoScrollPosition.middle);
|
||||
widget.atMemberPanelScroll?.scrollToIndex(newIndex, preferPosition: AutoScrollPosition.middle);
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
}
|
||||
|
|
@ -831,8 +706,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
} else {
|
||||
focusNode = FocusNode();
|
||||
}
|
||||
textEditingController =
|
||||
widget.controller?.textEditingController ?? TextEditingController();
|
||||
textEditingController = widget.controller?.textEditingController ?? TextEditingController();
|
||||
if (widget.initText != null) {
|
||||
textEditingController.text = widget.initText!;
|
||||
}
|
||||
|
|
@ -840,10 +714,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
widget.controller?.addListener(controllerHandler);
|
||||
}
|
||||
final AppLocale appLocale = I18nUtils.findDeviceLocale(null);
|
||||
languageType =
|
||||
(appLocale == AppLocale.zhHans || appLocale == AppLocale.zhHant)
|
||||
? 'zh'
|
||||
: 'en';
|
||||
languageType = (appLocale == AppLocale.zhHans || appLocale == AppLocale.zhHant) ? 'zh' : 'en';
|
||||
textEditingController.addListener(() {
|
||||
_isComposingText = textEditingController.value.composing.start != -1;
|
||||
});
|
||||
|
|
@ -853,13 +724,11 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
controllerHandler() {
|
||||
final actionType = widget.controller?.actionType;
|
||||
if (actionType == ActionType.longPressToAt) {
|
||||
mentionMemberInMessage(
|
||||
widget.controller?.atUserID, widget.controller?.atUserName);
|
||||
mentionMemberInMessage(widget.controller?.atUserID, widget.controller?.atUserName);
|
||||
} else if (actionType == ActionType.setTextField) {
|
||||
final newText = widget.controller?.inputText ?? "";
|
||||
textEditingController.text = newText;
|
||||
textEditingController.selection = TextSelection.fromPosition(
|
||||
TextPosition(offset: textEditingController.text.length));
|
||||
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: textEditingController.text.length));
|
||||
lastText = textEditingController.text;
|
||||
focusNode.requestFocus();
|
||||
return;
|
||||
|
|
@ -877,18 +746,14 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.conversationID != oldWidget.conversationID) {
|
||||
mentionedMembersMap.clear();
|
||||
handleSetDraftText(
|
||||
id: oldWidget.conversationID,
|
||||
convType: oldWidget.conversationType,
|
||||
groupID: oldWidget.groupID);
|
||||
handleSetDraftText(id: oldWidget.conversationID, convType: oldWidget.conversationType, groupID: oldWidget.groupID);
|
||||
if (oldWidget.initText != widget.initText) {
|
||||
textEditingController.text = widget.initText ?? "";
|
||||
} else {
|
||||
textEditingController.clear();
|
||||
}
|
||||
}
|
||||
if (widget.initText != oldWidget.initText &&
|
||||
TencentUtils.checkString(widget.initText) != null) {
|
||||
if (widget.initText != oldWidget.initText && TencentUtils.checkString(widget.initText) != null) {
|
||||
textEditingController.text = widget.initText!;
|
||||
focusNode.requestFocus();
|
||||
}
|
||||
|
|
@ -906,12 +771,8 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
|
||||
Future<bool> getMemberMuteStatus(String userID) async {
|
||||
// Get the mute state of the members recursively
|
||||
if (widget.model.groupMemberList?.any((item) => (item?.userID == userID)) ??
|
||||
false) {
|
||||
final int muteUntil = widget.model.groupMemberList
|
||||
?.firstWhere((item) => (item?.userID == userID))
|
||||
?.muteUntil ??
|
||||
0;
|
||||
if (widget.model.groupMemberList?.any((item) => (item?.userID == userID)) ?? false) {
|
||||
final int muteUntil = widget.model.groupMemberList?.firstWhere((item) => (item?.userID == userID))?.muteUntil ?? 0;
|
||||
return muteUntil * 1000 > DateTime.now().millisecondsSinceEpoch;
|
||||
} else {
|
||||
return false;
|
||||
|
|
@ -924,42 +785,28 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
}
|
||||
|
||||
final int selfRole = widget.model.selfMemberInfo?.role ?? 0;
|
||||
final bool willNotBeenMuted =
|
||||
(selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN ||
|
||||
selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
|
||||
final bool willNotBeenMuted = (selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN || selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
|
||||
|
||||
if (widget.conversationType == ConvType.group && !willNotBeenMuted) {
|
||||
if ((model.groupInfo?.isAllMuted ?? false) &&
|
||||
muteStatus != MuteStatus.all) {
|
||||
if ((model.groupInfo?.isAllMuted ?? false) && muteStatus != MuteStatus.all) {
|
||||
Future.delayed(const Duration(seconds: 0), () {
|
||||
setState(() {
|
||||
muteStatus = MuteStatus.all;
|
||||
});
|
||||
});
|
||||
} else if (selfModel.loginInfo?.userID != null &&
|
||||
await getMemberMuteStatus(selfModel.loginInfo!.userID!) &&
|
||||
muteStatus != MuteStatus.me) {
|
||||
} else if (selfModel.loginInfo?.userID != null && await getMemberMuteStatus(selfModel.loginInfo!.userID!) && muteStatus != MuteStatus.me) {
|
||||
Future.delayed(const Duration(seconds: 0), () {
|
||||
setState(() {
|
||||
muteStatus = MuteStatus.me;
|
||||
});
|
||||
});
|
||||
} else if (!(model.groupInfo?.isAllMuted ?? false) &&
|
||||
!(selfModel.loginInfo?.userID != null &&
|
||||
await getMemberMuteStatus(selfModel.loginInfo!.userID!)) &&
|
||||
muteStatus != MuteStatus.none) {
|
||||
} else if (!(model.groupInfo?.isAllMuted ?? false) && !(selfModel.loginInfo?.userID != null && await getMemberMuteStatus(selfModel.loginInfo!.userID!)) && muteStatus != MuteStatus.none) {
|
||||
Future.delayed(const Duration(seconds: 0), () {
|
||||
setState(() {
|
||||
muteStatus = MuteStatus.none;
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Future.delayed(const Duration(seconds: 0), () {
|
||||
setState(() {
|
||||
muteStatus = MuteStatus.none;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -982,8 +829,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
final theme = value.theme;
|
||||
final TUIChatSeparateViewModel model =
|
||||
Provider.of<TUIChatSeparateViewModel>(context);
|
||||
final TUIChatSeparateViewModel model = Provider.of<TUIChatSeparateViewModel>(context);
|
||||
|
||||
_getMuteType(model);
|
||||
|
||||
|
|
@ -1003,8 +849,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
|||
}
|
||||
|
||||
final forbiddenText = getForbiddenText();
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
|
||||
inputWidth = constraints.maxWidth;
|
||||
return TUIKitScreenUtils.getDeviceWidget(
|
||||
context: context,
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.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';
|
||||
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_group_profile_model.dart';
|
||||
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/widgets/contact_list.dart';
|
||||
import 'package:tencent_im_base/tencent_im_base.dart';
|
||||
|
||||
GlobalKey<_AddGroupMemberPageState> addGroupMemberKey = GlobalKey();
|
||||
|
||||
class AddGroupMemberPage extends StatefulWidget {
|
||||
final TUIGroupProfileModel model;
|
||||
final VoidCallback? onClose;
|
||||
|
||||
const AddGroupMemberPage({Key? key, required this.model}) : super(key: key);
|
||||
const AddGroupMemberPage({Key? key, required this.model, this.onClose}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _AddGroupMemberPageState();
|
||||
|
|
@ -25,7 +25,7 @@ class _AddGroupMemberPageState extends TIMUIKitState<AddGroupMemberPage> {
|
|||
if (selectedContacts.isNotEmpty) {
|
||||
final userIDs = selectedContacts.map((e) => e.userID).toList();
|
||||
await widget.model.inviteUserToGroup(userIDs);
|
||||
Navigator.pop(context);
|
||||
widget.onClose ?? Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,8 +68,7 @@ class _AddGroupMemberPageState extends TIMUIKitState<AddGroupMemberPage> {
|
|||
)
|
||||
],
|
||||
shadowColor: theme.weakDividerColor,
|
||||
backgroundColor: theme.appbarBgColor ??
|
||||
theme.primaryColor,
|
||||
backgroundColor: theme.appbarBgColor ?? theme.primaryColor,
|
||||
iconTheme: IconThemeData(
|
||||
color: theme.appbarTextColor,
|
||||
)),
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.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';
|
||||
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_group_profile_model.dart';
|
||||
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/widgets/group_member_list.dart';
|
||||
import 'package:tencent_im_base/tencent_im_base.dart';
|
||||
|
||||
GlobalKey<_DeleteGroupMemberPageState> deleteGroupMemberKey = GlobalKey();
|
||||
|
||||
class DeleteGroupMemberPage extends StatefulWidget {
|
||||
final TUIGroupProfileModel model;
|
||||
final VoidCallback? onClose;
|
||||
|
||||
const DeleteGroupMemberPage({Key? key, required this.model})
|
||||
: super(key: key);
|
||||
const DeleteGroupMemberPage({Key? key, required this.model, this.onClose}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _DeleteGroupMemberPageState();
|
||||
|
|
@ -30,11 +29,8 @@ class _DeleteGroupMemberPageState extends TIMUIKitState<DeleteGroupMemberPage> {
|
|||
|
||||
handleSearchGroupMembers(String searchText, context) async {
|
||||
searchText = searchText;
|
||||
List<V2TimGroupMemberFullInfo?> currentGroupMember =
|
||||
Provider.of<TUIGroupProfileModel>(context, listen: false)
|
||||
.groupMemberList;
|
||||
final res =
|
||||
await widget.model.searchGroupMember(V2TimGroupMemberSearchParam(
|
||||
List<V2TimGroupMemberFullInfo?> currentGroupMember = Provider.of<TUIGroupProfileModel>(context, listen: false).groupMemberList;
|
||||
final res = await widget.model.searchGroupMember(V2TimGroupMemberSearchParam(
|
||||
keywordList: [searchText],
|
||||
groupIDList: [widget.model.groupInfo!.groupID],
|
||||
));
|
||||
|
|
@ -55,25 +51,19 @@ class _DeleteGroupMemberPageState extends TIMUIKitState<DeleteGroupMemberPage> {
|
|||
currentGroupMember = [];
|
||||
}
|
||||
setState(() {
|
||||
searchMemberList =
|
||||
isSearchTextExist(searchText) ? currentGroupMember : null;
|
||||
searchMemberList = isSearchTextExist(searchText) ? currentGroupMember : null;
|
||||
});
|
||||
}
|
||||
|
||||
handleRole(groupMemberList) {
|
||||
return groupMemberList
|
||||
?.where((value) =>
|
||||
value?.role ==
|
||||
GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER)
|
||||
.toList() ??
|
||||
[];
|
||||
return groupMemberList?.where((value) => value?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER).toList() ?? [];
|
||||
}
|
||||
|
||||
void submitDelete() async {
|
||||
if (selectedGroupMember.isNotEmpty) {
|
||||
final userIDs = selectedGroupMember.map((e) => e.userID).toList();
|
||||
widget.model.kickOffMember(userIDs);
|
||||
Navigator.pop(context);
|
||||
widget.onClose ?? Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -86,8 +76,7 @@ class _DeleteGroupMemberPageState extends TIMUIKitState<DeleteGroupMemberPage> {
|
|||
desktopWidget: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: GroupProfileMemberList(
|
||||
memberList:
|
||||
handleRole(searchMemberList ?? widget.model.groupMemberList),
|
||||
memberList: handleRole(searchMemberList ?? widget.model.groupMemberList),
|
||||
canSelectMember: true,
|
||||
canSlideDelete: false,
|
||||
onSelectedMemberChange: (selectedMember) {
|
||||
|
|
@ -115,14 +104,12 @@ class _DeleteGroupMemberPageState extends TIMUIKitState<DeleteGroupMemberPage> {
|
|||
)
|
||||
],
|
||||
shadowColor: theme.weakBackgroundColor,
|
||||
backgroundColor: theme.appbarBgColor ??
|
||||
theme.primaryColor,
|
||||
backgroundColor: theme.appbarBgColor ?? theme.primaryColor,
|
||||
iconTheme: IconThemeData(
|
||||
color: theme.appbarTextColor,
|
||||
)),
|
||||
body: GroupProfileMemberList(
|
||||
memberList:
|
||||
handleRole(searchMemberList ?? widget.model.groupMemberList),
|
||||
memberList: handleRole(searchMemberList ?? widget.model.groupMemberList),
|
||||
canSelectMember: true,
|
||||
canSlideDelete: false,
|
||||
onSelectedMemberChange: (selectedMember) {
|
||||
|
|
|
|||
|
|
@ -3,17 +3,15 @@
|
|||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.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/business_logic/separate_models/tui_group_profile_model.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/data_services/core/tim_uikit_wide_modal_operation_key.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroupProfile/group_member/tui_add_group_member.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroupProfile/group_member/tui_delete_group_member.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroupProfile/group_member/tui_group_member_list.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
|
||||
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/widgets/wide_popup.dart';
|
||||
import 'package:tencent_im_base/tencent_im_base.dart';
|
||||
|
||||
|
|
@ -38,8 +36,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
|
|||
return friendRemark != "" ? friendRemark : showName;
|
||||
}
|
||||
|
||||
List<Widget> _groupMemberListBuilder(List memberList, TUITheme theme,
|
||||
TUIGroupProfileModel model, int showRange) {
|
||||
List<Widget> _groupMemberListBuilder(List memberList, TUITheme theme, TUIGroupProfileModel model, int showRange) {
|
||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor() == DeviceType.Desktop;
|
||||
return _getMemberList(memberList, showRange).map((element) {
|
||||
final faceUrl = element?.faceUrl ?? "";
|
||||
|
|
@ -74,10 +71,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
|
|||
Text(
|
||||
showName,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: theme.weakTextColor,
|
||||
fontSize: 10),
|
||||
style: TextStyle(overflow: TextOverflow.ellipsis, color: theme.weakTextColor, fontSize: 10),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
@ -86,21 +80,17 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
|
|||
}).toList();
|
||||
}
|
||||
|
||||
List<Widget> _inviteMemberBuilder(bool isCanInviteMember,
|
||||
bool isCanKickOffMember, theme, BuildContext context) {
|
||||
List<Widget> _inviteMemberBuilder(bool isCanInviteMember, bool isCanKickOffMember, theme, BuildContext context) {
|
||||
return [];
|
||||
}
|
||||
|
||||
void navigateToMemberList(BuildContext context, TUIGroupProfileModel model,
|
||||
List<V2TimGroupMemberFullInfo?> memberList) {
|
||||
final isDesktopScreen =
|
||||
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||
void navigateToMemberList(BuildContext context, TUIGroupProfileModel model, List<V2TimGroupMemberFullInfo?> memberList) {
|
||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||
if (!isDesktopScreen) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => GroupProfileMemberListPage(
|
||||
model: model, memberList: memberList),
|
||||
builder: (context) => GroupProfileMemberListPage(model: model, memberList: memberList),
|
||||
));
|
||||
} else {
|
||||
final option1 = memberList.length.toString();
|
||||
|
|
@ -109,18 +99,15 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
|
|||
context: context,
|
||||
width: MediaQuery.of(context).size.width * 0.5,
|
||||
height: MediaQuery.of(context).size.height * 0.8,
|
||||
title: TIM_t_para("群成员({{option1}}人)", "群成员($option1人)")(
|
||||
option1: option1),
|
||||
child: (onClose) =>
|
||||
GroupProfileMemberListPage(model: model, memberList: memberList));
|
||||
title: TIM_t_para("群成员({{option1}}人)", "群成员($option1人)")(option1: option1),
|
||||
child: (onClose) => GroupProfileMemberListPage(model: model, memberList: memberList));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
final TUITheme theme = value.theme;
|
||||
final isDesktopScreen =
|
||||
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||
final model = Provider.of<TUIGroupProfileModel>(context);
|
||||
final memberAmount = model.groupInfo?.memberCount ?? 0;
|
||||
final option1 = memberAmount.toString();
|
||||
|
|
@ -144,13 +131,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
|
|||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
decoration: isDesktopScreen
|
||||
? null
|
||||
: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: theme.weakDividerColor ??
|
||||
CommonColor.weakDividerColor))),
|
||||
decoration: isDesktopScreen ? null : BoxDecoration(border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))),
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
navigateToMemberList(context, model, memberList);
|
||||
|
|
@ -158,18 +139,12 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(TIM_t("群成员"),
|
||||
style: TextStyle(
|
||||
color: theme.darkTextColor,
|
||||
fontSize: isDesktopScreen ? 14 : 16)),
|
||||
Text(TIM_t("群成员"), style: TextStyle(color: theme.darkTextColor, fontSize: isDesktopScreen ? 14 : 16)),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
TIM_t_para("{{option1}}人", "$option1人")(
|
||||
option1: option1),
|
||||
style: TextStyle(
|
||||
color: theme.darkTextColor,
|
||||
fontSize: isDesktopScreen ? 14 : 16),
|
||||
TIM_t_para("{{option1}}人", "$option1人")(option1: option1),
|
||||
style: TextStyle(color: theme.darkTextColor, fontSize: isDesktopScreen ? 14 : 16),
|
||||
),
|
||||
Icon(
|
||||
Icons.keyboard_arrow_right,
|
||||
|
|
@ -188,15 +163,11 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
|
|||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: theme.weakDividerColor ??
|
||||
CommonColor.weakDividerColor),
|
||||
border: Border.all(width: 1, color: theme.weakDividerColor ?? CommonColor.weakDividerColor),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||
),
|
||||
// height: 30,
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
|
|
@ -247,6 +218,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
|
|||
},
|
||||
child: (onClose) => AddGroupMemberPage(
|
||||
model: model,
|
||||
onClose: onClose,
|
||||
key: addGroupMemberKey,
|
||||
));
|
||||
} else {
|
||||
|
|
@ -285,11 +257,11 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
|
|||
title: TIM_t("删除群成员"),
|
||||
height: 460,
|
||||
onSubmit: () {
|
||||
deleteGroupMemberKey.currentState
|
||||
?.submitDelete();
|
||||
deleteGroupMemberKey.currentState?.submitDelete();
|
||||
},
|
||||
child: (onClose) => DeleteGroupMemberPage(
|
||||
model: model,
|
||||
onClose: onClose,
|
||||
key: deleteGroupMemberKey,
|
||||
),
|
||||
);
|
||||
|
|
@ -297,8 +269,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
|
|||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
DeleteGroupMemberPage(model: model),
|
||||
builder: (context) => DeleteGroupMemberPage(model: model),
|
||||
));
|
||||
}
|
||||
},
|
||||
|
|
@ -319,9 +290,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
|
|||
margin: EdgeInsets.only(top: isDesktopScreen ? 12 : 16),
|
||||
child: Text(
|
||||
TIM_t("查看更多群成员"),
|
||||
style: TextStyle(
|
||||
color: theme.weakTextColor,
|
||||
fontSize: isDesktopScreen ? 12 : 14),
|
||||
style: TextStyle(color: theme.weakTextColor, fontSize: isDesktopScreen ? 12 : 14),
|
||||
),
|
||||
),
|
||||
onTap: () async {
|
||||
|
|
|
|||
|
|
@ -13,12 +13,13 @@ class KeepAliveWrapper extends StatefulWidget {
|
|||
_KeepAliveWrapperState createState() => _KeepAliveWrapperState();
|
||||
}
|
||||
|
||||
class _KeepAliveWrapperState extends State<KeepAliveWrapper>
|
||||
with AutomaticKeepAliveClientMixin {
|
||||
class _KeepAliveWrapperState extends State<KeepAliveWrapper> with AutomaticKeepAliveClientMixin {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return widget.child;
|
||||
return RepaintBoundary(
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
name: tencent_cloud_chat_uikit
|
||||
description: A powerful chat UI component library and business logic for Tencent Cloud Chat, creating seamless in-app chat modules for delightful user experiences.
|
||||
version: 2.3.1
|
||||
version: 2.3.2
|
||||
homepage: https://trtc.io/products/chat?utm_source=gfs&utm_medium=link&utm_campaign=%E6%B8%A0%E9%81%93&_channel_track_key=k6WgfCKn
|
||||
repository: https://github.com/TencentCloud/chat-uikit-flutter
|
||||
documentation: https://comm.qq.com/im/doc/flutter/en/TUIKit/readme.html
|
||||
|
|
|
|||
Loading…
Reference in New Issue