You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
444 lines
22 KiB
444 lines
22 KiB
import 'package:dating_touchme_app/controller/discover/room_controller.dart';
|
|
import 'package:dating_touchme_app/controller/overlay_controller.dart';
|
|
import 'package:dating_touchme_app/generated/assets.dart';
|
|
import 'package:dating_touchme_app/widget/live/disconnect_mic_dialog.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:tdesign_flutter/tdesign_flutter.dart';
|
|
|
|
/// 直播间顶部用户信息与操作区域
|
|
class LiveRoomUserHeader extends StatelessWidget {
|
|
const LiveRoomUserHeader({
|
|
super.key,
|
|
required this.userName,
|
|
required this.popularityText,
|
|
this.avatarAsset = Assets.imagesUserAvatar,
|
|
this.fireIconAsset = Assets.imagesFireIcon,
|
|
this.closeIconAsset = Assets.imagesCloseArrow,
|
|
this.onFollowTap,
|
|
this.onCloseTap,
|
|
});
|
|
|
|
final String userName;
|
|
final String popularityText;
|
|
final String avatarAsset;
|
|
final String fireIconAsset;
|
|
final String closeIconAsset;
|
|
final VoidCallback? onFollowTap;
|
|
final VoidCallback? onCloseTap;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// 获取 RoomController 判断当前用户角色
|
|
final roomController = Get.find<RoomController>();
|
|
final overlayController = Get.find<OverlayController>();
|
|
final isHost = roomController.currentRole == CurrentRole.broadcaster;
|
|
|
|
return Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Container(
|
|
height: 40.w,
|
|
padding: EdgeInsets.symmetric(horizontal: 3.w),
|
|
margin: EdgeInsets.only(left: 10.w),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.all(Radius.circular(40.w)),
|
|
color: const Color.fromRGBO(0, 0, 0, .25),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
// 支持网络图片和本地资源
|
|
ClipOval(
|
|
child: Image.network(
|
|
avatarAsset,
|
|
width: 34.w,
|
|
height: 34.w,
|
|
fit: BoxFit.cover,
|
|
errorBuilder: (context, error, stackTrace) {
|
|
return Image.asset(
|
|
Assets.imagesUserAvatar,
|
|
width: 34.w,
|
|
height: 34.w,
|
|
);
|
|
},
|
|
),
|
|
),
|
|
SizedBox(width: 7.w),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Text(
|
|
userName,
|
|
style: TextStyle(fontSize: 13.w, color: Colors.white),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Row(
|
|
children: [
|
|
// 只有主持人才显示直播设置按钮
|
|
if (isHost)
|
|
GestureDetector(
|
|
onTap: () {
|
|
roomController.setDialogDismiss(true);
|
|
SmartDialog.showAttach(
|
|
targetContext: context,
|
|
onDismiss: (){
|
|
roomController.setDialogDismiss(false);
|
|
},
|
|
builder: (context) {
|
|
// 判断是否有嘉宾在连麦
|
|
final hasGuests =
|
|
roomController.rtcChannelDetail.value?.maleInfo !=
|
|
null ||
|
|
roomController.rtcChannelDetail.value?.femaleInfo !=
|
|
null;
|
|
|
|
return Container(
|
|
width: 110.w,
|
|
margin: EdgeInsets.only(left: 160.w),
|
|
padding: EdgeInsets.symmetric(horizontal: 10.w),
|
|
decoration: BoxDecoration(
|
|
color: Colors.black.withAlpha(80),
|
|
borderRadius: BorderRadius.all(Radius.circular(10.w)),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(height: 15.w),
|
|
// 只有当有嘉宾在连麦时才显示"解除连麦"选项
|
|
GestureDetector(
|
|
onTap: () async {
|
|
// 隐藏键盘
|
|
FocusScope.of(context).unfocus();
|
|
// 隐藏 overlay
|
|
SmartDialog.dismiss();
|
|
roomController.setDialogDismiss(true);
|
|
|
|
|
|
SmartDialog.show(
|
|
alignment: Alignment.bottomCenter,
|
|
maskColor: TDTheme.of(context).fontGyColor2,
|
|
onDismiss: (){
|
|
roomController.setDialogDismiss(false);
|
|
},
|
|
|
|
builder: (_) {
|
|
return Material(
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(9.w)),
|
|
color: Colors.white,
|
|
child: Container(
|
|
width: 375.w,
|
|
height: 300.w,
|
|
padding: EdgeInsets.all(10.w),
|
|
child: Column(
|
|
children: [
|
|
Text(
|
|
"在麦用户",
|
|
style: TextStyle(
|
|
fontSize: 16.w,
|
|
fontWeight: FontWeight.w700
|
|
),
|
|
),
|
|
Expanded(
|
|
child: SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
Container(
|
|
margin: EdgeInsets.symmetric(vertical: 10.w),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Image.asset(
|
|
Assets.imagesUserAvatar,
|
|
width: 40.w,
|
|
height: 40.w,
|
|
),
|
|
SizedBox(width: 5.w,),
|
|
Column(
|
|
children: [
|
|
Text(
|
|
"开心",
|
|
style: TextStyle(
|
|
fontSize: 12.w
|
|
),
|
|
),
|
|
Text(
|
|
"22岁",
|
|
style: TextStyle(
|
|
fontSize: 12.w,
|
|
color: const Color.fromRGBO(121, 121, 121, 1)
|
|
),
|
|
),
|
|
],
|
|
)
|
|
],
|
|
),
|
|
|
|
Checkbox(
|
|
value: false,
|
|
onChanged: (value) {
|
|
|
|
},
|
|
activeColor: const Color.fromRGBO(117, 98, 249, 1),
|
|
side: const BorderSide(color: Colors.grey),
|
|
shape: const CircleBorder(),
|
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Container(
|
|
margin: EdgeInsets.symmetric(vertical: 10.w),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Image.asset(
|
|
Assets.imagesUserAvatar,
|
|
width: 40.w,
|
|
height: 40.w,
|
|
),
|
|
SizedBox(width: 5.w,),
|
|
Column(
|
|
children: [
|
|
Text(
|
|
"开心",
|
|
style: TextStyle(
|
|
fontSize: 12.w
|
|
),
|
|
),
|
|
Text(
|
|
"22岁",
|
|
style: TextStyle(
|
|
fontSize: 12.w,
|
|
color: const Color.fromRGBO(121, 121, 121, 1)
|
|
),
|
|
),
|
|
],
|
|
)
|
|
],
|
|
),
|
|
|
|
Checkbox(
|
|
value: false,
|
|
onChanged: (value) {
|
|
|
|
},
|
|
activeColor: const Color.fromRGBO(117, 98, 249, 1),
|
|
side: const BorderSide(color: Colors.grey),
|
|
shape: const CircleBorder(),
|
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Container(
|
|
width: 170.w,
|
|
height: 42.w,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.all(Radius.circular(42.w)),
|
|
color: const Color.fromRGBO(237, 237, 237, 1)
|
|
),
|
|
child: Center(
|
|
child: Text(
|
|
"取消",
|
|
style: TextStyle(
|
|
fontSize: 14.w,
|
|
fontWeight: FontWeight.w500
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
width: 170.w,
|
|
height: 42.w,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.all(Radius.circular(42.w)),
|
|
color: const Color.fromRGBO(117, 98, 249, 1)
|
|
),
|
|
child: Center(
|
|
child: Text(
|
|
"确认",
|
|
style: TextStyle(
|
|
fontSize: 14.w,
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.w500
|
|
),
|
|
),
|
|
),
|
|
)
|
|
],
|
|
)
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
Image.asset(
|
|
Assets.imagesMicOff,
|
|
width: 15.w,
|
|
),
|
|
SizedBox(width: 5.w),
|
|
Text(
|
|
'踢出直播间',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 13.sp,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(height: 15.w),
|
|
if (hasGuests)
|
|
GestureDetector(
|
|
onTap: () {
|
|
// 关闭设置弹窗
|
|
SmartDialog.dismiss();
|
|
// 弹出解除连麦对话框
|
|
roomController.setDialogDismiss(true);
|
|
SmartDialog.show(
|
|
onDismiss: (){
|
|
roomController.setDialogDismiss(false);
|
|
},
|
|
builder: (context) {
|
|
return DisconnectMicDialog();
|
|
},
|
|
);
|
|
},
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
Image.asset(
|
|
Assets.imagesMicOff,
|
|
width: 15.w,
|
|
),
|
|
SizedBox(width: 5.w),
|
|
Text(
|
|
'解除连麦',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 13.sp,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
if (hasGuests) SizedBox(height: 15.w),
|
|
|
|
GestureDetector(
|
|
onTap: () async {
|
|
await roomController.leaveChannel();
|
|
// 隐藏 overlay
|
|
SmartDialog.dismiss();
|
|
// 退出房间时清空RTM消息
|
|
if (Get.isRegistered<RoomController>()) {
|
|
final roomController = Get.find<RoomController>();
|
|
roomController.chatMessages.clear();
|
|
}
|
|
// 如果还没有执行 pop,手动调用 Get.back()
|
|
Get.back();
|
|
// 等待页面关闭后再显示小窗口,确保小窗口能正确显示
|
|
Future.delayed(const Duration(milliseconds: 200), () {
|
|
overlayController.hide();
|
|
});
|
|
},
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
Image.asset(
|
|
Assets.imagesExitRoom,
|
|
width: 15.w,
|
|
),
|
|
SizedBox(width: 5.w),
|
|
Text(
|
|
'结束直播',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 13.sp,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(height: 15.w),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
child: Container(
|
|
height: 30.w,
|
|
padding: EdgeInsets.symmetric(horizontal: 5.w),
|
|
margin: EdgeInsets.only(right: 15.w),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.all(Radius.circular(30.w)),
|
|
color: const Color.fromRGBO(0, 0, 0, .3),
|
|
border: Border.all(
|
|
color: const Color.fromRGBO(255, 255, 255, .3),
|
|
width: 1.w,
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(
|
|
Icons.settings_rounded,
|
|
color: Colors.white,
|
|
size: 18.w,
|
|
),
|
|
Text(
|
|
'直播设置',
|
|
style: TextStyle(color: Colors.white, fontSize: 13.sp),
|
|
),
|
|
Icon(
|
|
Icons.keyboard_arrow_down_sharp,
|
|
color: Colors.white,
|
|
size: 18.w,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
GestureDetector(
|
|
onTap: onCloseTap,
|
|
child: Container(
|
|
width: 30.w,
|
|
height: 30.w,
|
|
margin: EdgeInsets.only(right: 15.w),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.all(Radius.circular(30.w)),
|
|
color: const Color.fromRGBO(0, 0, 0, .3),
|
|
),
|
|
child: Center(
|
|
child: Image.asset(closeIconAsset, width: 14.w, height: 14.w),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|