import 'package:dsbridge_flutter/dsbridge_flutter.dart'; import 'package:electronic_assistant/base/base_page.dart'; import 'package:electronic_assistant/module/talk/controller.dart'; import 'package:electronic_assistant/module/talk/mindmap/view.dart'; import 'package:electronic_assistant/module/talk/summary/view.dart'; import 'package:electronic_assistant/module/talk/todo/view.dart'; import 'package:electronic_assistant/resource/colors.gen.dart'; import 'package:electronic_assistant/utils/expand.dart'; import 'package:electronic_assistant/utils/fixed_size_tab_indicator.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import '../../data/bean/talks.dart'; import '../../data/consts/event_report_id.dart'; import '../../resource/assets.gen.dart'; import '../../resource/string.gen.dart'; import '../../router/app_pages.dart'; import '../../utils/common_style.dart'; import 'original/view.dart'; class TalkPage extends BasePage { final String? talkId; late final List _pages; TalkPage({super.key}) : talkId = Get.arguments[TalkController.argumentTalkId] { Get.lazyPut(() => TalkController(), tag: talkId, fenix: true); _pages = [ SummaryView(talkId), MindMapView(talkId), TodoView(talkId), OriginalView(talkId), ]; } @override get controller => Get.find(tag: talkId); static void start(TalkBean item, {String eventTag = EventId.id_002}) { if (Get.currentRoute == RoutePath.talkDetail && Get.arguments[TalkController.argumentTalkId] == item.id) { return; } Get.toNamed(RoutePath.talkDetail, arguments: { TalkController.argumentItem: item, TalkController.argumentEventTag: eventTag, TalkController.argumentTalkId: item.id, }, preventDuplicates: false); } static void startById(String talkId, {String eventTag = ''}) { if (Get.currentRoute == RoutePath.talkDetail && Get.arguments[TalkController.argumentTalkId] == talkId) { return; } Get.toNamed(RoutePath.talkDetail, arguments: { TalkController.argumentTalkId: talkId, TalkController.argumentEventTag: eventTag, }, preventDuplicates: false); } @override Widget buildBody(BuildContext context) { return WillPopScope( onWillPop: () async { if (controller.isEditModel) { controller.onEditCancel(); return false; } if (controller.isShowMindFullScreen.value) { controller.onExitMindFullScreen(); return false; } return true; }, child: DefaultTabController( initialIndex: controller.defaultIndex, length: controller.tabBeans.length, child: Stack( children: [ Obx(() { return controller.temporaryController != null ? DWebViewWidget(controller: controller.temporaryController!) : const SizedBox.shrink(); }), _buildTalkContentView(), buildBottomView() ], ), ), ); } Widget _buildTalkContentView() { return Builder(builder: (context) { final statusBarHeight = MediaQuery.of(context).padding.top; return Obx(() { return Column( children: [ AnimatedContainer( key: controller.headGlobalKey, decoration: BoxDecoration( gradient: LinearGradient( colors: ['#E1E9FF'.toColor(), '#F9FAFE'.toColor()], begin: Alignment.topCenter, end: Alignment.bottomCenter, stops: const [0, 1.0], ), ), height: controller.isShowMindFullScreen.value ? 0 : controller.headViewHeight, duration: controller.mindFullDuration, child: SingleChildScrollView( physics: const NeverScrollableScrollPhysics(), child: Column(children: [ SizedBox(height: statusBarHeight), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ _buildToolbarLeftView(), _buildToolbarRightView(), ], ), buildTabBar(context), ]), ), ), buildTalkContentView() ], ); }); }); } Widget buildTabBar(BuildContext context) { TabController tabController = DefaultTabController.of(context); tabController.addListener(() { controller.updateTabIndex(tabController.index); }); return Obx(() { if (!controller.isEditModel) { return Column( children: [ TabBar( labelStyle: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold), unselectedLabelStyle: TextStyle(fontSize: 14.sp), labelColor: ColorName.primaryTextColor, unselectedLabelColor: ColorName.secondaryTextColor, labelPadding: EdgeInsets.only(top: 4.h), dividerHeight: 0, splashFactory: NoSplash.splashFactory, indicator: FixedSizeTabIndicator( width: 16.w, height: 3.w, radius: 3, color: ColorName.colorPrimary), tabs: controller.tabBeans .map((bean) => Tab(text: bean.title)) .toList()), SizedBox(height: 6.h), Divider(height: 1, color: '#F2F4F9'.color) ], ); } else { return SizedBox(height: 8.h, width: double.infinity); } }); } @override bool immersive() { return true; } Widget buildTalkContentView() { return Obx(() { if (controller.talkBean.value?.status.value == TalkStatus.notAnalysis && controller.isUploading.value != true) { if (controller.isShowElectricLow.value) { return buildElectricLowView(); } else { return buildNotAnalysisView(); } } else { return buildTabContentView(); } }); } Widget buildTabContentView() { return Expanded( child: TabBarView( physics: controller.isEditModel || controller.checkTabBean.value?.isDisallowScroll == true ? const NeverScrollableScrollPhysics() : null, children: _pages, ), ); } Widget buildNotAnalysisView() { return SizedBox( width: double.infinity, child: Column( children: [ SizedBox(height: 119.h), SizedBox( width: 100.w, height: 100.w, child: Assets.images.iconTalkSummaryUnanalyzed.image()), SizedBox(height: 4.h), Text(StringName.talkUnAnalyzed.tr, style: TextStyle( fontSize: 15.sp, color: ColorName.primaryTextColor)), SizedBox(height: 2.h), Text(StringName.talkUnAnalyzedTips.tr, style: TextStyle( fontSize: 12.sp, color: ColorName.secondaryTextColor)), SizedBox(height: 24.h), GestureDetector( onTap: () { controller.checkCanAnalyze(); }, child: Container( decoration: getPrimaryBtnDecoration(8), width: 240.w, height: 48.w, child: Center( child: Text( StringName.talkAnalyzedBtnTxt.tr, style: TextStyle(fontSize: 16.sp, color: ColorName.white), ), ), ), ) ], ), ); } Widget buildElectricLowView() { return GestureDetector( onTap: () { controller.onGoElectricStore(); }, child: Container( color: const Color(0xFFDFE4FC), padding: EdgeInsets.only(left: 16.w, right: 12.w, top: 8.h, bottom: 8.h), child: Row( children: [ SizedBox( width: 46.w, height: 56.w, child: Assets.images.iconTalkElectricLow.image()), SizedBox(width: 10.w), IntrinsicHeight( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 90.w, height: 21.w, child: Assets.images.iconTalkElectricLowTxt.image()), SizedBox(width: 1.w), Text(StringName.talkElectricLow.tr, style: TextStyle( fontSize: 12.sp, color: ColorName.secondaryTextColor)), ], ), ), const Spacer(), Container( decoration: getPrimaryBtnDecoration(8), width: 100.w, height: 36.w, child: Center( child: Text(StringName.talkGoStore.tr, style: TextStyle(fontSize: 16.sp, color: ColorName.white)), )) ], ), ), ); } Widget buildBottomView() { return Obx(() { return Visibility( key: controller.bottomGlobalKey, visible: controller.isEditModel == false, child: AnimatedPositioned( duration: controller.mindFullDuration, bottom: controller.isShowMindFullScreen.value ? controller.getBottomViewHeight() : 0.h, left: 0, right: 0, child: Align( alignment: Alignment.bottomCenter, child: Container( margin: EdgeInsets.only(bottom: 20.h), child: IntrinsicHeight( child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ _buildAIAnalysisView(), SizedBox(height: 8.h), _buildTalkEditView(), SizedBox(height: 10.h), buildAudioView() ], ), ), ), ), ), ); }); } Widget _buildTalkEditView() { return Obx(() { return Visibility( visible: controller.talkBean.value?.status.value == TalkStatus.analysisSuccess && controller.checkTabBean.value?.isShowEdit == true, maintainState: true, maintainAnimation: true, maintainSize: true, child: GestureDetector( onTap: () => controller.onEditModelClick(), child: Align( alignment: Alignment.centerLeft, child: Container( margin: EdgeInsets.only(left: 12.w), padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 6.w), decoration: BoxDecoration( color: ColorName.white, borderRadius: BorderRadius.circular(100), boxShadow: [ BoxShadow( color: ColorName.black5.withOpacity(0.08), spreadRadius: 2, blurRadius: 12, offset: const Offset(0, 1), ), ]), child: IntrinsicWidth( child: Row( children: [ Assets.images.iconTalkEdit.image(width: 16.w, height: 16.w), SizedBox(width: 2.w), Text(StringName.talkUpdateTxt.tr, style: TextStyle( height: 1, fontSize: 14.sp, color: ColorName.primaryTextColor)) ], ), ), ), ), ), ); }); } Widget _buildAIAnalysisView() { return Obx(() { return Visibility( visible: controller.talkBean.value?.status.value == TalkStatus.analysisSuccess, child: GestureDetector( onTap: () { controller.clickAIAnalysis(); }, child: Container( margin: EdgeInsets.only(right: 8.w), width: 64.w, height: 64.w, child: Assets.images.iconTalkLogo.image()), ), ); }); } buildAudioView() { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(100), boxShadow: [ BoxShadow( color: ColorName.black5.withOpacity(0.1), spreadRadius: 2, blurRadius: 12, offset: const Offset(0, 3), ), ], ), margin: EdgeInsets.symmetric(horizontal: 12.w), padding: EdgeInsets.symmetric(vertical: 6.w, horizontal: 9.w), child: Row( children: [ GestureDetector( onTap: () { controller.clickPlayAudio(); }, child: Obx(() { return SizedBox( width: 36.w, height: 36.w, child: (controller.isAudioPlaying.value) ? Assets.images.iconTalkAudioPlaying.image() : Assets.images.iconTalkAudioPause.image()); }), ), SizedBox(width: 15.w), Builder(builder: (context) { return Flexible( child: Obx(() { return SliderTheme( data: SliderTheme.of(context).copyWith( thumbColor: Colors.white, overlayShape: SliderComponentShape.noOverlay, trackHeight: 8, activeTrackColor: "#8A89E9".toColor(), inactiveTrackColor: "#F6F5F8".toColor(), trackShape: CustomTrackShape(), ), child: Slider( value: controller.audioProgressValue.value, min: 0.0, max: controller.sliderMax, onChanged: (value) { controller.updateProgress(value); }, ), ); }), ); }), SizedBox(width: 11.w), Obx(() { return Text(controller.audioDuration.value.toFormattedString(), style: TextStyle( fontSize: 10.sp, color: ColorName.secondaryTextColor)); }) ], ), ); } Widget _buildToolbarLeftView() { return Obx(() { if (controller.isEditModel) { return Align( alignment: Alignment.centerLeft, child: IconButton( icon: Assets.images.iconTalkEditCancel .image(width: 24.w, height: 24.w), onPressed: () { controller.onEditCancel(); }, ), ); } else { return Row( children: [ IconButton( icon: Assets.images.iconTalkBack.image(width: 24.w, height: 24.w), onPressed: () { Get.back(); }, ), SizedBox(width: 6.w), Obx(() { return GestureDetector( onTap: () { controller.onEditTitleClick(); }, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ ConstrainedBox( constraints: BoxConstraints(maxWidth: 0.65.sw), child: Text( maxLines: 1, overflow: TextOverflow.ellipsis, controller.talkBean.value?.title.value ?? '', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 15.sp, color: ColorName.primaryTextColor, ), ), ), SizedBox(width: 2.w), Assets.images.iconTalkEditTitle .image(width: 16.w, height: 16.w) ], ), SizedBox(height: 2.h), Text( controller.talkBean.value?.createTime ?? '', style: TextStyle( fontSize: 11.sp, color: ColorName.secondaryTextColor), ) ], ), ); }) ], ); } }); } Widget _buildToolbarRightView() { return Obx(() { return Visibility( visible: controller.talkBean.value?.status.value == TalkStatus.analysisSuccess, child: controller.isEditModel ? GestureDetector( onTap: () { controller.onEditDoneClick(); }, child: Padding( padding: EdgeInsets.symmetric(horizontal: 12.w), child: Text(StringName.done.tr, style: TextStyle( fontSize: 17.sp, color: ColorName.primaryTextColor)), ), ) : Row( children: [ IconButton( icon: Assets.images.iconTalkShare .image(width: 20.w, height: 20.w), onPressed: () { controller.onShareClick(); }, ), ], ), ); }); } } class CustomTrackShape extends RoundedRectSliderTrackShape { @override Rect getPreferredRect({ required RenderBox parentBox, Offset offset = Offset.zero, required SliderThemeData sliderTheme, bool isEnabled = false, bool isDiscrete = false, }) { final trackHeight = sliderTheme.trackHeight; final trackLeft = offset.dx; final trackTop = offset.dy + (parentBox.size.height - trackHeight!) / 2; final trackWidth = parentBox.size.width; return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight); } }