chatapp3-flutter/lib/modules/room/voice_room_page.dart
2026-04-16 19:23:54 +08:00

277 lines
10 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:yumi/app_localizations.dart';
import 'package:yumi/app/constants/sc_global_config.dart';
import 'package:yumi/ui_kit/components/sc_compontent.dart';
import 'package:yumi/services/audio/rtc_manager.dart';
import 'package:yumi/ui_kit/widgets/room/room_bottom_widget.dart';
import 'package:provider/provider.dart';
import 'package:yumi/shared/tools/sc_lk_event_bus.dart';
import 'package:yumi/app/routes/sc_fluro_navigator.dart';
import 'package:yumi/shared/business_logic/models/res/join_room_res.dart';
import 'package:yumi/services/gift/gift_animation_manager.dart';
import 'package:yumi/services/gift/gift_system_manager.dart';
import 'package:yumi/services/audio/rtm_manager.dart';
import 'package:yumi/ui_kit/widgets/room/anim/l_gift_animal_view.dart';
import 'package:yumi/ui_kit/widgets/room/anim/room_entrance_screen.dart';
import 'package:yumi/ui_kit/widgets/room/effect/luck_gift_nomor_anim_widget.dart';
import 'package:yumi/ui_kit/widgets/room/room_head_widget.dart';
import 'package:yumi/ui_kit/widgets/room/room_msg_item.dart';
import 'package:yumi/ui_kit/widgets/room/room_online_user_widget.dart';
import 'package:yumi/ui_kit/widgets/room/room_play_widget.dart';
import 'package:yumi/shared/data_sources/models/enum/sc_gift_type.dart';
import '../../ui_kit/components/sc_float_ichart.dart';
import '../../ui_kit/widgets/room/seat/room_seat_widget.dart';
import 'chat/all/all_chat_page.dart';
import 'chat/chat/chat_page.dart';
import 'chat/gift/gift_chat_page.dart';
///语聊房
class VoiceRoomPage extends StatefulWidget {
const VoiceRoomPage({super.key});
@override
State<VoiceRoomPage> createState() => _VoiceRoomPageState();
}
class _VoiceRoomPageState extends State<VoiceRoomPage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
final List<Widget> _pages = [AllChatPage(), ChatPage(), GiftChatPage()];
final List<Widget> _tabs = [];
late StreamSubscription _subscription;
@override
void initState() {
super.initState();
_tabController = TabController(length: _pages.length, vsync: this);
Provider.of<RtmProvider>(context, listen: false).msgFloatingGiftListener =
_floatingGiftListener;
_tabController.addListener(() {}); // 监听切换
_subscription = eventBus.on<SCGiveRoomLuckPageDisposeEvent>().listen((
event,
) {
if (mounted) {
Provider.of<GiftProvider>(context, listen: false).clearAllGiftData();
Provider.of<GiftProvider>(
context,
listen: false,
).toggleGiftAnimationVisibility(false);
}
});
}
@override
void dispose() {
final rtmProvider = Provider.of<RtmProvider>(context, listen: false);
if (rtmProvider.msgFloatingGiftListener == _floatingGiftListener) {
rtmProvider.msgFloatingGiftListener = null;
}
_tabController.dispose(); // 释放资源
_subscription.cancel();
super.dispose();
}
bool roomThemeBackActi(JoinRoomRes? room) {
if (room?.roomProps?.roomTheme != null) {
if (room?.roomProps?.roomTheme?.themeBack != null &&
room!.roomProps!.roomTheme!.themeBack!.isNotEmpty) {
if ((room.roomProps?.roomTheme?.expireTime ?? 0) >
DateTime.now().millisecondsSinceEpoch) {
return true;
}
}
}
return false;
}
@override
Widget build(BuildContext context) {
_tabs.clear();
_tabs.add(Tab(text: SCAppLocalizations.of(context)!.all));
_tabs.add(Tab(text: SCAppLocalizations.of(context)!.chat));
_tabs.add(Tab(text: SCAppLocalizations.of(context)!.gift));
return PopScope(
canPop: false,
onPopInvokedWithResult: (bool didPop, Object? result) {
if (!didPop) {
SCFloatIchart().show();
SCNavigatorUtils.goBack(context);
}
},
child: Scaffold(
backgroundColor:
SCGlobalConfig.businessLogicStrategy.getVoiceRoomBackgroundColor(),
resizeToAvoidBottomInset: false,
body: SafeArea(
top: false,
child: Stack(
children: [
Consumer<RtcProvider>(
builder: (context, ref, child) {
return roomThemeBackActi(ref.currenRoom)
? netImage(
url:
ref.currenRoom?.roomProps?.roomTheme?.themeBack ??
"",
width: ScreenUtil().screenWidth,
height: ScreenUtil().screenHeight,
noDefaultImg: true,
fit: BoxFit.cover,
)
: Image.asset(
SCGlobalConfig.businessLogicStrategy
.getVoiceRoomDefaultBackgroundImage(),
width: ScreenUtil().screenWidth,
height: ScreenUtil().screenHeight,
fit: BoxFit.cover,
);
},
),
Column(
children: [
SizedBox(height: ScreenUtil().setWidth(42)),
RoomHeadWidget(),
SizedBox(height: ScreenUtil().setWidth(5)),
RoomOnlineUserWidget(),
RoomSeatWidget(),
SizedBox(height: 2.w),
Expanded(
child: Stack(
children: [
Column(
children: [_buildChatView(), RoomBottomWidget()],
),
LGiftAnimalPage(),
Transform.translate(
offset: Offset(0, -20),
child: RoomAnimationQueueScreen(),
),
],
),
),
],
),
// _buildPlayViews(),
///幸运礼物中奖动画
LuckGiftNomorAnimWidget(),
],
),
),
),
);
}
///消息
Widget _buildChatView() {
return Expanded(
child: Stack(
alignment: AlignmentDirectional.bottomEnd,
children: [
Column(
children: [
TabBar(
tabAlignment: TabAlignment.start,
labelPadding: SCGlobalConfig.businessLogicStrategy
.getVoiceRoomTabLabelPadding()
.copyWith(
left:
SCGlobalConfig.businessLogicStrategy
.getVoiceRoomTabLabelPadding()
.left *
ScreenUtil().setWidth(1),
right:
SCGlobalConfig.businessLogicStrategy
.getVoiceRoomTabLabelPadding()
.right *
ScreenUtil().setWidth(1),
),
labelColor:
SCGlobalConfig.businessLogicStrategy
.getVoiceRoomTabLabelColor(),
isScrollable: true,
indicator: BoxDecoration(),
unselectedLabelColor:
SCGlobalConfig.businessLogicStrategy
.getVoiceRoomTabUnselectedLabelColor(),
labelStyle: SCGlobalConfig.businessLogicStrategy
.getVoiceRoomTabLabelStyle()
.copyWith(
fontSize:
SCGlobalConfig.businessLogicStrategy
.getVoiceRoomTabLabelStyle()
.fontSize! *
ScreenUtil().setSp(1),
),
unselectedLabelStyle: SCGlobalConfig.businessLogicStrategy
.getVoiceRoomTabUnselectedLabelStyle()
.copyWith(
fontSize:
SCGlobalConfig.businessLogicStrategy
.getVoiceRoomTabUnselectedLabelStyle()
.fontSize! *
ScreenUtil().setSp(1),
),
indicatorColor:
SCGlobalConfig.businessLogicStrategy
.getVoiceRoomTabIndicatorColor(),
dividerColor:
SCGlobalConfig.businessLogicStrategy
.getVoiceRoomTabDividerColor(),
controller: _tabController,
tabs: _tabs,
),
Expanded(
child: Container(
margin: SCGlobalConfig.businessLogicStrategy
.getVoiceRoomChatContainerMargin()
.copyWith(
end:
SCGlobalConfig.businessLogicStrategy
.getVoiceRoomChatContainerMargin()
.end *
ScreenUtil().setWidth(1),
),
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: TabBarView(
controller: _tabController,
children: _pages,
),
),
),
),
],
),
RoomPlayWidget(),
],
),
);
}
///礼物上飘动画
_floatingGiftListener(Msg msg) {
if (Provider.of<GiftProvider>(context, listen: false).hideLGiftAnimal) {
return;
}
var giftModel = LGiftModel();
final giftTab = (msg.gift?.giftTab ?? '').trim();
giftModel.labelId = "${msg.gift?.id}${msg.user?.id}${msg.toUser?.id}";
giftModel.sendUserName = msg.user?.userNickname ?? "";
giftModel.sendToUserName = msg.toUser?.userNickname ?? "";
giftModel.sendUserPic = msg.user?.userAvatar ?? "";
giftModel.giftPic = msg.gift?.giftPhoto ?? "";
giftModel.giftCount = msg.number ?? 0;
giftModel.isLuckyGift =
giftTab == "LUCK" || giftTab == SCGiftType.LUCKY_GIFT.name;
Provider.of<GiftAnimationManager>(
context,
listen: false,
).enqueueGiftAnimation(giftModel);
}
}