|
|
@@ -0,0 +1,344 @@
|
|
|
+import 'package:clean/base/base_page.dart';
|
|
|
+import 'package:clean/module/calendar/calendar_month_controller.dart';
|
|
|
+import 'package:flutter/Material.dart';
|
|
|
+import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
|
+import 'package:get/get.dart';
|
|
|
+import 'package:wechat_assets_picker/wechat_assets_picker.dart';
|
|
|
+import '../../data/bean/photos_type.dart';
|
|
|
+import '../../resource/assets.gen.dart';
|
|
|
+import '../../router/app_pages.dart';
|
|
|
+import '../people_photo/photo_group.dart';
|
|
|
+import 'calendar_state.dart';
|
|
|
+
|
|
|
+class CalendarMonthPage extends BasePage<CalendarMonthController> {
|
|
|
+ const CalendarMonthPage({Key? key}) : super(key: key);
|
|
|
+
|
|
|
+ static void start({required PhotoGroup photoGroup}) {
|
|
|
+ Get.toNamed(RoutePath.calendarMonth, arguments: {
|
|
|
+ "PhotoGroup": photoGroup,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @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.isSelectMode.value
|
|
|
+ ? controller.isSelectMode.value = false
|
|
|
+ : controller.clickBack();
|
|
|
+ },
|
|
|
+ child: SafeArea(
|
|
|
+ child: Obx(() {
|
|
|
+ if (controller.photoGroup.value.images.isEmpty) {
|
|
|
+ return _noNoPicturesCard();
|
|
|
+ }
|
|
|
+ return Column(
|
|
|
+ children: [
|
|
|
+ _titleCard(),
|
|
|
+ Obx(() {
|
|
|
+ return Expanded(
|
|
|
+ child: GridView.builder(
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 16.w),
|
|
|
+ scrollDirection: Axis.vertical,
|
|
|
+ // 设置为垂直方向滚动
|
|
|
+ physics: BouncingScrollPhysics(),
|
|
|
+ gridDelegate:
|
|
|
+ SliverGridDelegateWithFixedCrossAxisCount(
|
|
|
+ crossAxisCount: 3, // 每行显示 3 个元素
|
|
|
+ mainAxisSpacing: 8.w, // 垂直间距
|
|
|
+ crossAxisSpacing: 8.h, // 水平间距
|
|
|
+ ),
|
|
|
+ itemCount: controller.photoGroup.value.images.length,
|
|
|
+ itemBuilder: _buildPhotoItem(
|
|
|
+ controller.photoGroup.value.images)),
|
|
|
+ );
|
|
|
+ }),
|
|
|
+ Obx(() {
|
|
|
+ return controller.isSelectMode.value
|
|
|
+ ? controller.selectedPhotosIds.isNotEmpty
|
|
|
+ ? _bottomBarCard()
|
|
|
+ : Container()
|
|
|
+ : Container();
|
|
|
+ }),
|
|
|
+ SizedBox(height: 8.h),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }),
|
|
|
+ )),
|
|
|
+ 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: [
|
|
|
+ Obx(() {
|
|
|
+ return Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
+ children: [
|
|
|
+ controller.isSelectMode.value
|
|
|
+ ? GestureDetector(
|
|
|
+ onTap: () {
|
|
|
+ controller.isSelectMode.value = false;
|
|
|
+ },
|
|
|
+ child: Container(
|
|
|
+ width: 71.w,
|
|
|
+ height: 30.h,
|
|
|
+ decoration: ShapeDecoration(
|
|
|
+ color: Color(0xFF2A3E55),
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
+ borderRadius: BorderRadius.circular(83.r),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ child: Center(
|
|
|
+ child: Text(
|
|
|
+ 'Cancel',
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.white,
|
|
|
+ fontSize: 14.sp,
|
|
|
+ fontWeight: FontWeight.w400,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ))
|
|
|
+ : GestureDetector(
|
|
|
+ onTap: controller.clickBack,
|
|
|
+ child: Assets.images.iconBackArrow.image(
|
|
|
+ width: 28.w,
|
|
|
+ height: 28.h,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ controller.photoGroup.value.images.isEmpty
|
|
|
+ ? Container()
|
|
|
+ : GestureDetector(
|
|
|
+ onTap: () => controller.isSelectMode.value
|
|
|
+ ? controller.toggleGroupSelection(
|
|
|
+ controller.photoGroup.value.images)
|
|
|
+ : null,
|
|
|
+ child: Obx(() => controller.isSelectMode.value
|
|
|
+ ? Text(
|
|
|
+ controller.photoGroup.value.isSelected.value
|
|
|
+ ? 'Deselect All'
|
|
|
+ : 'Select All',
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.white.withValues(alpha: 0.7),
|
|
|
+ fontSize: 14.sp,
|
|
|
+ fontWeight: FontWeight.w400,
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ : GestureDetector(
|
|
|
+ onTap: () {
|
|
|
+ controller.isSelectMode.value = true;
|
|
|
+ },
|
|
|
+ child: Container(
|
|
|
+ width: 71.w,
|
|
|
+ height: 30.h,
|
|
|
+ alignment: Alignment.center,
|
|
|
+ decoration: ShapeDecoration(
|
|
|
+ color: Color(0xFF1F2D3F),
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
+ borderRadius: BorderRadius.circular(83.r),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ child: Text(
|
|
|
+ 'Select',
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.white,
|
|
|
+ fontSize: 14.sp,
|
|
|
+ fontWeight: FontWeight.w400,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ )),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }),
|
|
|
+ controller.photoGroup.value.images.isEmpty
|
|
|
+ ? Container()
|
|
|
+ : Column(
|
|
|
+ children: [
|
|
|
+ SizedBox(height: 12.h),
|
|
|
+ Text(
|
|
|
+ CalendarState.formatMonth(
|
|
|
+ controller.photoGroup.value.month ?? ""),
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.white,
|
|
|
+ fontSize: 24.sp,
|
|
|
+ fontWeight: FontWeight.w700,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ SizedBox(height: 20.h),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget Function(BuildContext, int) _buildPhotoItem(
|
|
|
+ List<AssetEntity> images) =>
|
|
|
+ (context, index) {
|
|
|
+ final group = controller.photoGroup.value;
|
|
|
+
|
|
|
+ return GestureDetector(
|
|
|
+ onTap: () => controller.clickImage(images, index),
|
|
|
+ child: Obx(() {
|
|
|
+ final isSelected = group.selectedImages[index];
|
|
|
+ return Stack(
|
|
|
+ children: [
|
|
|
+ Container(
|
|
|
+ width: 104.w,
|
|
|
+ height: 104.w,
|
|
|
+ decoration: ShapeDecoration(
|
|
|
+ color: Colors.white.withValues(alpha: 0.12),
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
+ borderRadius: BorderRadius.circular(9.27.sp),
|
|
|
+ ),
|
|
|
+ image: DecorationImage(
|
|
|
+ image: AssetEntityImageProvider(
|
|
|
+ group.images[index],
|
|
|
+ thumbnailSize: const ThumbnailSize.square(300),
|
|
|
+ isOriginal: false,
|
|
|
+ ),
|
|
|
+ fit: BoxFit.cover,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Positioned(
|
|
|
+ right: 8.w,
|
|
|
+ bottom: 8.h,
|
|
|
+ child: Visibility(
|
|
|
+ visible: controller.isSelectMode.value,
|
|
|
+ child: GestureDetector(
|
|
|
+ onTap: () =>
|
|
|
+ controller.toggleImageSelection(images, index),
|
|
|
+ child: Container(
|
|
|
+ child: isSelected
|
|
|
+ ? Center(
|
|
|
+ child: Assets.images.iconSelected.image(
|
|
|
+ width: 20.w,
|
|
|
+ height: 20.h,
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ : Center(
|
|
|
+ child: Assets.images.iconUnselected.image(
|
|
|
+ width: 20.w,
|
|
|
+ height: 20.h,
|
|
|
+ )),
|
|
|
+ ))),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }),
|
|
|
+ );
|
|
|
+ };
|
|
|
+
|
|
|
+ Widget _bottomBarCard() {
|
|
|
+ return GestureDetector(
|
|
|
+ onTap: () {
|
|
|
+ // controller.clickDelete();
|
|
|
+ },
|
|
|
+ child: Container(
|
|
|
+ width: 328.w,
|
|
|
+ height: 48.h,
|
|
|
+ decoration: ShapeDecoration(
|
|
|
+ color: Color(0xFF0279FB),
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
+ borderRadius: BorderRadius.circular(10.r),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 16.w),
|
|
|
+ child: Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
+ children: [
|
|
|
+ Assets.images.iconDelete.image(
|
|
|
+ width: 18.w,
|
|
|
+ height: 18.h,
|
|
|
+ ),
|
|
|
+ SizedBox(width: 5.w),
|
|
|
+ Obx(() {
|
|
|
+ return Text(
|
|
|
+ 'delete ${controller.selectedFilesSizeString}',
|
|
|
+ textAlign: TextAlign.center,
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.white,
|
|
|
+ fontSize: 16.sp,
|
|
|
+ fontWeight: FontWeight.w500,
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget _noNoPicturesCard() {
|
|
|
+ return Column(
|
|
|
+ children: [
|
|
|
+ _titleCard(),
|
|
|
+ SizedBox(
|
|
|
+ height: 170.h,
|
|
|
+ ),
|
|
|
+ Container(
|
|
|
+ child: Column(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
+ children: [
|
|
|
+ Container(
|
|
|
+ width: 70.w,
|
|
|
+ height: 70.h,
|
|
|
+ clipBehavior: Clip.antiAlias,
|
|
|
+ decoration: BoxDecoration(),
|
|
|
+ child: Assets.images.iconNoPictures.image(),
|
|
|
+ ),
|
|
|
+ SizedBox(height: 22.h),
|
|
|
+ Text(
|
|
|
+ 'No pictures found',
|
|
|
+ textAlign: TextAlign.center,
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.white,
|
|
|
+ fontSize: 20.sp,
|
|
|
+ fontWeight: FontWeight.w700,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ SizedBox(height: 12.h),
|
|
|
+ Text(
|
|
|
+ 'No pictures available at the moment',
|
|
|
+ textAlign: TextAlign.center,
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.white.withValues(alpha: 0.6),
|
|
|
+ fontSize: 14.sp,
|
|
|
+ fontWeight: FontWeight.w400,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|