feat: 群组信息自定义

This commit is contained in:
Zeew 2025-07-15 22:14:08 +08:00
parent a7149a29c3
commit e5d1225f7a
3 changed files with 244 additions and 128 deletions

View File

@ -18,29 +18,57 @@ import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme_view_model.dart';
typedef GroupItemBuilder = Widget Function(BuildContext context, V2TimGroupInfo groupInfo);
typedef GroupItemBuilder =
Widget Function(BuildContext context, V2TimGroupInfo groupInfo);
/// TIMUIKitGroup State的类型定义
typedef TIMUIKitGroupState = _TIMUIKitGroupState;
class TIMUIKitGroup extends StatefulWidget {
final void Function(V2TimGroupInfo groupInfo, V2TimConversation conversation)? onTapItem;
final void Function(V2TimGroupInfo groupInfo, V2TimConversation conversation)?
onTapItem;
final Widget Function(BuildContext context)? emptyBuilder;
final GroupItemBuilder? itemBuilder;
/// the filter for group conversation
final bool Function(V2TimGroupInfo? groupInfo)? groupCollector;
const TIMUIKitGroup({Key? key, this.onTapItem, this.emptyBuilder, this.itemBuilder, this.groupCollector})
: super(key: key);
const TIMUIKitGroup({
Key? key,
this.onTapItem,
this.emptyBuilder,
this.itemBuilder,
this.groupCollector,
}) : super(key: key);
@override
State<StatefulWidget> createState() => _TIMUIKitGroupState();
///
/// Static method to refresh group list data
static void refreshGroupListData(GlobalKey<TIMUIKitGroupState> key) {
key.currentState?.refreshGroupListData();
}
}
class _TIMUIKitGroupState extends TIMUIKitState<TIMUIKitGroup> {
final TUIFriendShipViewModel _friendshipViewModel = serviceLocator<TUIFriendShipViewModel>();
final TUIGroupListenerModel _groupListenerModel = serviceLocator<TUIGroupListenerModel>();
final TUIFriendShipViewModel _friendshipViewModel =
serviceLocator<TUIFriendShipViewModel>();
final TUIGroupListenerModel _groupListenerModel =
serviceLocator<TUIGroupListenerModel>();
List<ISuspensionBeanImpl<V2TimGroupInfo>> _getShowList(List<V2TimGroupInfo> groupList) {
final List<ISuspensionBeanImpl<V2TimGroupInfo>> showList = List.empty(growable: true);
///
/// Refresh group list data
void refreshGroupListData() {
_friendshipViewModel.loadGroupListData();
}
List<ISuspensionBeanImpl<V2TimGroupInfo>> _getShowList(
List<V2TimGroupInfo> groupList,
) {
final List<ISuspensionBeanImpl<V2TimGroupInfo>> showList = List.empty(
growable: true,
);
for (var i = 0; i < groupList.length; i++) {
final item = groupList[i];
@ -63,10 +91,16 @@ class _TIMUIKitGroupState extends TIMUIKitState<TIMUIKitGroup> {
final theme = Provider.of<TUIThemeViewModel>(context).theme;
final showName = groupInfo.groupName ?? groupInfo.groupID;
final faceUrl = groupInfo.faceUrl ?? "";
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
final isDesktopScreen =
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
return Container(
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))),
border: Border(
bottom: BorderSide(
color: theme.weakDividerColor ?? CommonColor.weakDividerColor,
),
),
),
child: Material(
color: isDesktopScreen ? theme.wideBackgroundColor : null,
child: InkWell(
@ -82,7 +116,9 @@ class _TIMUIKitGroupState extends TIMUIKitState<TIMUIKitGroup> {
);
final res = await TencentImSDKPlugin.v2TIMManager
.getConversationManager()
.getConversation(conversationID: "group_${groupInfo.groupID}");
.getConversation(
conversationID: "group_${groupInfo.groupID}",
);
if (res.code == 0 && res.data != null) {
conversation = res.data!;
}
@ -112,9 +148,13 @@ class _TIMUIKitGroupState extends TIMUIKitState<TIMUIKitGroup> {
padding: const EdgeInsets.only(top: 10, bottom: 20),
child: Text(
showName,
style: TextStyle(color: Colors.black, fontSize: isDesktopScreen ? 14 : 18),
style: TextStyle(
color: Colors.black,
fontSize: isDesktopScreen ? 14 : 18,
),
),
),
),
))
],
),
),
@ -139,10 +179,14 @@ class _TIMUIKitGroupState extends TIMUIKitState<TIMUIKitGroup> {
providers: [
ChangeNotifierProvider.value(value: _friendshipViewModel),
ChangeNotifierProvider.value(value: _groupListenerModel),
ChangeNotifierProvider.value(value: serviceLocator<TUIThemeViewModel>()),
ChangeNotifierProvider.value(
value: serviceLocator<TUIThemeViewModel>(),
),
],
builder: (BuildContext context, Widget? w) {
final NeedUpdate? needUpdate = Provider.of<TUIGroupListenerModel>(context).needUpdate;
final NeedUpdate? needUpdate = Provider.of<TUIGroupListenerModel>(
context,
).needUpdate;
if (needUpdate != null) {
_groupListenerModel.needUpdate = null;
switch (needUpdate.updateType) {
@ -156,7 +200,9 @@ class _TIMUIKitGroupState extends TIMUIKitState<TIMUIKitGroup> {
break;
}
}
List<V2TimGroupInfo> groupList = Provider.of<TUIFriendShipViewModel>(context).groupList;
List<V2TimGroupInfo> groupList = Provider.of<TUIFriendShipViewModel>(
context,
).groupList;
if (widget.groupCollector != null) {
groupList = groupList.where(widget.groupCollector!).toList();
}
@ -169,7 +215,8 @@ class _TIMUIKitGroupState extends TIMUIKitState<TIMUIKitGroup> {
final groupInfo = showList[index].memberInfo;
final itemBuilder = _getItemBuilder();
return itemBuilder(context, groupInfo);
});
},
);
}
if (widget.emptyBuilder != null) {

View File

@ -20,8 +20,13 @@ import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class GroupMemberTitle extends TIMUIKitStatelessWidget {
final VoidCallback? onAddMemberPressed;
final VoidCallback? onRemoveMemberPressed;
GroupMemberTitle({
Key? key,
this.onAddMemberPressed,
this.onRemoveMemberPressed,
}) : super(key: key);
List<V2TimGroupMemberFullInfo?> _getMemberList(memberList, int showRange) {
@ -40,8 +45,14 @@ class GroupMemberTitle extends TIMUIKitStatelessWidget {
return friendRemark != "" ? friendRemark : showName;
}
List<Widget> _groupMemberListBuilder(List memberList, TUITheme theme, TUIGroupProfileModel model, int showRange) {
final isDesktopScreen = TUIKitScreenUtils.getFormFactor() == DeviceType.Desktop;
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 ?? "";
final showName = _getShowName(element);
@ -61,22 +72,25 @@ class GroupMemberTitle extends TIMUIKitStatelessWidget {
width: isDesktopScreen ? 36 : 50,
height: isDesktopScreen ? 36 : 50,
child: Avatar(
borderRadius: isDesktopScreen ? BorderRadius.circular(18) : null,
borderRadius: isDesktopScreen
? BorderRadius.circular(18)
: null,
faceUrl: faceUrl,
showName: showName,
type: 1,
),
),
if (!isDesktopScreen)
const SizedBox(
height: 8,
),
if (!isDesktopScreen) const SizedBox(height: 8),
if (!isDesktopScreen)
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,
),
),
],
),
),
@ -84,19 +98,30 @@ class GroupMemberTitle 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;
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();
TUIKitWidePopup.showPopupWindow(
@ -104,15 +129,20 @@ class GroupMemberTitle 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();
@ -139,7 +169,14 @@ class GroupMemberTitle extends TIMUIKitStatelessWidget {
decoration: isDesktopScreen
? null
: BoxDecoration(
border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))),
border: Border(
bottom: BorderSide(
color:
theme.weakDividerColor ??
CommonColor.weakDividerColor,
),
),
),
child: InkWell(
onTap: () async {
navigateToMemberList(context, model, memberList);
@ -147,19 +184,30 @@ class GroupMemberTitle 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,
color: theme.weakTextColor,
),
],
)
),
],
),
),
@ -171,25 +219,30 @@ class GroupMemberTitle 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: [
Icon(
Icons.search,
color: hexToColor("979797"),
size: 16,
),
Icon(Icons.search, color: hexToColor("979797"), size: 16),
const SizedBox(width: 6),
Text(TIM_t("搜索"),
Text(
TIM_t("搜索"),
style: TextStyle(
color: theme.weakTextColor,
fontSize: 12,
)),
),
),
],
),
),
@ -214,10 +267,14 @@ class GroupMemberTitle extends TIMUIKitStatelessWidget {
height: isDesktopScreen ? 32 : 48,
child: IconButton(
onPressed: () {
if (onAddMemberPressed != null) {
onAddMemberPressed!();
} else {
if (isDesktopScreen) {
TUIKitWidePopup.showPopupWindow(
context: context,
operationKey: TUIKitWideModalOperationKey.addGroupMembers,
operationKey:
TUIKitWideModalOperationKey.addGroupMembers,
width: 350,
title: TIM_t("添加群成员"),
height: 460,
@ -228,24 +285,24 @@ class GroupMemberTitle extends TIMUIKitStatelessWidget {
model: model,
onClose: onClose,
key: addGroupMemberKey,
));
),
);
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddGroupMemberPage(
model: model,
builder: (context) =>
AddGroupMemberPage(model: model),
),
));
);
}
}
},
icon: Icon(
Icons.add,
size: isDesktopScreen ? 16 : 18,
),
icon: Icon(Icons.add, size: isDesktopScreen ? 16 : 18),
color: theme.weakTextColor,
),
)),
),
),
if (isCanKickOffMember)
DottedBorder(
borderType: BorderType.RRect,
@ -257,15 +314,20 @@ class GroupMemberTitle extends TIMUIKitStatelessWidget {
height: isDesktopScreen ? 32 : 48,
child: IconButton(
onPressed: () {
if (onRemoveMemberPressed != null) {
onRemoveMemberPressed!();
} else {
if (isDesktopScreen) {
TUIKitWidePopup.showPopupWindow(
operationKey: TUIKitWideModalOperationKey.kickOffGroupMembers,
operationKey: TUIKitWideModalOperationKey
.kickOffGroupMembers,
context: context,
width: 350,
title: TIM_t("删除群成员"),
height: 460,
onSubmit: () {
deleteGroupMemberKey.currentState?.submitDelete();
deleteGroupMemberKey.currentState
?.submitDelete();
},
child: (onClose) => DeleteGroupMemberPage(
model: model,
@ -277,8 +339,11 @@ class GroupMemberTitle extends TIMUIKitStatelessWidget {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DeleteGroupMemberPage(model: model),
));
builder: (context) =>
DeleteGroupMemberPage(model: model),
),
);
}
}
},
icon: Icon(
@ -287,7 +352,8 @@ class GroupMemberTitle extends TIMUIKitStatelessWidget {
),
color: theme.weakTextColor,
),
)),
),
),
],
),
),
@ -298,7 +364,10 @@ class GroupMemberTitle 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 {

View File

@ -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: 5.0.1
version: 5.0.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