import 'package:clean/base/base_page.dart'; import 'package:clean/data/bean/photos_type.dart'; import 'package:clean/module/photo_preview/photo_preview_controller.dart'; import 'package:clean/resource/assets.gen.dart'; import 'package:clean/router/app_pages.dart'; import 'package:clean/utils/toast_util.dart'; import 'package:clean/widget/photo_swipe_card.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'; class PhotoPreviewPage extends BasePage { PhotoPreviewPage({Key? key}) : super(key: key); static void start(PhotosType photosType, String currentImageId) { print(' PhotoPreviewPage start $photosType $currentImageId'); Get.toNamed(RoutePath.photoPreview, arguments: { "photosType": photosType, "currentImageId": currentImageId, }); } @override bool immersive() { // TODO: implement immersive return true; } @override bool statusBarDarkFont() { // TODO: implement statusBarDarkFont return false; } @override Widget buildBody(BuildContext context) { return Stack(children: [ Container( child: PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) { if (didPop) { return; } controller.clickBack(); }, child: SafeArea( child: Container( child: Obx(() { if (controller.isSwiperEnd.value || controller.listAssetEntity.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.value, cardsCount: controller.listAssetEntity.length, onSwipe: controller.onSwipe, onUndo: controller.onSwiperUndo, numberOfCardsDisplayed: (controller.listAssetEntity.length == 1) ? 1 : 2, onEnd: controller.onSwiperEnd, cardBuilder: (context, index, horizontalOffsetPercentage, verticalOffsetPercentage) { print( 'index: $index, horizontalOffsetPercentage: $horizontalOffsetPercentage, verticalOffsetPercentage: $verticalOffsetPercentage'); final assetEntity = controller.listAssetEntity[index]; return Stack( children: [ ClipRRect( borderRadius: BorderRadius.circular(20.r), child: AssetEntityImage( assetEntity, width: 314.w, height: 392.h, fit: BoxFit.cover, ), ), if (horizontalOffsetPercentage != 0) Positioned( top: 0, right: horizontalOffsetPercentage < -10 ? 0 : null, left: horizontalOffsetPercentage > 10 ? 0 : null, child: Container( child: Column( children: [ (horizontalOffsetPercentage < -10) ? Assets.images.iconPhotoPreviewDelete .image( width: 60.w, height: 60.w, ) : (horizontalOffsetPercentage > 10) ? Assets .images.iconPhotoPreviewKeep .image( width: 60.w, height: 60.w, ) : SizedBox(), (horizontalOffsetPercentage < -10) ? Text( 'Delete ', style: TextStyle( color: Colors.white, fontSize: 24.sp, fontWeight: FontWeight.w500, ), ) : (horizontalOffsetPercentage > 10) ? Text( 'Keep', style: TextStyle( color: Colors.white, fontSize: 24.sp, fontWeight: FontWeight.w500, ), ) : SizedBox(), ], )), ), ], ); }, ), ), Spacer(), bottomButtonCard(), _bottomBarCard(), ], ); } }), ), ), )), Obx(() { if (controller.isSwiperEnd.value || controller.listAssetEntity.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.listAssetEntity.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 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.selectedFileCount.value} 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.listAssetEntity.isEmpty ? SizedBox() : _bottomBarCard(), ], ); } }