import 'dart:io'; import 'package:auto_route/auto_route.dart'; import 'package:eitc_erm_dental_flutter/app_router.gr.dart'; import 'package:eitc_erm_dental_flutter/entity/history_item_info.dart'; import 'package:eitc_erm_dental_flutter/funcs.dart'; import 'package:eitc_erm_dental_flutter/pages/history/vm/history_view_model.dart'; import 'package:eitc_erm_dental_flutter/pages/history/widget/history_item_view.dart'; import 'package:eitc_erm_dental_flutter/widget/main_button.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; ///历史记录页面 @RoutePage(name: "historyRoute") class HistoryPage extends ConsumerStatefulWidget { const HistoryPage({super.key}); @override ConsumerState createState() => _HistoryPageState(); } class _HistoryPageState extends ConsumerState { //照片列表 final List _photoList = []; //视频列表 final List _videoList = []; @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return PopScope( canPop: false, onPopInvokedWithResult: _onPop, child: Scaffold( appBar: _getAppBar(context), body: Padding( padding: EdgeInsets.symmetric(horizontal: 16.w), child: Column( children: [ _getSelectedCount(context), Expanded(child: _getListWidget(context)), _getBottomButtons(context), SizedBox( height: 5.h, ) ], ), ), )); } ///pop拦截 void _onPop(bool didPop, _) { if (didPop) { return; } if (ref.read(historySelectModeProvider)) { _setSelectMode(false); return; } Navigator.pop(context); } ///获取appbar AppBar _getAppBar(BuildContext context) { return AppBar( centerTitle: true, forceMaterialTransparency: true, title: Text(getS().history), leading: IconButton( onPressed: () { Navigator.pop(context); }, icon: Icon( Platform.isIOS ? Icons.arrow_back_ios_new : Icons.arrow_back)), actions: [ PopupMenuButton( icon: const Icon(Icons.menu), //弹出菜单背景色 color: const Color(0xFF383838), //背景形状 shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.r)), itemBuilder: (ctx) { return [ PopupMenuItem( child: SizedBox( width: double.infinity, child: Text( getS().byTime, textAlign: TextAlign.center, style: const TextStyle(color: Colors.white), ), ), onTap: () => _updateListType(0), ), PopupMenuItem( child: SizedBox( width: double.infinity, child: Text( getS().byCategory, textAlign: TextAlign.center, style: const TextStyle(color: Colors.white), ), ), onTap: () => _updateListType(1), ) ]; }), ], ); } ///更新列表类型 void _updateListType(int type) { if (ref.read(historyViewTypeProvider) == type) { return; } ref.read(historyViewTypeProvider.notifier).setType(type); } ///获取已选择数量widget Widget _getSelectedCount(BuildContext context) { return Consumer(builder: (ctx, ref, _) { bool isSelectedMode = ref.watch(historySelectModeProvider); Color primaryColor = Theme.of(context).colorScheme.primary; //如果不用Visibility的方式,当进入选择模式时,GridView会滚到最上面 return Visibility( visible: isSelectedMode, child: Row( children: [ Consumer(builder: (_, tref, __) { int count = tref.watch(historySelectedCountProvider); return Text(getS().hasSelectCountItem(count)); }), SizedBox( width: 6.w, ), ElevatedButton( onPressed: () => _setSelectMode(false), style: ButtonStyle( minimumSize: const WidgetStatePropertyAll(Size.zero), padding: WidgetStatePropertyAll(EdgeInsets.symmetric( horizontal: 15.w, vertical: 4.h)), elevation: const WidgetStatePropertyAll(0.0), backgroundColor: const WidgetStatePropertyAll(Color(0xFFCEDCF0))), child: Row( children: [ Text( getS().cancel, style: TextStyle(color: primaryColor, fontSize: 12.sp), ), SizedBox( width: 5.w, ), Icon(Icons.close, size: 18.r, color: primaryColor) ], )), const Spacer(), SizedBox( width: 25.w, child: Consumer(builder: (_, cref, __) { int count = cref.watch(historySelectedCountProvider); return Checkbox( value: count == (cref .read(historyListProvider) .value ?.getMergedList(false) .length ?? 0), shape: const CircleBorder(), onChanged: (bo) => cref .read(historyListProvider.notifier) .selectAll(bo ?? false)); })), Text(getS().selectAll), SizedBox( width: 5.w, ), ], )); }); } Widget _getLoading() { return Center( child: Row( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Icon( Icons.downloading, size: 35.r, ), SizedBox( width: 10.w, ), Text( getS().loadingHistories, ) ], ), ); } Widget _getEmpty() { return Center( child: Row( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Icon( Icons.sentiment_dissatisfied, size: 35.r, ), SizedBox( width: 10.w, ), Text( getS().noHistories, ) ], ), ); } Widget _getListWidget(BuildContext context) { return Consumer(builder: (ctx, ref, _) { AsyncValue value = ref.watch(historyListProvider); int viewType = ref.watch(historyViewTypeProvider); return switch (value) { AsyncData(value: var data) => data.isEmpty ? _getEmpty() : (viewType == 0 ? _getTimeList(data) : _getTypeList(ctx, data)), _ => _getLoading() }; }); } ///获取按时间列表 Widget _getTimeList(HistoryListData data) { return _getGridView(data.getMergedList(true)); } ///获取按类型列表 Widget _getTypeList(BuildContext context, HistoryListData data) { return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( getS().photo, style: Theme.of(context).textTheme.titleMedium, ), SizedBox( height: 10.h, ), _getGridView(data.photoList, shinkWarp: true, scrollable: false), SizedBox( height: 10.h, ), Text( getS().video, style: Theme.of(context).textTheme.titleMedium, ), SizedBox( height: 10.h, ), _getGridView(data.videoList, shinkWarp: true, scrollable: false) ], ), ); } ///获取GridView Widget _getGridView(List list, {bool shinkWarp = false, bool scrollable = true}) { return GridView.builder( shrinkWrap: shinkWarp, physics: scrollable ? const ClampingScrollPhysics() : const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 164.0 / 120.0, mainAxisSpacing: 8.r, crossAxisSpacing: 15.r), itemBuilder: (ctx, index) { HistoryItemInfo item = list[index]; return GestureDetector( child: HistoryItemView( index: index, name: item.name, path: item.path, type: item.type, ), onTap: () => _onTap(ctx, item), onLongPress: () => _onLongPress(ctx, item), ); }, itemCount: list.length, ); } ///点击 void _onTap(BuildContext context, HistoryItemInfo info) async { if (ref.read(historySelectModeProvider)) { ref.read(historyListProvider.notifier).select(info, !info.isSelected); return; } await context.pushRoute(info.type == 0 ? PhotoViewRoute(info: info) : VideoPlayerRoute(info: info)); } ///长按 void _onLongPress(BuildContext context, HistoryItemInfo info) { if (ref.read(historySelectModeProvider)) { return; } _setSelectMode(true); ref.read(historyListProvider.notifier).select(info, true); } ///设置选择模式 void _setSelectMode(bool isSelectMode) { ref.read(historySelectModeProvider.notifier).setSelectMode(isSelectMode); } ///获取选择的条目 List _getSelectedItems() { return ref.read(historyListProvider.notifier).getSelectedItems(); } ///获取底部按钮 Widget _getBottomButtons(BuildContext context) { bool isSelectedMode = ref.watch(historySelectModeProvider); //如果不用Visibility的方式,当进入选择模式时,GridView会滚到最上面 return Visibility( visible: isSelectedMode, child: Row( children: [ Expanded( child: MainButton( text: getS().upload, onPressed: () => _onUpload(context)), ), SizedBox( width: 15.w, ), Expanded( child: MainButton( text: getS().delete, onPressed: () => _onDelete(context), isOutlined: true, )), ], )); } ///上传 void _onUpload(BuildContext context) async { if (!await checkInternetWifi()) { return; } List list = _getSelectedItems(); if (list.isEmpty) { showToast(text: getS().pleaseSelectToUpload); return; } if (context.mounted) { context.pushRoute( UploadSelectClinicRoute(uploadList: list, isFromView: false)); } } ///删除 void _onDelete(BuildContext context) async { List list = _getSelectedItems(); if (list.isEmpty) { showToast(text: getS().pleaseSelectToDelete); return; } bool? bo = await showDeleteAlertDialog( context, getS().deleteMultiHint(list.length)); if (bo == null || !bo) { return; } bool result = await ref.read(historyListProvider.notifier).delete(list); showToast(text: result ? getS().deleteSuccess : getS().deleteFailed); } }