chatapp3-flutter/lib/ui_kit/widgets/room/room_online_user_widget.dart
2026-04-20 22:40:22 +08:00

253 lines
8.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:provider/provider.dart';
import 'package:yumi/app/constants/sc_global_config.dart';
import 'package:yumi/ui_kit/components/sc_compontent.dart';
import 'package:yumi/ui_kit/components/text/sc_text.dart';
import 'package:yumi/shared/business_logic/models/res/login_res.dart';
import 'package:yumi/shared/tools/sc_lk_dialog_util.dart';
import 'package:yumi/services/room/rc_room_manager.dart';
import 'package:yumi/services/audio/rtc_manager.dart';
import 'package:yumi/modules/room/online/room_online_page.dart';
import 'package:yumi/modules/room/rank/room_gift_rank_page.dart';
class RoomOnlineUserWidget extends StatefulWidget {
const RoomOnlineUserWidget({super.key});
@override
State<RoomOnlineUserWidget> createState() => _RoomOnlineUserWidgetState();
}
class _RoomOnlineUserWidgetState extends State<RoomOnlineUserWidget> {
double get _onlineUsersShellHeight => 27.w;
double get _onlineUsersAvatarsWidth => 58.w;
double get _onlineUsersCounterWidth => 18.w;
double get _onlineUsersShellWidth =>
_onlineUsersAvatarsWidth + _onlineUsersCounterWidth;
void _openRoomOnlinePage() {
showBottomInBottomDialog(
context,
RoomOnlinePage(
roomId:
context
.read<RtcProvider>()
.currenRoom
?.roomProfile
?.roomProfile
?.id,
),
);
}
@override
Widget build(BuildContext context) {
return Selector<RtcProvider, _RoomOnlineUsersSnapshot>(
selector:
(context, provider) => _RoomOnlineUsersSnapshot(
onlineUsers: List<SocialChatUserProfile>.unmodifiable(
provider.onlineUsers,
),
),
builder: (context, onlineSnapshot, child) {
final onlineUsers = onlineSnapshot.onlineUsers;
return Row(
children: [
_buildExperience(),
SizedBox(width: 15.w),
Expanded(
child: Align(
alignment: Alignment.centerRight,
child:
onlineUsers.isNotEmpty
? _buildOnlineUsers(onlineUsers)
: _buildOnlineUsersPlaceholder(),
),
),
],
);
},
);
}
Widget _buildOnlineUsers(List<SocialChatUserProfile> onlineUsers) {
return Padding(
padding: EdgeInsets.only(right: 5.w),
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: _openRoomOnlinePage,
child: SizedBox(
width: _onlineUsersShellWidth,
height: _onlineUsersShellHeight,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: _onlineUsersAvatarsWidth,
height: 25.w,
child: Align(
alignment: Alignment.centerRight,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize: MainAxisSize.min,
children: List.generate(onlineUsers.length, (index) {
return Transform.translate(
offset: Offset(-3.w * index, 0),
child: Padding(
padding: EdgeInsets.only(right: 0.w),
child: netImage(
url: onlineUsers[index].userAvatar ?? "",
width: 23.w,
height: 23.w,
defaultImg:
SCGlobalConfig.businessLogicStrategy
.getMePageDefaultAvatarImage(),
shape: BoxShape.circle,
border: Border.all(
color: Colors.white,
width: 1.w,
),
),
),
);
}),
),
),
),
),
SizedBox(
width: _onlineUsersCounterWidth,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 3.w, vertical: 1.w),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
"sc_images/room/sc_icon_online_peple.png",
width: 12.w,
height: 12.sp,
),
text("${onlineUsers.length}", fontSize: 9, lineHeight: 1),
],
),
),
),
],
),
),
),
);
}
Widget _buildOnlineUsersPlaceholder() {
return Padding(
padding: EdgeInsets.only(right: 5.w),
child: SizedBox(
width: _onlineUsersShellWidth,
height: _onlineUsersShellHeight,
),
);
}
///房间榜单入口
_buildExperience() {
return Consumer<SocialChatRoomManager>(
builder: (context, ref, child) {
return GestureDetector(
child: Container(
constraints: BoxConstraints(minWidth: 90.w, maxWidth: 104.w),
height: 27.w,
padding: EdgeInsetsDirectional.only(start: 8.w, end: 4.w),
decoration: BoxDecoration(
color: Colors.white10,
borderRadius: BorderRadiusDirectional.only(
topEnd: Radius.circular(20.w),
bottomEnd: Radius.circular(20.w),
),
),
alignment: AlignmentDirectional.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
"sc_images/room/sc_icon_room_contribute.png",
width: 18.w,
height: 18.w,
),
SizedBox(width: 4.w),
Expanded(
child: FittedBox(
fit: BoxFit.scaleDown,
alignment: Alignment.centerLeft,
child: text(
"${ref.roomContributeLevelRes?.thisWeekIntegral ?? 0}",
fontSize: 13.sp,
textColor: Colors.orangeAccent,
fontWeight: FontWeight.w600,
),
),
),
Icon(
Icons.chevron_right,
size: 13.w,
color: Colors.orangeAccent,
),
],
),
),
onTap: () {
SmartDialog.show(
tag: "showRoomGiftRankPage",
alignment: Alignment.bottomCenter,
animationType: SmartAnimationType.fade,
builder: (_) {
return RoomGiftRankPage();
},
);
},
);
},
);
}
}
class _RoomOnlineUsersSnapshot {
const _RoomOnlineUsersSnapshot({required this.onlineUsers});
final List<SocialChatUserProfile> onlineUsers;
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (other is! _RoomOnlineUsersSnapshot ||
other.onlineUsers.length != onlineUsers.length) {
return false;
}
for (int index = 0; index < onlineUsers.length; index++) {
final currentUser = onlineUsers[index];
final otherUser = other.onlineUsers[index];
if (currentUser.id != otherUser.id ||
currentUser.userAvatar != otherUser.userAvatar ||
currentUser.userNickname != otherUser.userNickname ||
currentUser.roles != otherUser.roles ||
currentUser.heartbeatVal != otherUser.heartbeatVal) {
return false;
}
}
return true;
}
@override
int get hashCode => Object.hashAll(
onlineUsers.map((user) => Object.hash(user.id, user.userAvatar)),
);
}