chatapp3-flutter/lib/ui_kit/widgets/room/room_user_info_card.dart
2026-04-09 21:32:23 +08:00

958 lines
51 KiB
Dart

import 'dart:convert';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:yumi/app_localizations.dart';
import 'package:yumi/main.dart';
import 'package:yumi/ui_kit/components/sc_debounce_widget.dart';
import 'package:yumi/ui_kit/components/text/sc_text.dart';
import 'package:yumi/shared/data_sources/sources/local/user_manager.dart';
import 'package:yumi/modules/index/main_route.dart';
import 'package:yumi/services/audio/rtm_manager.dart';
import 'package:yumi/ui_kit/widgets/room/room_msg_input.dart';
import 'package:yumi/ui_kit/widgets/room/room_user_card_setting.dart';
import 'package:marquee/marquee.dart';
import 'package:provider/provider.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/enum/conversation_type.dart';
import 'package:yumi/ui_kit/components/sc_compontent.dart';
import 'package:yumi/ui_kit/components/sc_tts.dart';
import 'package:yumi/app/routes/sc_fluro_navigator.dart';
import 'package:yumi/shared/tools/sc_lk_dialog_util.dart';
import 'package:yumi/shared/tools/sc_room_utils.dart';
import 'package:yumi/shared/data_sources/sources/repositories/sc_room_repository_imp.dart';
import 'package:yumi/shared/data_sources/sources/repositories/sc_user_repository_impl.dart';
import 'package:yumi/shared/business_logic/models/res/login_res.dart';
import 'package:yumi/shared/business_logic/models/res/user_count_guard_res.dart';
import 'package:yumi/services/general/sc_app_general_manager.dart';
import 'package:yumi/services/audio/rtc_manager.dart';
import 'package:yumi/services/auth/user_profile_manager.dart';
import 'package:yumi/modules/gift/gift_page.dart';
import '../../../shared/data_sources/models/enum/sc_room_roles_type.dart';
import '../../../shared/business_logic/models/res/sc_user_identity_res.dart';
import '../../../modules/chat/chat_route.dart';
class RoomUserInfoCard extends StatefulWidget {
String? userId;
RoomUserInfoCard({super.key, this.userId});
@override
_RoomUserInfoCardState createState() => _RoomUserInfoCardState();
}
class _RoomUserInfoCardState extends State<RoomUserInfoCard> {
SocialChatUserProfileManager? userProvider;
String roomId = "";
SCUserIdentityRes? userIdentity;
@override
void initState() {
super.initState();
userProvider = Provider.of<SocialChatUserProfileManager>(
context,
listen: false,
);
roomId =
Provider.of<RtcProvider>(
context,
listen: false,
).currenRoom?.roomProfile?.roomProfile?.id ??
"";
userProvider?.roomUserCard(roomId, widget.userId ?? "");
SCAccountRepository().userIdentity(userId: widget.userId).then((v) {
userIdentity = v;
setState(() {});
});
}
@override
void dispose() {
super.dispose();
userProvider?.userCardInfo = null;
}
@override
Widget build(BuildContext context) {
return SafeArea(
top: false,
child: Consumer<SocialChatUserProfileManager>(
builder: (context, ref, child) {
if (ref.userCardInfo == null) {
return SizedBox(
height: ScreenUtil().screenHeight * 0.7,
child: Center(
child: Container(
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(8),
),
width: 55.w,
height: 55.w,
child: CupertinoActivityIndicator(color: Colors.white24),
),
),
);
}
return Container(
constraints: BoxConstraints(
maxHeight: ScreenUtil().screenHeight * 0.7,
),
margin: EdgeInsets.symmetric(horizontal: 15.w),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Stack(
alignment: Alignment.center,
children: [
Container(
margin: EdgeInsets.only(
top:
ref.userCardInfo?.userProfile
?.getDataCard()
?.sourceUrl !=
null
? 45.w
: 55.w,
),
child: Stack(
children: [
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors:
ref.userCardInfo?.userProfile
?.getDataCard()
?.sourceUrl !=
null
? [
Colors.transparent,
Colors.transparent,
]
: [
Color(0xff18F2B1),
Color(0xffE4FFF6),
Color(0xffE4FFF6),
Color(0xffE4FFF6),
Color(0xffE4FFF6),
Color(0xffE4FFF6),
Color(0xffE4FFF6),
Color(0xffFFFFFF),
],
),
borderRadius: BorderRadius.all(
Radius.circular(12.w),
),
),
child: Stack(
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
SizedBox(height: 25.w),
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
SizedBox(width: 20.w),
GestureDetector(
child: head(
url:
ref
.userCardInfo
?.userProfile
?.userAvatar ??
"",
width: 55.w,
border: Border.all(
color: Colors.white,
width: 2,
),
headdress:
ref.userCardInfo?.userProfile
?.getHeaddress()
?.sourceUrl,
),
onTap: () {
SCNavigatorUtils.push(
context,
"${SCMainRoute.person}?isMe=${AccountStorage().getCurrentUser()?.userProfile?.id == widget.userId}&tageId=${widget.userId}",
);
},
),
SizedBox(width: 3.w),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Row(
children: [
msgRoleTag(
ref
.userCardInfo
?.roomRole ??
"",
width: 16.w,
height: 16.w,
),
SizedBox(width: 2.w),
socialchatNickNameText(
maxWidth: 115.w,
ref
.userCardInfo
?.userProfile
?.userNickname ??
"",
fontSize: 14.sp,
textColor: Colors.black,
fontWeight: FontWeight.bold,
type: "",
needScroll:
(ref
.userCardInfo
?.userProfile
?.userNickname
?.characters
.length ??
0) >
10,
),
],
),
SizedBox(height: 2.w),
text(
"ID:${ref.userCardInfo?.userProfile?.getID() ?? 0}",
fontSize: 12.sp,
textColor: Colors.black,
fontWeight: FontWeight.bold,
),
],
),
],
),
Row(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(15.w),
color: Colors.transparent,
),
padding: EdgeInsets.symmetric(
horizontal: 10.w,
vertical: 5.w,
),
child: Row(
children: [
SizedBox(width: 20.w,),
netImage(
url:
Provider.of<
SCAppGeneralManager
>(
context,
listen: false,
)
.findCountryByName(
ref
.userCardInfo
?.userProfile
?.countryName ??
"",
)
?.nationalFlag ??
"",
borderRadius:
BorderRadius.all(
Radius.circular(3.w),
),
width: 19.w,
height: 14.w,
),
SizedBox(width: 5.w),
Container(
constraints: BoxConstraints(
maxWidth: 110.w,
),
child: text(
ref
.userCardInfo
?.userProfile
?.countryName ??
"",
textColor: Colors.black,
fontSize: 12.sp,
fontWeight: FontWeight.bold,
),
),
],
),
),
SizedBox(width: 5.w),
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
ref
.userCardInfo
?.userProfile
?.userSex ==
0
? "sc_images/login/sc_icon_sex_woman_bg.png"
: "sc_images/login/sc_icon_sex_man_bg.png",
),
),
),
padding: EdgeInsets.symmetric(
horizontal: 10.w,
vertical: 5.w,
),
child: Row(
children: [
xb(
ref
.userCardInfo
?.userProfile
?.userSex,
),
SizedBox(width: 3.w),
text(
"${ref.userCardInfo?.userProfile?.age ?? 0}",
textColor: Colors.white,
fontSize: 12.sp,
fontWeight: FontWeight.bold,
),
],
),
),
],
),
SizedBox(height: 15.w),
Container(
margin: EdgeInsets.symmetric(
horizontal: 25.w,
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
widget.userId !=
AccountStorage()
.getCurrentUser()
?.userProfile
?.id
? SCDebounceWidget(
child: Column(
children: [
Image.asset(
"sc_images/room/sc_icon_send_user_message.png",
width: 32.w,
height: 32.w,
),
SizedBox(height: 5.w),
Container(
alignment:
Alignment.center,
width: 70.w,
child: text(
SCAppLocalizations.of(
context,
)!.sayHi2,
textColor: Color(
0xff808080,
),
fontWeight:
FontWeight.w600,
fontSize: 14.sp,
),
),
],
),
onTap: () async {
Navigator.of(context).pop();
var conversation =
V2TimConversation(
type:
ConversationType
.V2TIM_C2C,
userID: widget.userId,
conversationID: '',
);
var bool =
await Provider.of<
RtmProvider
>(
context,
listen: false,
).startConversation(
conversation,
);
if (!bool) return;
var json = jsonEncode(
conversation.toJson(),
);
SCNavigatorUtils.push(
navigatorKey.currentState!.context,
"${SCChatRouter.chat}?conversation=${Uri.encodeComponent(json)}",
);
},
)
: Container(),
widget.userId !=
AccountStorage()
.getCurrentUser()
?.userProfile
?.id
? SCDebounceWidget(
child: Selector<
SocialChatUserProfileManager,
bool
>(
selector:
(context, provider) =>
provider
.userCardInfo
?.follow ??
false,
shouldRebuild:
(prev, next) =>
prev != next,
builder: (
context,
follow,
_,
) {
return Column(
children: [
Image.asset(
follow
? "sc_images/room/sc_icon_user_un_follow.png"
: "sc_images/room/sc_icon_user_follow.png",
width: 32.w,
height: 32.w,
),
SizedBox(height: 5.w),
Container(
alignment:
Alignment
.center,
width: 70.w,
child: text(
// 使用 Flutter 内置 Text
follow
? SCAppLocalizations.of(
context,
)!.followed
: SCAppLocalizations.of(
context,
)!.follow, //
fontSize: 14.sp,
textColor: Color(
0xff808080,
),
fontWeight:
FontWeight
.bold,
),
),
],
);
},
),
onTap: () {
// ✅ 使用正确的 Provider 访问方式
final provider = Provider.of<
SocialChatUserProfileManager
>(context, listen: false);
provider.followUser(
widget.userId ?? "",
);
},
)
: Container(),
widget.userId !=
AccountStorage()
.getCurrentUser()
?.userProfile
?.id
? SCDebounceWidget(
child: Column(
children: [
Image.asset(
"sc_images/room/sc_icon_at_tag_user.png",
width: 32.w,
height: 32.w,
),
SizedBox(height: 5.w),
Container(
alignment:
Alignment.center,
width: 70.w,
child: text(
SCAppLocalizations.of(
context,
)!.atTag,
textColor: Color(
0xff808080,
),
fontWeight:
FontWeight.w600,
fontSize: 14.sp,
),
),
],
),
onTap: () async {
if (SCRoomUtils.touristCanMsg(
context,
)) {
if ((ref
.userCardInfo
?.userProfile
?.userNickname ??
"")
.isEmpty) {
return;
}
Navigator.of(
context,
).pop();
Navigator.push(
context,
PopRoute(
child: RoomMsgInput(
atTextContent:
"<user id=\"${widget.userId}\">${ref.userCardInfo?.userProfile?.userNickname}</user>",
),
),
);
}
},
)
: Container(),
widget.userId !=
AccountStorage()
.getCurrentUser()
?.userProfile
?.id
? SCDebounceWidget(
child: Column(
children: [
Image.asset(
"sc_images/room/sc_icon_send_user_gift.png",
width: 32.w,
height: 32.w,
),
SizedBox(height: 5.w),
Container(
alignment:
Alignment.center,
width: 70.w,
child: text(
SCAppLocalizations.of(
context,
)!.send,
textColor: Color(
0xff808080,
),
fontWeight:
FontWeight.w600,
fontSize: 14.sp,
),
),
],
),
onTap: () {
Navigator.of(context).pop();
SmartDialog.show(
tag: "showGiftControl",
alignment:
Alignment
.bottomCenter,
maskColor:
Colors.transparent,
animationType:
SmartAnimationType
.fade,
clickMaskDismiss: true,
builder: (_) {
return GiftPage(
toUser:
ref
.userCardInfo
?.userProfile,
);
},
);
},
)
: Container(),
],
),
),
SizedBox(height: 35.w),
],
),
],
),
),
AccountStorage()
.getCurrentUser()
?.userProfile
?.id !=
widget.userId
? Positioned(
top:28.w,
right: 15.w,
child: GestureDetector(
child: Image.asset(
"sc_images/room/sc_icon_user_card_report.png",
width: 24.w,
height: 24.w,
color: Colors.black,
),
onTap: () {
SCNavigatorUtils.push(
context,
"${SCMainRoute.report}?type=user&tageId=${widget.userId}",
replace: false,
);
},
),
)
: Container(),
ref.userCardInfo?.roomRole ==
SCRoomRolesType.HOMEOWNER.name
? Container()
: (AccountStorage()
.getCurrentUser()
?.userProfile
?.id !=
widget.userId &&
Provider.of<RtcProvider>(
context,
listen: false,
).isFz() ||
AccountStorage()
.getCurrentUser()
?.userProfile
?.id !=
widget.userId &&
Provider.of<RtcProvider>(
context,
listen: false,
).isGL())
? Positioned(
top:28.w,
right: 45.w,
child: GestureDetector(
child: Image.asset(
"sc_images/room/sc_icon_room_user_card_setting.png",
width: 24.w,
height: 24.w,
color: Colors.black,
),
onTap: () {
if (userProvider?.userCardInfo != null) {
Navigator.of(context).pop();
showBottomInBottomDialog(
context!,
RoomUserCardSetting(
roomId: roomId,
userCardInfo:
userProvider?.userCardInfo
?.copyWith(),
),
);
}
},
),
)
: Container(),
],
),
),
],
),
],
),
),
);
},
),
);
}
String roleName(String role) {
if (role == SCRoomRolesType.HOMEOWNER.name) {
return SCAppLocalizations.of(context)!.owner;
} else if (role == SCRoomRolesType.ADMIN.name) {
return SCAppLocalizations.of(context)!.admin;
} else if (role == SCRoomRolesType.MEMBER.name) {
return SCAppLocalizations.of(context)!.member;
}
return SCAppLocalizations.of(context)!.guest;
}
_buildEmptyCpItem(bool canAdd) {
return Container(
width: ScreenUtil().screenWidth,
margin: EdgeInsets.symmetric(horizontal: 12.w),
height: 105.w,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
canAdd
? "sc_images/person/sc_icon_no_cp_item_bg.png"
: "sc_images/person/sc_icon_no_cp_item_bg4.png",
),
fit: BoxFit.fill,
),
),
child: Container(
margin: EdgeInsets.only(bottom: 13.w),
alignment: AlignmentDirectional.bottomCenter,
child: text(
SCAppLocalizations.of(context)!.noMatchedCP,
fontWeight: FontWeight.w600,
fontSize: 12.sp,
textColor: canAdd ? Color(0xFFFF79A1) : Colors.white,
),
),
);
}
Widget _buildCpItem(CPRes item) {
return Stack(
alignment: AlignmentDirectional.center,
children: [
Container(
width: ScreenUtil().screenWidth,
margin: EdgeInsets.symmetric(horizontal: 15.w),
height: 135.w,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("sc_images/person/sc_icon_no_cp_item_bg2.png"),
fit: BoxFit.fill,
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 68.w),
Container(
alignment: AlignmentDirectional.bottomCenter,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
"sc_images/person/sc_icon_cp_value_tag.png",
height: 18.w,
),
SizedBox(width: 5.w),
text(
_cpVaFormat(item.cpValue ?? 0),
fontWeight: FontWeight.w600,
fontSize: 12.sp,
textColor: Color(0xFFFF79A1),
),
],
),
),
SizedBox(height: 8.w),
Container(
alignment: AlignmentDirectional.bottomCenter,
child: text(
SCAppLocalizations.of(
context,
)!.timeSpentTogether(item.days ?? ""),
fontWeight: FontWeight.w600,
fontSize: 12.sp,
textColor: Color(0xFFFF79A1),
),
),
Container(
alignment: AlignmentDirectional.bottomCenter,
child: text(
SCAppLocalizations.of(context)!.firstDay(item.firstDay ?? ""),
fontWeight: FontWeight.w600,
fontSize: 11.sp,
textColor: Colors.white,
),
),
],
),
),
PositionedDirectional(
top: 30.w,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
GestureDetector(
child: SizedBox(
height: 50.w,
child: Stack(
alignment: AlignmentDirectional.center,
children: [
netImage(
url: item.meUserAvatar ?? "",
width: 48.w,
shape: BoxShape.circle,
defaultImg:
"sc_images/general/sc_icon_avar_defalt.png",
),
Image.asset(
"sc_images/person/sc_icon_cp_head_ring.png",
),
],
),
),
onTap: () {
SCNavigatorUtils.push(
context,
replace: false,
"${SCMainRoute.person}?isMe=${AccountStorage().getCurrentUser()?.userProfile?.id == item.meUserId}&tageId=${item.meUserId}",
);
},
),
Container(
alignment: Alignment.center,
width: 80.w,
height: 15.w,
child:
(item.meUserNickname?.length ?? 0) > 8
? Marquee(
text: item.meUserNickname ?? "",
style: TextStyle(
fontSize: 10.sp,
color: Colors.white,
fontWeight: FontWeight.w600,
decoration: TextDecoration.none,
),
scrollAxis: Axis.horizontal,
crossAxisAlignment: CrossAxisAlignment.start,
blankSpace: 20.0,
velocity: 40.0,
pauseAfterRound: Duration(seconds: 1),
accelerationDuration: Duration(seconds: 1),
accelerationCurve: Curves.easeOut,
decelerationDuration: Duration(milliseconds: 550),
decelerationCurve: Curves.easeOut,
)
: Text(
item.meUserNickname ?? "",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 10.sp,
color: Colors.white,
fontWeight: FontWeight.w600,
decoration: TextDecoration.none,
),
),
),
],
),
SizedBox(width: 120.w),
Column(
children: [
GestureDetector(
child: SizedBox(
height: 50.w,
child: Stack(
alignment: AlignmentDirectional.center,
children: [
netImage(
url: item.cpUserAvatar ?? "",
width: 48.w,
shape: BoxShape.circle,
defaultImg:
"sc_images/general/sc_icon_avar_defalt.png",
),
Image.asset(
"sc_images/person/sc_icon_cp_head_ring.png",
),
],
),
),
onTap: () {
SCNavigatorUtils.push(
context,
replace: false,
"${SCMainRoute.person}?isMe=${AccountStorage().getCurrentUser()?.userProfile?.id == item.cpUserId}&tageId=${item.cpUserId}",
);
},
),
Container(
alignment: Alignment.center,
width: 80.w,
height: 15.w,
child:
(item.cpUserNickname?.length ?? 0) > 8
? Marquee(
text: item.cpUserNickname ?? "",
style: TextStyle(
fontSize: 10.sp,
color: Colors.white,
fontWeight: FontWeight.w600,
decoration: TextDecoration.none,
),
scrollAxis: Axis.horizontal,
crossAxisAlignment: CrossAxisAlignment.start,
blankSpace: 20.0,
velocity: 40.0,
pauseAfterRound: Duration(seconds: 1),
accelerationDuration: Duration(seconds: 1),
accelerationCurve: Curves.easeOut,
decelerationDuration: Duration(milliseconds: 550),
decelerationCurve: Curves.easeOut,
)
: Text(
item.cpUserNickname ?? "",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 10.sp,
color: Colors.white,
fontWeight: FontWeight.w600,
decoration: TextDecoration.none,
),
),
),
],
),
],
),
),
],
);
}
String getUserCardBg() {
return "";
}
String _cpVaFormat(double cpValue) {
int value = cpValue.toInt();
if (value > 99999) {
return "${(value / 1000).toStringAsFixed(0)}k";
}
return "$value";
}
}