import 'package:audio_waveforms/audio_waveforms.dart'; import 'package:common_utils/common_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import '../../../core/theme/app_colors.dart'; import '../controllers/meeting_details_controller.dart'; import 'mind_map_tab.dart'; import 'overview_tab.dart'; import 'speech_tab.dart'; import 'summary_tab.dart'; class MeetingDetailsView extends GetView { const MeetingDetailsView({super.key}); @override Widget build(BuildContext context) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; return Obx( () => Scaffold( backgroundColor: isDarkMode ? Colors.black : Colors.grey[50], appBar: _buildAppBar(isDarkMode), body: NestedScrollView( controller: controller.scrollController, headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return [ SliverAppBar( automaticallyImplyLeading: false, expandedHeight: 210.w, backgroundColor: Colors.transparent, flexibleSpace: FlexibleSpaceBar( collapseMode: CollapseMode.pin, background: Align( alignment: Alignment.topCenter, child: Container( height: 200.w, decoration: BoxDecoration( color: Colors.grey[200]!, borderRadius: BorderRadius.vertical( bottom: Radius.circular(20.r), ), ), child: Column( children: [ Container( margin: EdgeInsets.only(bottom: 5.w), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8.r), ), child: AudioFileWaveforms( size: Size(350.w, 120.w), playerController: controller.playerController, playerWaveStyle: PlayerWaveStyle( fixedWaveColor: Colors.grey[300]!, liveWaveColor: Colors.red, seekLineColor: Colors.red, scaleFactor: 600, ), ), ), SizedBox( width: 350.w, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ StreamBuilder( stream: controller.playerController .onCurrentDurationChanged, builder: (context, snapshot) { final position = snapshot.data ?? 0; return Text( DateUtil.formatDateMs( position, format: 'HH:mm:ss', isUtc: true, ), style: TextStyle( color: isDarkMode ? Colors.grey[400] : Colors.grey[500], fontSize: 12.sp, ), ); }, ), Obx( () => Text( DateUtil.formatDateMs( controller.durationMax.value, format: 'HH:mm:ss', isUtc: true, ), style: TextStyle( color: isDarkMode ? Colors.grey[400] : Colors.grey[500], fontSize: 12.sp, ), ), ), ], ), ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Icon( Icons.replay_10, color: Colors.black, size: 30.w, ), StreamBuilder( stream: controller .playerController.onPlayerStateChanged, builder: (context, snapshot) { bool isPlay = snapshot.data?.isPlaying ?? false; return GestureDetector( onTap: () { if (isPlay) { controller.playerController .pausePlayer(); } else { controller.playerController .startPlayer(); } }, child: Icon( isPlay ? Icons.pause_circle : Icons.play_circle, color: Colors.black, size: 48.w, ), ); }, ), Icon( Icons.forward_10, color: Colors.black, size: 30.w, ), ], ), ], ), ), ), ), ), ]; }, body: _buildBody(context, isDarkMode), ), ), ); } // 构建应用栏 PreferredSizeWidget _buildAppBar(bool isDarkMode) { return AppBar( backgroundColor: controller.isTop.value ? Colors.grey[50] : Colors.grey[200], surfaceTintColor: Colors.transparent, elevation: 0.5, leading: controller.isSpeakerText.value ? GestureDetector( onTap: () { controller.isSpeakerText.value = false; controller.editSpeakerTextId.value = 0; controller.editSpeakerTextList = []; }, child: Center( child: Text( 'cancel'.tr, style: TextStyle( color: isDarkMode ? Colors.white : Colors.black87, fontSize: 16.sp, ), ), ), ) : IconButton( icon: Icon( Icons.arrow_back_ios, color: isDarkMode ? Colors.white : Colors.black, size: 20.sp, ), onPressed: () => Get.back(), ), title: Opacity( opacity: controller.isTop.value ? 1.0 : 0.0, child: Container( width: 170.w, padding: EdgeInsets.symmetric(horizontal: 2.w, vertical: 3.w), clipBehavior: Clip.hardEdge, decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(30.r), ), child: Row( children: [ StreamBuilder( stream: controller.playerController.onPlayerStateChanged, builder: (context, snapshot) { bool isPlay = snapshot.data?.isPlaying ?? false; return GestureDetector( onTap: () { if (isPlay) { controller.playerController.pausePlayer(); } else { controller.playerController.startPlayer(); } }, child: Icon( isPlay ? Icons.pause_circle : Icons.play_circle, color: Colors.black, size: 30.w, ), ); }, ), 4.horizontalSpace, AudioFileWaveforms( size: Size(130.w, 30.w), playerController: controller.playerController, playerWaveStyle: PlayerWaveStyle( fixedWaveColor: Colors.grey[400]!, liveWaveColor: Colors.red, seekLineColor: Colors.red, scaleFactor: 100, ), ), ], ), ), ), centerTitle: true, actions: [ if (controller.isSpeakerText.value) GestureDetector( onTap: controller.editSpeakerText, child: Padding( padding: EdgeInsets.symmetric( horizontal: 12.w, vertical: 6.w, ), child: Text( 'save'.tr, style: TextStyle( color: isDarkMode ? AppColors.primary : Colors.blue, fontSize: 16.sp, ), ), ), ), if (!controller.isSpeakerText.value) IconButton( icon: Icon( Icons.ios_share, color: isDarkMode ? Colors.white : Colors.black, size: 22.sp, ), onPressed: () {}, ), if (!controller.isSpeakerText.value) IconButton( icon: Container( width: 22.w, height: 22.w, alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20.r), border: Border.all( color: isDarkMode ? Colors.white : Colors.black, width: 2, ), ), child: Icon( Icons.more_horiz, color: isDarkMode ? Colors.white : Colors.black, size: 16.sp, ), ), onPressed: () {}, ), ], ); } // 构建主体内容 Widget _buildBody(BuildContext context, bool isDarkMode) { return Column( children: [ Container( padding: EdgeInsets.symmetric(horizontal: 8.w), margin: EdgeInsets.symmetric(vertical: 10.w), child: Obx( () => Row( children: [ _iconItem(Icons.summarize, '概述', 0), _iconItem(Icons.message, '转写', 1), _iconItem(Icons.article, '总结', 2), _iconItem(Icons.lan, '思维导图', 3), ], ), ), ), Expanded( child: Padding( padding: EdgeInsets.symmetric(horizontal: 12.w), child: TabBarView( controller: controller.tabController, physics: const NeverScrollableScrollPhysics(), children: const [ OverviewTab(), SpeechTab(), SummaryTab(), MindMapTab(), ], ), ), ), ], ); } Widget _iconItem(IconData icon, String title, int index) { bool isActive = controller.currentIndex.value == index; return Expanded( flex: isActive ? 1 : 0, child: GestureDetector( onTap: () { if (isActive) return; controller.tabController.index = index; controller.isSpeakerText.value = false; controller.editSpeakerTextId.value = 0; controller.editSpeakerTextList = []; }, child: Container( height: 45.w, padding: EdgeInsets.symmetric(horizontal: 18.w), margin: EdgeInsets.symmetric(horizontal: 4.w), decoration: BoxDecoration( color: isActive ? Colors.black : Colors.grey[200], borderRadius: BorderRadius.circular(12.w), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( icon, color: isActive ? Colors.white : Colors.grey[600], size: 20.sp, ), if (isActive) Padding( padding: EdgeInsets.only(left: 5.w), child: Text( title, style: TextStyle( color: Colors.white, fontSize: 16.sp, ), ), ), ], ), ), ), ); } }