import 'package:clean/base/base_page.dart'; import 'package:clean/module/calendar/preview/calendar_preview_controller.dart'; import 'package:flutter/Material.dart'; import 'package:flutter/src/widgets/framework.dart'; import 'package:flutter_card_swiper/flutter_card_swiper.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:lottie/lottie.dart'; import 'package:wechat_assets_picker/wechat_assets_picker.dart'; import '../../../resource/assets.gen.dart'; import '../../../router/app_pages.dart'; import '../../../utils/styles.dart'; import '../../people_photo/photo_group.dart'; import 'package:video_player/video_player.dart'; class CalendarPreviewPage extends BasePage { const CalendarPreviewPage({Key? key}) : super(key: key); static void start( {required PhotoGroup photoGroup, required String currentImageId}) { Get.toNamed(RoutePath.calendarPreview, arguments: { "photoGroup": photoGroup, "currentImageId": currentImageId, }); } @override bool statusBarDarkFont() { return false; } @override bool immersive() { return true; } @override Widget buildBody(BuildContext context) { return Stack(children: [ PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) { if (didPop) { return; } controller.clickBack(); }, child: SafeArea( child: Obx(() { if (controller.isSwiperEnd.value || controller.photoGroup.value.images.isEmpty) { return onSwiperEndCard(); } else { return Column( children: [ _titleCard(), Spacer(), SizedBox( width: 314.w, height: 392.h, child: CardSwiper( scale: 0.8, allowedSwipeDirection: AllowedSwipeDirection.only( right: true, left: true, ), isLoop: false, backCardOffset: Offset(0.w, -20.h), controller: controller.cardSwiperController, cardsCount: controller.photoGroup.value.images.length, onSwipe: controller.onSwipe, onUndo: controller.onSwiperUndo, numberOfCardsDisplayed: (controller.photoGroup.value.images.length == 1) ? 1 : 1, onEnd: controller.onSwiperEnd, cardBuilder: (context, index, horizontalOffsetPercentage, verticalOffsetPercentage) { final assetEntity = controller.photoGroup.value.images[index]; return Stack( children: [ ClipRRect( borderRadius: BorderRadius.circular(20.r), child: // 判断这个是不是视频 assetEntity.type == AssetType.video ? Stack( alignment: Alignment.center, children: [ AssetEntityImage( assetEntity, width: 314.w, height: 392.h, fit: BoxFit.cover, ), GestureDetector( // 点击播放视频 onTap: () => controller .playVideo(assetEntity), child: Icon( Icons.play_circle_filled, size: 50.w, color: Colors.white .withValues(alpha: 0.8), ), ) ], ) : AssetEntityImage( assetEntity, width: 314.w, height: 392.h, fit: BoxFit.cover, isOriginal: true, // errorBuilder: // (context, error, stackTrace) { // debugPrint( // 'AssetEntityImage error $error'); // return Container(); // }, frameBuilder: Styles.animFrameBuilder(), )), if (horizontalOffsetPercentage != 0) Positioned( top: 0, right: horizontalOffsetPercentage < -10.w ? 0 : null, left: horizontalOffsetPercentage > 10.w ? 0 : null, child: Container( child: Column( children: [ (horizontalOffsetPercentage < -10.w) ? Assets.images.iconPhotoPreviewDelete .image( width: 60.w, height: 60.w, ) : (horizontalOffsetPercentage > 10.w) ? Assets.images.iconPhotoPreviewKeep .image( width: 60.w, height: 60.w, ) : SizedBox(), (horizontalOffsetPercentage < -10.w) ? Text( 'Delete ', style: TextStyle( color: Colors.white, fontSize: 24.sp, fontWeight: FontWeight.w500, ), ) : (horizontalOffsetPercentage > 10.w) ? Text( 'Keep', style: TextStyle( color: Colors.white, fontSize: 24.sp, fontWeight: FontWeight.w500, ), ) : SizedBox(), ], )), ), ], ); }, ), ), Spacer(), bottomButtonCard(), _bottomBarCard(), ], ); } }), ), ), Obx(() { if (controller.isSwiperEnd.value || controller.photoGroup.value.images.isEmpty) { return IgnorePointer( child: Assets.images.bgPhotoSelectedPreviewFinish.image( width: 360.w, ), ); } else { return IgnorePointer( child: Assets.images.bgHome.image( width: 360.w, ), ); } }), ]); } Widget _titleCard() { return Container( alignment: Alignment.centerLeft, padding: EdgeInsets.only(left: 16.w, top: 14.h, right: 16.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( onTap: controller.clickBack, child: Assets.images.iconBackArrow.image( width: 28.w, height: 28.h, ), ), Obx(() => Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '${controller.groupIndex.value + 1}', textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 16.sp, fontWeight: FontWeight.w700, ), ), Text( ' / ${controller.photoGroup.value.images.length}', textAlign: TextAlign.center, style: TextStyle( color: Colors.white.withValues(alpha: 0.6), fontSize: 16.sp, fontWeight: FontWeight.w500, ), ), ], )), GestureDetector( onTap: controller.recoverSelectPhoto, child: Assets.images.iconPreviewRecover.image( width: 30.w, height: 30.h, ), ), ], ), SizedBox(height: 12.h), ], ), ); } Widget _bottomBarCard() { return GestureDetector( onTap: controller.clickJumpSelected, child: Container( width: 360.w, height: 81.h, padding: EdgeInsets.symmetric(horizontal: 16.w), decoration: ShapeDecoration( color: Color(0xFF23232A), shape: RoundedRectangleBorder( side: BorderSide( width: 1.w, color: Colors.white.withValues(alpha: 0.1)), borderRadius: BorderRadius.only( topLeft: Radius.circular(14.r), topRight: Radius.circular(14.r), ), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Obx(() { return Text( '${controller.photoGroup.value.selectedPhotosIds.length} files selected (${controller.selectedFilesSizeString} )', textAlign: TextAlign.center, style: TextStyle( color: Colors.white.withValues(alpha: 0.9), fontSize: 13.sp, fontWeight: FontWeight.w500, ), ); }), GestureDetector( onTap: controller.clickDelete, child: Container( width: 108.w, height: 38.h, decoration: ShapeDecoration( color: Color(0xFF0279FB), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.r), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Text( 'Delete', textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 16.sp, fontWeight: FontWeight.w500, ), ), Assets.images.iconDelete.image( width: 18.w, height: 18.h, ), ], ), )), ], ), )); } Widget bottomButtonCard() { return Container( margin: EdgeInsets.only(bottom: 54.h), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ GestureDetector( onTap: () => controller.clickSelect(), child: Assets.images.iconPreviewSelect.image( width: 62.w, height: 62.h, ), ), GestureDetector( onTap: () => controller.clickUnselect(), child: Assets.images.iconPreviewNoSelect.image( width: 62.w, height: 62.h, ), ), ], ), ); } Widget onSwiperEndCard() { return Column( children: [ Container( child: Lottie.asset( Assets.anim.animFireworks, controller: controller.animationController, height: 351.h, repeat: false, ), ), Visibility( visible: controller.animationIsComplete.value, child: Center( child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'Perfect!', textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 32.sp, fontWeight: FontWeight.w700, ), ), SizedBox(height: 16.h), SizedBox( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( clipBehavior: Clip.antiAlias, decoration: BoxDecoration(), child: Assets.images.iconPreviewSwiperEndFirework.image( width: 40.w, height: 40.w, ), ), SizedBox(width: 4.w), Text( 'All Similar and Redundant\nPhotos Cleared', textAlign: TextAlign.center, style: TextStyle( color: Colors.white.withValues(alpha: 0.9), fontSize: 16.sp, fontWeight: FontWeight.w400, ), ), SizedBox(width: 4.w), Container( clipBehavior: Clip.antiAlias, decoration: BoxDecoration(), child: Assets.images.iconPreviewSwiperEndFirework.image( width: 40.w, height: 40.w, ), ), ], ), ), ], ), )), Spacer( flex: 5, ), controller.photoGroup.value.images.isEmpty ? SizedBox() : _bottomBarCard(), ], ); } }