import 'package:electronic_assistant/base/base_page.dart'; import 'package:electronic_assistant/data/bean/talks.dart'; import 'package:electronic_assistant/data/repositories/account_repository.dart'; import 'package:electronic_assistant/dialog/rename_dialog.dart'; import 'package:electronic_assistant/dialog/talk_delete_dialog.dart'; import 'package:electronic_assistant/module/chat/view.dart'; import 'package:electronic_assistant/module/store/view.dart'; import 'package:electronic_assistant/popup/talk_popup.dart'; import 'package:electronic_assistant/resource/assets.gen.dart'; import 'package:electronic_assistant/resource/colors.gen.dart'; import 'package:electronic_assistant/resource/string.gen.dart'; import 'package:electronic_assistant/utils/expand.dart'; import 'package:electronic_assistant/widget/pull_to_refresh.dart'; import 'package:flutter/gestures.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 '../../data/bean/agenda.dart'; import '../../router/app_pages.dart'; import '../agenda/detail/view.dart'; import '../agenda/task_item_view.dart'; import '../talk/view.dart'; import 'controller.dart'; class HomePage extends BasePage { const HomePage({super.key}); @override Widget buildBody(BuildContext context) { return Stack( children: [ buildBgBox(), SafeArea( child: Column( children: [ Container( width: 1.sw, padding: const EdgeInsets.all(12).w, child: buildOperationBar(), ), Expanded( child: Container( color: "#F6F5F8".toColor(), child: PullToRefresh( enableRefresh: true, controller: controller.refreshController, onRefresh: () { controller.requestHomeData(); }, child: CustomScrollView( slivers: [ buildHeaderView(), buildTalkRecordTitle(), SliverToBoxAdapter( child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ "#FEFEFE".toColor(), "#FCFBFC".toColor() ], ), ), height: 0.3472222.sw, padding: EdgeInsets.only(bottom: 15.h), child: buildTalkRecord(), ), ), buildTalkTodoTitle(), buildTalkTodoContent(), buildSeeMoreView(), ], ), ), )) ], ), ) ], ); } @override bool immersive() { return true; } Widget buildHeaderView() { return SliverToBoxAdapter( child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ColorName.white, "#EEEFFB".toColor()], ), ), padding: EdgeInsets.only(left: 12.w, right: 12.w, top: 8.h, bottom: 16.h), child: Row( children: [ Expanded( child: _buildHeaderCard( StringName.homeTalkAudio.tr, StringName.homeTalkQuickAudio.tr, Assets.images.iconHomeTalkRecordCard.image().image, [ "#1763F9".toColor(), "#28B2FF".toColor(), ], onTap: () { controller.onRecordClick(); }), ), SizedBox(width: 8.w), Expanded( child: _buildHeaderCard( StringName.homeTalkImportAudio.tr, StringName.homeTalkAnalyzeLocalAudio.tr, Assets.images.iconHomeTalkSelectCard.image().image, [ "#5869ED".toColor(), "#6E8AF7".toColor(), ], onTap: () { controller.onPickerAudioFile(); }), ), ], ), ), ); } Widget _buildHeaderCard( String title, String content, ImageProvider imageProvider, List bgColor, { VoidCallback? onTap, }) { return GestureDetector( onTap: onTap, child: AspectRatio( aspectRatio: 164 / 80, child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: bgColor, ), borderRadius: BorderRadius.circular(12), ), child: Stack( children: [ Align( alignment: Alignment.centerRight, child: AspectRatio( aspectRatio: 1, child: SizedBox( height: double.infinity, child: Image(image: imageProvider)), ), ), Align( alignment: Alignment.centerLeft, child: IntrinsicHeight( child: Container( margin: EdgeInsets.only(left: 12.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: TextStyle( fontSize: 16.sp, color: ColorName.white, fontWeight: FontWeight.bold)), SizedBox(height: 4.h), Text(content, style: TextStyle( fontSize: 12.sp, color: ColorName.white80)), ], ), ), ), ) ], ), ), ), ); } SliverToBoxAdapter buildSeeMoreView() { return SliverToBoxAdapter( child: Obx(() { return Visibility( visible: controller.agendaList.isNotEmpty, child: Container( alignment: Alignment.center, padding: const EdgeInsets.only(top: 12, bottom: 36).w, child: RichText( text: TextSpan( text: StringName.homeTalkTodo1.tr, style: TextStyle( color: ColorName.secondaryTextColor, fontSize: 12.sp), children: [ TextSpan( text: StringName.homeTalkTodo2.tr, style: TextStyle( color: ColorName.colorPrimary, fontSize: 12.sp), recognizer: TapGestureRecognizer() ..onTap = () { controller.onGoAgendaList(); }), ], ), ), ), ); }), ); } SliverToBoxAdapter buildTalkTodoTitle() { return SliverToBoxAdapter( child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: ["#FCFBFC".toColor(), "#F6F5F8".toColor()], ), ), child: Column( children: [ SizedBox(height: 12.w), buildTitle(StringName.talkSummaryTodoTitle.tr, () { controller.onGoAgendaList(); }), SizedBox(height: 12.w) ], ), )); } SliverToBoxAdapter buildTalkRecordTitle() { return SliverToBoxAdapter( child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ColorName.white, "#FEFEFE".toColor()], ), ), padding: const EdgeInsets.symmetric(vertical: 12).w, child: buildTitle(StringName.homeTalkRecord.tr, () { controller.goTalkRecordPage(); }), ), ); } Row buildOperationBar() { return Row(children: [buildGoLogin(), const Spacer(), buildGoStore()]); } GestureDetector buildGoStore() { return GestureDetector( child: DecoratedBox( decoration: BoxDecoration( color: "#F6F5F8".toColor(), borderRadius: BorderRadius.circular(32), ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5).w, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( width: 20.w, height: 20.w, child: Assets.images.iconHomeCharge.image()), SizedBox(width: 2.w), Text(StringName.homeChargeTxt.tr, style: TextStyle( fontSize: 15.sp, color: ColorName.primaryTextColor)), ], ), )), onTap: () { // accountRepository.logout(); // ToastUtil.showToast('GoStore'); StorePage.start(fromType: StoreFromType.home); }); } Widget buildGoLogin() { return Obx(() { return GestureDetector( onTap: () { if (controller.isLogin) { controller.showLoginDrawer(); } else { controller.onLoginClick(); } }, child: Row( children: [ SizedBox( width: 36.w, height: 36.w, child: controller.isLogin ? Assets.images.iconHomeLogged.image() : Assets.images.iconHomeNoLogin.image()), SizedBox(width: 8.w), Text(controller.loginTxt, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 15.sp, color: ColorName.primaryTextColor)), SizedBox(width: 6.w), controller.isLogin ? const SizedBox.shrink() : SizedBox( height: 16.w, child: Assets.images.iconGoLoginArrow.image()) ], ), ); }); } DecoratedBox buildBgBox() { return DecoratedBox( decoration: const BoxDecoration(color: ColorName.white), child: Container( height: double.infinity, )); } Widget buildTalkRecord() { return SizedBox( width: 1.sw, child: CustomScrollView( scrollDirection: Axis.horizontal, slivers: [ SliverToBoxAdapter(child: SizedBox(width: 12.w)), Obx(() { return SliverList.builder( itemBuilder: _builderTalkItem, itemCount: controller.talkList.length >= 10 ? 10 : controller.talkList.length); }), ], ), ); } Widget _builderTalkItem(BuildContext context, int index) { return Obx(() { TalkBean? item = controller.talkList[index]; return _buildTalkView(item, onLongPressStart: (details) { if (!accountRepository.isLogin.value) { return; } showTalkPopup(details.globalPosition, Alignment.bottomRight, onRename: () { showRenameTalkDialog(item); }, onDelete: () { showDeleteTalkDialog(item); }); }, onItemClick: () { controller.onTalkItemClick(item); }); }); } Widget _builderAgendaItem(BuildContext context, int index) { return Obx(() { Agenda item = controller.agendaList[index]; return GestureDetector( onTap: () { AgendaDetailPage.start(item); }, child: taskItemView( item, onThinkingClick: () { ChatPage.startByTalkId( item.isExample == true ? ChatFromType.fromTalkExample : ChatFromType.fromAnalysisBtn, item.talkId, agenda: item); }, onCheckClick: () { controller.agendaComplete(item); }, ), ); }); } SliverToBoxAdapter buildGoRecordView() { return SliverToBoxAdapter( child: GestureDetector( onTap: () => Get.toNamed(RoutePath.record), child: Container( margin: EdgeInsets.only(right: 8.w), decoration: BoxDecoration( color: Colors.white, border: Border.all(color: '#EBEBFF'.toColor(), width: 1), borderRadius: BorderRadius.circular(8.0), ), child: SizedBox( width: 100.w, height: double.infinity, child: Stack( children: [ Positioned( right: 0, bottom: 0, child: SizedBox( width: 48.w, child: Assets.images.bgHomeQuickAudio.image(), ), ), Positioned.fill( child: Align( alignment: Alignment.center, child: Column( children: [ SizedBox(height: 20.h), SizedBox( width: 32.w, height: 32.w, child: Assets.images.iconAddTalk.image()), SizedBox(height: 6.h), Text(StringName.homeTalkAudio.tr, style: TextStyle( fontSize: 14.sp, color: ColorName.colorPrimary, fontWeight: FontWeight.bold)), Builder(builder: (context) { controller.todoTargetContext = context; return Text(StringName.homeTalkQuickAudio.tr, style: TextStyle( fontSize: 10.sp, color: ColorName.secondaryTextColor)); }) ], ), )), ], ), ), ), )); } Widget _buildTalkView(TalkBean item, {VoidCallback? onItemClick, GestureLongPressStartCallback? onLongPressStart}) { return GestureDetector( onTap: onItemClick, onLongPressStart: onLongPressStart, child: Container( width: 258.w, margin: EdgeInsets.only(right: 8.w), decoration: BoxDecoration( color: Colors.white, border: Border.all(color: '#F0F0F0'.toColor(), width: 2), borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(24), bottomRight: Radius.circular(12), bottomLeft: Radius.circular(12)), ), padding: EdgeInsets.only(left: 10.w, right: 16.w), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(top: 14).h, child: Stack( children: [ SizedBox( width: 35.w, height: 40.w, child: Assets.images.iconFilesFile.image()), Visibility( visible: item.isExample.isTrue, child: Container( margin: const EdgeInsets.only(top: 32).w, decoration: BoxDecoration( color: "#B2BAC4".toColor(), borderRadius: BorderRadius.circular(4)), padding: const EdgeInsets.symmetric( horizontal: 5.5, vertical: 2) .w, child: Text(StringName.homeTalkExample.tr, style: TextStyle( height: 1, fontSize: 12.sp, color: ColorName.white)), ), ), ], ), ), SizedBox(width: 8.w), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(item.title.value.orEmpty, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 15.sp, color: ColorName.primaryTextColor, fontWeight: FontWeight.bold)), SizedBox(height: 5.h), Text( item.summary.value.orEmpty, style: TextStyle( fontSize: 12.sp, color: ColorName.secondaryTextColor), overflow: TextOverflow.ellipsis, maxLines: 2, ), SizedBox(height: 8.h), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text(item.duration.toFormattedDuration(), style: TextStyle( fontSize: 12.sp, color: ColorName.tertiaryTextColor)), SizedBox(width: 6.w), Container( width: 1, height: 9, color: ColorName.tertiaryTextColor), SizedBox(width: 6.w), Text(item.createTime.orEmpty, style: TextStyle( fontSize: 12.sp, color: ColorName.tertiaryTextColor)) ], ) ], ), ) ], )), ); } Widget buildTitle(String titleName, VoidCallback? onTap) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12).w, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text(titleName, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 17.sp, color: ColorName.primaryTextColor)), const Spacer(), Visibility( visible: onTap == null ? false : true, child: GestureDetector( onTap: onTap, child: Padding( padding: const EdgeInsets.symmetric(vertical: 6).w, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( StringName.homeTalkSeeAll.tr, style: TextStyle( fontSize: 13.sp, color: ColorName.tertiaryTextColor), ), Container( margin: const EdgeInsets.only(bottom: 1), width: 16.w, height: 16.w, child: Assets.images.iconHomeTalkArrow.image()), ], ), ), ), ) ], ), ); } void showUnfinishedRecordPopup() { SmartDialog.showAttach( targetContext: controller.todoTargetContext, alignment: Alignment.bottomRight, animationType: SmartAnimationType.fade, clickMaskDismiss: true, maskColor: Colors.transparent, bindPage: true, builder: (_) => Padding( padding: const EdgeInsets.only(top: 7).h, child: Stack( alignment: Alignment.topCenter, children: [ SizedBox( width: 146.w, height: 66.w, child: Assets.images.bgAudioTodoPopup.image()), Container( alignment: Alignment.center, padding: const EdgeInsets.only(top: 17).w, width: 146.w, child: Text(StringName.homePopupTipsTxt.tr, style: TextStyle(fontSize: 14.sp, color: Colors.white))) ], ), ), ); } void showRenameTalkDialog(TalkBean item) { reNameDialog(StringName.talkRenameTitle.tr, item.title.value, hintTxt: StringName.talkRenameTitleHint.tr, maxLength: 15, returnBuilder: (newName) { controller.requestName(newName, item); }); } void showDeleteTalkDialog(TalkBean item) { talkDeleteDialog(item.id, item.title.value, returnBuilder: () { controller.requestDelete(item); }); } Widget buildTalkTodoContent() { return Obx(() { if (controller.agendaList.isEmpty) { return SliverToBoxAdapter(child: buildAgendaEmptyView(50.h)); } else { return SliverList.builder( itemBuilder: _builderAgendaItem, itemCount: controller.agendaList.length >= 10 ? 10 : controller.agendaList.length); } }); } } Widget buildAgendaEmptyView(double top, {bool isVisible = true}) { return Visibility( visible: isVisible, child: Container( width: double.infinity, padding: EdgeInsets.symmetric(vertical: top), child: Column( children: [ SizedBox( width: 100.w, height: 100.w, child: Assets.images.iconNoTask.image()), SizedBox(height: 4.h), Text(StringName.agendaNoData.tr, style: TextStyle( color: ColorName.secondaryTextColor, fontSize: 14.sp)), ], ), ), ); }