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.
 
 
 
 
 

217 lines
7.2 KiB

import 'package:dating_touchme_app/controller/discover/room_controller.dart';
import 'package:dating_touchme_app/controller/overlay_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:dating_touchme_app/widget/live/live_room_user_header.dart';
import 'package:dating_touchme_app/widget/live/live_room_anchor_showcase.dart';
import 'package:dating_touchme_app/widget/live/live_room_active_speaker.dart';
import 'package:dating_touchme_app/widget/live/live_room_notice_chat_panel.dart';
import 'package:dating_touchme_app/widget/live/live_room_action_bar.dart';
import 'package:dating_touchme_app/widget/live/live_gift_popup.dart';
import 'package:dating_touchme_app/widget/live/live_recharge_popup.dart';
import 'package:dating_touchme_app/widget/live/svga_player_widget.dart';
class LiveRoomPage extends StatefulWidget {
final int id;
const LiveRoomPage({super.key, required this.id});
@override
State<LiveRoomPage> createState() => _LiveRoomPageState();
}
class _LiveRoomPageState extends State<LiveRoomPage> {
late final RoomController _roomController;
late final OverlayController _overlayController;
String message = '';
final TextEditingController _messageController = TextEditingController();
final activeGift = ValueNotifier<int?>(null);
final giftNum = ValueNotifier<int>(1);
final activePay = ValueNotifier<int?>(null);
List<Map> payList = [
{"num": 10, "price": 10, "hasTag": true},
{"num": 60, "price": 60, "hasTag": true},
{"num": 300, "price": 60, "hasTag": true},
{"num": 1080, "price": 1080, "hasTag": false},
{"num": 2880, "price": 2880, "hasTag": false},
{"num": 5000, "price": 5000, "hasTag": false},
{"num": 10000, "price": 10000, "hasTag": false},
{"num": 20000, "price": 20000, "hasTag": false},
{"num": 50000, "price": 50000, "hasTag": false},
];
final payChecked = ValueNotifier<bool>(true);
changeActive(int index) {
activeGift.value = index;
setState(() {});
}
changePayActive(int index) {
activePay.value = index;
setState(() {});
}
@override
void initState() {
super.initState();
_roomController = Get.isRegistered<RoomController>()
? Get.find<RoomController>()
: Get.put(RoomController());
_overlayController = Get.find<OverlayController>();
}
@override
void dispose() {
_messageController.dispose();
super.dispose();
}
/// 发送消息
Future<void> _sendMessage() async {
final content = _messageController.text.trim();
if (content.isEmpty) {
return;
}
// 发送消息
await _roomController.sendChatMessage(content);
// 清空输入框
_messageController.clear();
message = '';
}
void _showGiftPopup() {
SmartDialog.show(
alignment: Alignment.bottomCenter,
maskColor: TDTheme.of(context).fontGyColor2,
builder: (_) => Obx(() {
// 优先使用 API 返回的 giftProducts,如果为空则使用后备列表
final giftProducts = _roomController.giftProducts;
final giftList = giftProducts.toList();
return LiveGiftPopup(
activeGift: activeGift,
giftNum: giftNum,
giftList: giftList,
changeActive: changeActive,
);
}),
);
}
void _showRechargePopup() {
SmartDialog.show(
alignment: Alignment.bottomCenter,
maskColor: TDTheme.of(context).fontGyColor2,
builder: (_) => LiveRechargePopup(
activePay: activePay,
payChecked: payChecked,
payList: payList,
changePayActive: changePayActive,
),
);
}
@override
Widget build(BuildContext context) {
return PopScope(
onPopInvokedWithResult: (bool didPop, Object? result) async {
_overlayController.toggle();
Get.back();
},
child: Scaffold(
body: Stack(
children: [
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color.fromRGBO(248, 242, 255, 1),
Color.fromRGBO(247, 247, 247, 1),
],
),
),
),
Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Color.fromRGBO(19, 16, 47, 1),
Color.fromRGBO(19, 16, 47, 1),
],
),
),
),
Container(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(height: 10.w),
Obx(() {
final detail =
_roomController.rtcChannelDetail.value;
final anchorInfo = detail?.anchorInfo;
final userName = anchorInfo!.nickName;
final avatarAsset = anchorInfo.profilePhoto;
const popularityText = '0'; // TODO: 使用真实数据
return LiveRoomUserHeader(
userName: userName,
popularityText: popularityText,
avatarAsset: avatarAsset,
onCloseTap: () {
_overlayController.show();
// 延迟返回,确保 overlay 先显示
Future.microtask(() {
Get.back();
});
},
);
}),
SizedBox(height: 7.w),
LiveRoomAnchorShowcase(),
SizedBox(height: 5.w),
const LiveRoomActiveSpeaker(),
SizedBox(height: 9.w),
const LiveRoomNoticeChatPanel(),
SizedBox(height: 17.w),
],
),
),
),
LiveRoomActionBar(
messageController: _messageController,
onMessageChanged: (value) {
message = value;
},
onSendTap: _sendMessage,
onGiftTap: _showGiftPopup,
onChargeTap: _showRechargePopup,
),
],
),
),
// SVGA 动画播放组件
const SvgaPlayerWidget(),
],
),
),
);
}
}