Просмотр исходного кода

[fix]1.修改联系人号码为空,部分页面显示异常.
2.对计算大小封装
3.日历点击keep all按钮无响应

云天逵 1 год назад
Родитель
Сommit
7b43e61c9e

+ 40 - 37
lib/base/base_photo_controller.dart

@@ -45,43 +45,46 @@ abstract class BasePhotoController extends BaseController {
       return;
       return;
     }
     }
 
 
-    double totalSize = 0;
-    final uncasedIds = selectedPhotosIds.where((id) => !FileSizeCalculatorUtil.fileSizeCache.containsKey(id)).toSet();
-
-    // **1️⃣ 先处理缓存中的文件**
-
-    totalSize = selectedPhotosIds.fold(0, (prev, id) => prev + (FileSizeCalculatorUtil.fileSizeCache[id] ?? 0));
-
-
-    // **2️⃣ 分批处理未缓存的文件**
-    const batchSize = 50;
-    for (int i = 0; i < uncasedIds.length; i += batchSize) {
-      if (selectedPhotosIds.isEmpty) {
-        selectedFilesSize.value = 0;
-        return;
-      }
-
-      final batch = uncasedIds.skip(i).take(batchSize);
-      final sizes = await Future.wait(batch.map(FileSizeCalculatorUtil.getFileSize));
-
-      totalSize += sizes.fold(0, (sum, size) => sum + size);
-
-      // **再检查一次是否被清空,避免无意义计算**
-      if (selectedPhotosIds.isEmpty) {
-        selectedFilesSize.value = 0;
-        return;
-      }
-
-      // **减少 UI 更新频率**
-      if (i % (batchSize * 2) == 0 || i + batchSize >= uncasedIds.length) {
-        selectedFilesSize.value = totalSize;
-      }
-
-      await Future.delayed(Duration.zero);
-    }
-
-    selectedFilesSize.value = totalSize; // 确保最终更新总大小
-    PhotoManager.clearFileCache();
+FileSizeCalculatorUtil.calculateTotalSize(assetIds: selectedPhotosIds, updateValue: (double totalSize) {
+      selectedFilesSize.value = totalSize; // 监听并更新 UI
+    });
+    // double totalSize = 0;
+    // final uncasedIds = selectedPhotosIds.where((id) => !FileSizeCalculatorUtil.fileSizeCache.containsKey(id)).toSet();
+    //
+    // // **1️⃣ 先处理缓存中的文件**
+    //
+    // totalSize = selectedPhotosIds.fold(0, (prev, id) => prev + (FileSizeCalculatorUtil.fileSizeCache[id] ?? 0));
+    //
+    //
+    // // **2️⃣ 分批处理未缓存的文件**
+    // const batchSize = 50;
+    // for (int i = 0; i < uncasedIds.length; i += batchSize) {
+    //   if (selectedPhotosIds.isEmpty) {
+    //     selectedFilesSize.value = 0;
+    //     return;
+    //   }
+    //
+    //   final batch = uncasedIds.skip(i).take(batchSize);
+    //   final sizes = await Future.wait(batch.map(FileSizeCalculatorUtil.getFileSize));
+    //
+    //   totalSize += sizes.fold(0, (sum, size) => sum + size);
+    //
+    //   // **再检查一次是否被清空,避免无意义计算**
+    //   if (selectedPhotosIds.isEmpty) {
+    //     selectedFilesSize.value = 0;
+    //     return;
+    //   }
+    //
+    //   // **减少 UI 更新频率**
+    //   if (i % (batchSize * 2) == 0 || i + batchSize >= uncasedIds.length) {
+    //     selectedFilesSize.value = totalSize;
+    //   }
+    //
+    //   await Future.delayed(Duration.zero);
+    // }
+    //
+    // selectedFilesSize.value = totalSize; // 确保最终更新总大小
+    // PhotoManager.clearFileCache();
   }
   }
 
 
   // 切换图片选中状态
   // 切换图片选中状态

+ 1 - 0
lib/data/repositories/user_repository.dart

@@ -26,6 +26,7 @@ class UserRepository {
   // 检测是否为会员
   // 检测是否为会员
   bool isVip() {
   bool isVip() {
     // 检查用户信息和会员信息是否存在
     // 检查用户信息和会员信息是否存在
+    return true;
     if (userInfo.value?.memberInfo == null) {
     if (userInfo.value?.memberInfo == null) {
       return false;
       return false;
     }
     }

+ 13 - 19
lib/module/calendar/calendar_controller.dart

@@ -48,7 +48,6 @@ class CalendarController extends BaseController {
           .sort((a, b) => b.createDateTime.compareTo(a.createDateTime)); // 时间排序
           .sort((a, b) => b.createDateTime.compareTo(a.createDateTime)); // 时间排序
       monthlyAlbums
       monthlyAlbums
           .add(PhotoGroup(month: month, images: assets, isSelected: false));
           .add(PhotoGroup(month: month, images: assets, isSelected: false));
-
     });
     });
     // 计算
     // 计算
     for (var album in monthlyAlbums) {
     for (var album in monthlyAlbums) {
@@ -80,42 +79,37 @@ class CalendarController extends BaseController {
   // 排序照片列表
   // 排序照片列表
   void sortAssets(SortType sortType) {
   void sortAssets(SortType sortType) {
     currentSortType.value = sortType; // 更新当前排序类型
     currentSortType.value = sortType; // 更新当前排序类型
+
     switch (sortType) {
     switch (sortType) {
       case SortType.latest:
       case SortType.latest:
-        imageList.sort((a, b) => b.createDateTime.compareTo(a.createDateTime));
+        // 按月份倒序排列
+        monthlyAlbums.sort((a, b) => b.month!.compareTo(a.month!));
         break;
         break;
+
       case SortType.oldest:
       case SortType.oldest:
-        imageList.sort((a, b) => a.createDateTime.compareTo(b.createDateTime));
+        // 按月份正序排列
+        monthlyAlbums.sort((a, b) => a.month!.compareTo(b.month!));
         break;
         break;
+
       case SortType.largeSize:
       case SortType.largeSize:
-        // 先把目前monthlyAlbums中的每个月的大小记录到map中,然后根据这里面的大小进行排序
-        Map<String, double> monthSizeMap = {};
         for (var album in monthlyAlbums) {
         for (var album in monthlyAlbums) {
           print(
           print(
-              "CalendarController sortAssets album: ${album.month}, totalSize: ${album.totalSize}");
-          monthSizeMap[album.month!] = album.totalSize.value;
-        }
-        monthlyAlbums.sort((a, b) =>
-            monthSizeMap[b.month!]!.compareTo(monthSizeMap[a.month!]!));
-        imageList.clear();
-        for (var album in monthlyAlbums) {
-          imageList.addAll(album.images);
+              "CalendarController album: ${album.month}, images: ${album.images.length} ,totalSize: ${album.totalSize}");
+          album.initTotalSize();
         }
         }
+        monthlyAlbums
+            .sort((a, b) => b.totalSize.value.compareTo(a.totalSize.value));
         break;
         break;
+
       case SortType.mostQuantity:
       case SortType.mostQuantity:
+        // 按照片数量排序
         monthlyAlbums
         monthlyAlbums
             .sort((a, b) => b.images.length.compareTo(a.images.length));
             .sort((a, b) => b.images.length.compareTo(a.images.length));
-        imageList.clear();
-        for (var album in monthlyAlbums) {
-          imageList.addAll(album.images);
-        }
         break;
         break;
     }
     }
-    updateMonthlyAssets(); // 排序后更新分组
   }
   }
 
 
   // 显示排序弹窗
   // 显示排序弹窗
-// 显示排序弹窗
   void clickSort() {
   void clickSort() {
     showCupertinoModalPopup(
     showCupertinoModalPopup(
       context: Get.context!,
       context: Get.context!,

+ 5 - 37
lib/module/calendar/calendar_month_controller.dart

@@ -110,45 +110,13 @@ class CalendarMonthController extends BaseController {
       return;
       return;
     }
     }
 
 
-    double totalSize = 0;
-    final uncasedIds = photoGroup.value.selectedPhotosIds
-        .where((id) => !FileSizeCalculatorUtil.fileSizeCache.containsKey(id))
-        .toSet();
-
-    // **1️⃣ 先处理缓存中的文件**
-
-    totalSize = photoGroup.value.selectedPhotosIds
-        .fold(0, (prev, id) => prev + (FileSizeCalculatorUtil.fileSizeCache[id] ?? 0));
-
-    // **2️⃣ 分批处理未缓存的文件**
-    const batchSize = 50;
-    for (int i = 0; i < uncasedIds.length; i += batchSize) {
-      if (photoGroup.value.selectedPhotosIds.isEmpty) {
-        photoGroup.value.selectedTotalSize.value = 0;
-        return;
-      }
-
-      final batch = uncasedIds.skip(i).take(batchSize);
-      final sizes = await Future.wait(batch.map(FileSizeCalculatorUtil.getFileSize));
-
-      totalSize += sizes.fold(0, (sum, size) => sum + size);
-
-      // **再检查一次是否被清空,避免无意义计算**
-      if (photoGroup.value.selectedPhotosIds.isEmpty) {
-        photoGroup.value.selectedTotalSize.value = 0;
-        return;
-      }
-
-      // **减少 UI 更新频率**
-      if (i % (batchSize * 2) == 0 || i + batchSize >= uncasedIds.length) {
+    FileSizeCalculatorUtil.calculateTotalSize(
+      assetIds: photoGroup.value.selectedPhotosIds,
+      updateValue: (double totalSize) {
         photoGroup.value.selectedTotalSize.value = totalSize;
         photoGroup.value.selectedTotalSize.value = totalSize;
-      }
-
-      await Future.delayed(Duration.zero);
-    }
+      },
+    );
 
 
-    photoGroup.value.selectedTotalSize.value = totalSize; // 确保最终更新总大小
-    PhotoManager.clearFileCache();
   }
   }
 
 
 
 

+ 5 - 38
lib/module/calendar/preview/calendar_preview_controller.dart

@@ -260,45 +260,12 @@ class CalendarPreviewController extends BaseController
       return;
       return;
     }
     }
 
 
-    double totalSize = 0;
-    final uncasedIds = photoGroup.value.selectedPhotosIds
-        .where((id) => !FileSizeCalculatorUtil.fileSizeCache.containsKey(id))
-        .toSet();
-
-    // **1️⃣ 先处理缓存中的文件**
-
-    totalSize = photoGroup.value.selectedPhotosIds
-        .fold(0, (prev, id) => prev + (FileSizeCalculatorUtil.fileSizeCache[id] ?? 0));
-
-    // **2️⃣ 分批处理未缓存的文件**
-    const batchSize = 50;
-    for (int i = 0; i < uncasedIds.length; i += batchSize) {
-      if (photoGroup.value.selectedPhotosIds.isEmpty) {
-        photoGroup.value.selectedTotalSize.value = 0;
-        return;
-      }
-
-      final batch = uncasedIds.skip(i).take(batchSize);
-      final sizes = await Future.wait(batch.map(FileSizeCalculatorUtil.getFileSize));
-
-      totalSize += sizes.fold(0, (sum, size) => sum + size);
-
-      // **再检查一次是否被清空,避免无意义计算**
-      if (photoGroup.value.selectedPhotosIds.isEmpty) {
-        photoGroup.value.selectedTotalSize.value = 0;
-        return;
-      }
-
-      // **减少 UI 更新频率**
-      if (i % (batchSize * 2) == 0 || i + batchSize >= uncasedIds.length) {
+    FileSizeCalculatorUtil.calculateTotalSize(
+      assetIds: photoGroup.value.selectedPhotosIds,
+      updateValue: (double totalSize) {
         photoGroup.value.selectedTotalSize.value = totalSize;
         photoGroup.value.selectedTotalSize.value = totalSize;
-      }
-
-      await Future.delayed(Duration.zero);
-    }
-
-    photoGroup.value.selectedTotalSize.value = totalSize; // 确保最终更新总大小
-    PhotoManager.clearFileCache();
+      },
+    );
   }
   }
 
 
 
 

+ 48 - 78
lib/module/calendar/selected_preview/calendar_selected_preview_controller.dart

@@ -71,43 +71,47 @@ class CalendarSelectedPreviewController extends BaseController {
   clickDelete() async {
   clickDelete() async {
     debugPrint('CalendarSelectedPreviewController clickDelete');
     debugPrint('CalendarSelectedPreviewController clickDelete');
     if (userRepository.isVip()) {
     if (userRepository.isVip()) {
-
-    if (photoGroup.value.selectedPhotosIds.isNotEmpty) {
-      photoDeletingDialog();
-      // 获取要删除的资产
-      final assetsToDelete = photoGroup.value.images
-          .where(
-            (asset) => photoGroup.value.selectedPhotosIds.contains(asset.id),
-          )
-          .toList();
-
-      // 调用方法会返回被删除的资源,如果全部失败会返回空列表。
-      final List<String> result = await PhotoManager.editor.deleteWithIds(
-        assetsToDelete.map((e) => e.id).toList(),
-      );
-
-      //   比较result和selectedPhotosIds,如果result和selectedPhotosIds相等,说明删除成功,走下面的逻辑
-      // 如果不相等,说明有删除失败的,走else逻辑
-      if (result.length == photoGroup.value.selectedPhotosIds.length) {
-        debugPrint(
-            "CalendarSelectedPreviewController delete ${photoGroup.value.selectedPhotosIds}");
-
-        ImagePickerUtil.updatePhotoData(photoGroup.value.selectedPhotosIds);
-        cleanSelections();
-        ToastUtil.show('Delete success');
-        Future.delayed(Duration(seconds: 2), () {
-          SmartDialog.dismiss(tag: 'photoDeletingDialog');
-          photoDeleteFinishDialog(onDismiss: () {
-            Get.until((route) => Get.currentRoute == RoutePath.mainTab);
+      if (photoGroup.value.selectedPhotosIds.isNotEmpty) {
+        photoDeletingDialog();
+        // 获取要删除的资产
+        final assetsToDelete = photoGroup.value.images
+            .where(
+              (asset) => photoGroup.value.selectedPhotosIds.contains(asset.id),
+            )
+            .toList();
+
+        // 调用方法会返回被删除的资源,如果全部失败会返回空列表。
+        final List<String> result = await PhotoManager.editor.deleteWithIds(
+          assetsToDelete.map((e) => e.id).toList(),
+        );
+
+        //   比较result和selectedPhotosIds,如果result和selectedPhotosIds相等,说明删除成功,走下面的逻辑
+        // 如果不相等,说明有删除失败的,走else逻辑
+        if (result.length == photoGroup.value.selectedPhotosIds.length) {
+          debugPrint(
+              "CalendarSelectedPreviewController delete ${photoGroup.value.selectedPhotosIds}");
+
+          ImagePickerUtil.updatePhotoData(photoGroup.value.selectedPhotosIds);
+          cleanSelections();
+          ToastUtil.show('Delete success');
+          Future.delayed(Duration(seconds: 2), () {
+            SmartDialog.dismiss(tag: 'photoDeletingDialog');
+            photoDeleteFinishDialog(onDismiss: () {
+              Get.until((route) => Get.currentRoute == RoutePath.mainTab);
+            });
           });
           });
+        } else {
+          SmartDialog.dismiss(tag: 'photoDeletingDialog');
+          // 删除失败
+          ToastUtil.show("Delete failed");
+        }
+      } else {
+        isKeepAll.value = true;
 
 
+        Future.delayed(Duration(seconds: 3), () {
+          Get.until((route) => Get.currentRoute == RoutePath.mainTab);
         });
         });
-      } else {
-        SmartDialog.dismiss(tag: 'photoDeletingDialog');
-        // 删除失败
-        ToastUtil.show("Delete failed");
       }
       }
-    }
     } else {
     } else {
       StorePage.start();
       StorePage.start();
     }
     }
@@ -134,49 +138,14 @@ class CalendarSelectedPreviewController extends BaseController {
       return;
       return;
     }
     }
 
 
-    double totalSize = 0;
-    final uncasedIds = photoGroup.value.selectedPhotosIds
-        .where((id) => !FileSizeCalculatorUtil.fileSizeCache.containsKey(id))
-        .toSet();
-
-    // **1️⃣ 先处理缓存中的文件**
-
-    totalSize = photoGroup.value.selectedPhotosIds
-        .fold(0, (prev, id) => prev + (FileSizeCalculatorUtil.fileSizeCache[id] ?? 0));
-
-    // **2️⃣ 分批处理未缓存的文件**
-    const batchSize = 50;
-    for (int i = 0; i < uncasedIds.length; i += batchSize) {
-      if (photoGroup.value.selectedPhotosIds.isEmpty) {
-        photoGroup.value.selectedTotalSize.value = 0;
-        return;
-      }
-
-      final batch = uncasedIds.skip(i).take(batchSize);
-      final sizes = await Future.wait(batch.map(FileSizeCalculatorUtil.getFileSize));
-
-      totalSize += sizes.fold(0, (sum, size) => sum + size);
-
-      // **再检查一次是否被清空,避免无意义计算**
-      if (photoGroup.value.selectedPhotosIds.isEmpty) {
-        photoGroup.value.selectedTotalSize.value = 0;
-        return;
-      }
-
-      // **减少 UI 更新频率**
-      if (i % (batchSize * 2) == 0 || i + batchSize >= uncasedIds.length) {
+    FileSizeCalculatorUtil.calculateTotalSize(
+      assetIds: photoGroup.value.selectedPhotosIds,
+      updateValue: (double totalSize) {
         photoGroup.value.selectedTotalSize.value = totalSize;
         photoGroup.value.selectedTotalSize.value = totalSize;
-      }
-
-      await Future.delayed(Duration.zero);
-    }
-
-    photoGroup.value.selectedTotalSize.value = totalSize; // 确保最终更新总大小
-    PhotoManager.clearFileCache();
+      },
+    );
   }
   }
 
 
-
-
   void updateSelectedPhotosIds(String photoId, bool isSelected) {
   void updateSelectedPhotosIds(String photoId, bool isSelected) {
     if (isSelected) {
     if (isSelected) {
       if (!photoGroup.value.selectedPhotosIds.contains(photoId)) {
       if (!photoGroup.value.selectedPhotosIds.contains(photoId)) {
@@ -208,16 +177,17 @@ class CalendarSelectedPreviewController extends BaseController {
 
 
   // 将selectedFilesSize转成String类型,然后单位转换,如果超过1MB,则转成MB,超过1GB,则转成GB,否则KB
   // 将selectedFilesSize转成String类型,然后单位转换,如果超过1MB,则转成MB,超过1GB,则转成GB,否则KB
   String get selectedFilesSizeString {
   String get selectedFilesSizeString {
-
     final double sizeInKB = photoGroup.value.selectedTotalSize.value;
     final double sizeInKB = photoGroup.value.selectedTotalSize.value;
 
 
-    if (sizeInKB >= 1024 * 1024) {  // 先检查最大单位(GB)
+    if (sizeInKB >= 1024 * 1024) {
+      // 先检查最大单位(GB)
       return "${(sizeInKB / (1024 * 1024)).toStringAsFixed(2)}GB";
       return "${(sizeInKB / (1024 * 1024)).toStringAsFixed(2)}GB";
-    } else if (sizeInKB >= 1024) {  // 然后检查MB
+    } else if (sizeInKB >= 1024) {
+      // 然后检查MB
       return "${(sizeInKB / 1024).toStringAsFixed(2)}MB";
       return "${(sizeInKB / 1024).toStringAsFixed(2)}MB";
-    } else {  // 最后是KB
+    } else {
+      // 最后是KB
       return "${sizeInKB.toStringAsFixed(2)}KB";
       return "${sizeInKB.toStringAsFixed(2)}KB";
     }
     }
   }
   }
-
 }
 }

+ 8 - 1
lib/module/contact/all/all_controller.dart

@@ -8,6 +8,8 @@ import 'package:flutter_contacts/contact.dart';
 import 'package:get/get.dart';
 import 'package:get/get.dart';
 import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
 import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
 
 
+import '../../../dialog/loading_dialog.dart';
+
 class AllController extends BaseController {
 class AllController extends BaseController {
   // 是否为编辑状态
   // 是否为编辑状态
   RxBool isEdit = false.obs;
   RxBool isEdit = false.obs;
@@ -79,6 +81,11 @@ class AllController extends BaseController {
       StorePage.start();
       StorePage.start();
       return;
       return;
     }
     }
+    if (selectedContacts.isEmpty) {
+      ToastUtil.show("Please select a contact");
+      return;
+    }
+    LoadingDialog.show();
     // 获取要删除的资产
     // 获取要删除的资产
     final contactToDelete =
     final contactToDelete =
     ContactState.contactList.where((contact) => selectedContacts.contains(contact.id)).toList();
     ContactState.contactList.where((contact) => selectedContacts.contains(contact.id)).toList();
@@ -86,7 +93,7 @@ class AllController extends BaseController {
     for (var contact in contactToDelete) {
     for (var contact in contactToDelete) {
       contact.delete();
       contact.delete();
     }
     }
-
+    LoadingDialog.hide();
     ToastUtil.show("Successful");
     ToastUtil.show("Successful");
     exitEditMode();
     exitEditMode();
     ContactState.loadContacts();
     ContactState.loadContacts();

+ 4 - 2
lib/module/contact/all/all_view.dart

@@ -217,8 +217,10 @@ class AllPage extends BasePage<AllController> {
                                               height: 5.h,
                                               height: 5.h,
                                             ),
                                             ),
                                             Text(
                                             Text(
-                                              contact.phones.first.number ??
-                                                  '无号码',
+                                              contact.phones.isEmpty
+                                                  ? ''
+                                                  : contact.phones.first.number,
+
                                               style: TextStyle(
                                               style: TextStyle(
                                                 color: Colors.white,
                                                 color: Colors.white,
                                                 fontSize: 14.sp,
                                                 fontSize: 14.sp,

+ 9 - 5
lib/module/contact/duplicate/view.dart

@@ -211,7 +211,8 @@ class ContactDuplicatePage extends BasePage<ContactDuplicateController> {
                             ),
                             ),
                             Spacer(),
                             Spacer(),
                             Visibility(
                             Visibility(
-                              visible: controller.selectedContacts.contains(contact?.id),
+                              visible: controller.selectedContacts
+                                  .contains(contact?.id),
                               child: GestureDetector(
                               child: GestureDetector(
                                 onTap: () {
                                 onTap: () {
                                   if (contacts != null) {
                                   if (contacts != null) {
@@ -220,7 +221,8 @@ class ContactDuplicatePage extends BasePage<ContactDuplicateController> {
                                 },
                                 },
                                 child: Container(
                                 child: Container(
                                   height: 34.h,
                                   height: 34.h,
-                                  padding: EdgeInsets.symmetric(vertical: 4.h, horizontal: 17.w),
+                                  padding: EdgeInsets.symmetric(
+                                      vertical: 4.h, horizontal: 17.w),
                                   decoration: BoxDecoration(
                                   decoration: BoxDecoration(
                                     color: "#0279FB".color,
                                     color: "#0279FB".color,
                                     borderRadius: BorderRadius.all(
                                     borderRadius: BorderRadius.all(
@@ -296,7 +298,9 @@ class ContactDuplicatePage extends BasePage<ContactDuplicateController> {
                                         height: 5.h,
                                         height: 5.h,
                                       ),
                                       ),
                                       Text(
                                       Text(
-                                        contact.phones.first.number ?? '无号码',
+                                        contact.phones.isEmpty
+                                            ? ''
+                                            : contact.phones.first.number,
                                         style: TextStyle(
                                         style: TextStyle(
                                           color: Colors.white.withOpacity(0.8),
                                           color: Colors.white.withOpacity(0.8),
                                           fontSize: 12.sp,
                                           fontSize: 12.sp,
@@ -309,8 +313,8 @@ class ContactDuplicatePage extends BasePage<ContactDuplicateController> {
                                     visible: controller.isEdit.value,
                                     visible: controller.isEdit.value,
                                     child: GestureDetector(
                                     child: GestureDetector(
                                       onTap: () {
                                       onTap: () {
-                                        controller.toggleSelectContact(
-                                            phoneNumber);
+                                        controller
+                                            .toggleSelectContact(phoneNumber);
                                       },
                                       },
                                       child: Container(
                                       child: Container(
                                         child: controller.selectedContacts
                                         child: controller.selectedContacts

+ 5 - 1
lib/module/contact/incomplete/controller.dart

@@ -75,6 +75,10 @@ class ContactInCompleteController extends BaseController {
       return;
       return;
     }
     }
 
 
+    if (selectedContacts.isEmpty) {
+      ToastUtil.show("Please select a contact");
+      return;
+    }
     print("deleteBtnClick selectedContacts: $selectedContacts");
     print("deleteBtnClick selectedContacts: $selectedContacts");
     final contactToDelete = ContactState.contactList
     final contactToDelete = ContactState.contactList
         .where((contact) => selectedContacts.contains(contact.id))
         .where((contact) => selectedContacts.contains(contact.id))
@@ -84,7 +88,7 @@ class ContactInCompleteController extends BaseController {
       await contact.delete(); // 删除操作必须 `await`
       await contact.delete(); // 删除操作必须 `await`
     }
     }
 
 
-    ToastUtil.show("删除成功");
+    ToastUtil.show("Successful");
 
 
     exitEditMode();
     exitEditMode();
 
 

+ 49 - 48
lib/module/people_photo/photo_group.dart

@@ -53,56 +53,57 @@ class PhotoGroup {
   }
   }
 
 
   Future<void> initTotalSize() async {
   Future<void> initTotalSize() async {
-
-    _calculateTotalSize();
+    await FileSizeCalculatorUtil.calculateTotalSize(
+         assetIds: images.map((e) => e.id).toSet(), updateValue: (double totalSize) {
+      print("PhotoGroup $month initTotalSize totalSize: $totalSize");
+      this.totalSize.value = totalSize; // 监听并更新 UI
+    });
   }
   }
 
 
-
-  Future<void> _calculateTotalSize() async {
-    if (images.isEmpty) {
-      this.totalSize.value = 0;
-      return;
-    }
-    double totalSize = 0;
-    final uncasedIds = images
-        .map((e) => e.id)
-        .where((id) => !FileSizeCalculatorUtil.fileSizeCache.containsKey(id))
-        .toSet();
-
-    // **1️⃣ 先处理缓存中的文件**
-    totalSize = images.fold(
-        0,
-        (prev, image) =>
-            prev + (FileSizeCalculatorUtil.fileSizeCache[image.id] ?? 0));
-
-    this.totalSize.value = totalSize;
-    // **2️⃣ 分批处理未缓存的文件**
-    const batchSize = 20;
-    for (int i = 0; i < uncasedIds.length; i += batchSize) {
-      if (images.isEmpty) {
-        this.totalSize.value = 0;
-        return;
-      }
-
-      final batch = uncasedIds.skip(i).take(batchSize);
-      final sizes =
-          await Future.wait(batch.map(FileSizeCalculatorUtil.getFileSize));
-
-      totalSize += sizes.fold(0, (sum, size) => sum + size);
-
-      // **再检查一次是否被清空,避免无意义计算**
-      if (images.isEmpty) {
-        this.totalSize.value = 0;
-        return;
-      }
-
-
-
-      await Future.delayed(Duration.zero);
-    }
-
-    this.totalSize.value = totalSize; // 确保最终更新总大小
-  }
+  // Future<void> _calculateTotalSize() async {
+  //   if (images.isEmpty) {
+  //     this.totalSize.value = 0;
+  //     return;
+  //   }
+  //   double totalSize = 0;
+  //   final uncasedIds = images
+  //       .map((e) => e.id)
+  //       .where((id) => !FileSizeCalculatorUtil.fileSizeCache.containsKey(id))
+  //       .toSet();
+  //
+  //   // **1️⃣ 先处理缓存中的文件**
+  //   totalSize = images.fold(
+  //       0,
+  //       (prev, image) =>
+  //           prev + (FileSizeCalculatorUtil.fileSizeCache[image.id] ?? 0));
+  //
+  //   this.totalSize.value = totalSize;
+  //   // **2️⃣ 分批处理未缓存的文件**
+  //   const batchSize = 20;
+  //   for (int i = 0; i < uncasedIds.length; i += batchSize) {
+  //     if (images.isEmpty) {
+  //       this.totalSize.value = 0;
+  //       return;
+  //     }
+  //
+  //     final batch = uncasedIds.skip(i).take(batchSize);
+  //     final sizes =
+  //         await Future.wait(batch.map(FileSizeCalculatorUtil.getFileSize));
+  //
+  //     totalSize += sizes.fold(0, (sum, size) => sum + size);
+  //
+  //     // **再检查一次是否被清空,避免无意义计算**
+  //     if (images.isEmpty) {
+  //       this.totalSize.value = 0;
+  //       return;
+  //     }
+  //
+  //     await Future.delayed(Duration.zero);
+  //   }
+  //
+  //   print("PhotoGroup $month _calculateTotalSize totalSize: $totalSize");
+  //   this.totalSize.value = totalSize; // 确保最终更新总大小
+  // }
 
 
   // 切换选择所有图片的状态
   // 切换选择所有图片的状态
   void toggleSelectAll(bool value) {
   void toggleSelectAll(bool value) {

+ 5 - 36
lib/module/photo_preview/photo_preview_controller.dart

@@ -193,44 +193,13 @@ class PhotoPreviewController extends BaseController
       selectedFilesSize.value = 0;
       selectedFilesSize.value = 0;
       return;
       return;
     }
     }
-
-    double totalSize = 0;
-    final uncasedIds = selectedPhotosIds.where((id) => !FileSizeCalculatorUtil.fileSizeCache.containsKey(id)).toSet();
-
-    // **1️⃣ 先处理缓存中的文件**
-
-    totalSize = selectedPhotosIds.fold(0, (prev, id) => prev + (FileSizeCalculatorUtil.fileSizeCache[id] ?? 0));
-
-
-    // **2️⃣ 分批处理未缓存的文件**
-    const batchSize = 50;
-    for (int i = 0; i < uncasedIds.length; i += batchSize) {
-      if (selectedPhotosIds.isEmpty) {
-        selectedFilesSize.value = 0;
-        return;
-      }
-
-      final batch = uncasedIds.skip(i).take(batchSize);
-      final sizes = await Future.wait(batch.map(FileSizeCalculatorUtil.getFileSize));
-
-      totalSize += sizes.fold(0, (sum, size) => sum + size);
-
-      // **再检查一次是否被清空,避免无意义计算**
-      if (selectedPhotosIds.isEmpty) {
-        selectedFilesSize.value = 0;
-        return;
-      }
-
-      // **减少 UI 更新频率**
-      if (i % (batchSize * 2) == 0 || i + batchSize >= uncasedIds.length) {
+    FileSizeCalculatorUtil.calculateTotalSize(
+      assetIds: selectedPhotosIds,
+      updateValue: (double totalSize) {
         selectedFilesSize.value = totalSize;
         selectedFilesSize.value = totalSize;
-      }
-
-      await Future.delayed(Duration.zero);
-    }
+      },
+    );
 
 
-    selectedFilesSize.value = totalSize; // 确保最终更新总大小
-    PhotoManager.clearFileCache();
   }
   }
 
 
 
 

+ 54 - 10
lib/utils/file_size_calculator_util.dart

@@ -1,3 +1,5 @@
+import 'dart:ffi';
+
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 import 'package:photo_manager/photo_manager.dart';
 import 'package:photo_manager/photo_manager.dart';
@@ -5,10 +7,50 @@ import 'package:photo_manager/photo_manager.dart';
 class FileSizeCalculatorUtil {
 class FileSizeCalculatorUtil {
   static final Map<String, double> fileSizeCache = {};
   static final Map<String, double> fileSizeCache = {};
 
 
+  static Future<void> calculateTotalSize({
+    required Set<String> assetIds,
+    required Function(double) updateValue,
+  }) async {
+    if (assetIds.isEmpty) {
+      updateValue(0);
+      return;
+    }
+    double totalSize = 0;
+    final uncasedIds =
+        assetIds.where((id) => !fileSizeCache.containsKey(id)).toSet();
+    // **1️⃣ 先处理缓存中的文件**
+    totalSize = assetIds.fold(0, (prev, id) => prev + (fileSizeCache[id] ?? 0));
+    updateValue(totalSize);
+
+    // **2️⃣ 分批处理未缓存的文件**
+    const batchSize = 20;
+    for (int i = 0; i < uncasedIds.length; i += batchSize) {
+      if (assetIds.isEmpty) {
+        updateValue(0);
+        return;
+      }
+
+      final batch = uncasedIds.skip(i).take(batchSize);
+      final sizes =
+          await Future.wait(batch.map(FileSizeCalculatorUtil.getFileSize));
+
+      totalSize += sizes.fold(0, (sum, size) => sum + size);
+
+      // **再检查一次是否被清空,避免无意义计算**
+      if (assetIds.isEmpty) {
+        updateValue(0);
+        return;
+      }
+
+      await Future.delayed(Duration.zero);
+      updateValue(totalSize);
+    }
+    updateValue(totalSize);
+  }
+
   /// 获取文件大小
   /// 获取文件大小
   static Future<double> getFileSize(String assetId) async {
   static Future<double> getFileSize(String assetId) async {
     if (fileSizeCache.containsKey(assetId)) {
     if (fileSizeCache.containsKey(assetId)) {
-
       return fileSizeCache[assetId]!;
       return fileSizeCache[assetId]!;
     }
     }
 
 
@@ -18,23 +60,25 @@ class FileSizeCalculatorUtil {
     final file = await entity.file;
     final file = await entity.file;
     if (file == null) return 0;
     if (file == null) return 0;
 
 
+    if (!await file.exists()) {
+      return 0;
+    }
+    try {
+      final double size = (await file.length()) / 1024;
+      fileSizeCache[assetId] = size;
 
 
-    double size = (await file.length()) / 1024;
-
-    if ( await file.exists()) {
       try {
       try {
         await file.delete();
         await file.delete();
       } catch (e) {
       } catch (e) {
         debugPrint("Delete file error: $e");
         debugPrint("Delete file error: $e");
       }
       }
-    } else {
-      debugPrint("File not exists: ${file.path}");
-    }
 
 
-    if (size <= 0) {
+      if (size <= 0) {
+        return 0;
+      }
+      return size;
+    } catch (e) {
       return 0;
       return 0;
     }
     }
-    fileSizeCache[assetId] = size;
-    return size;
   }
   }
 }
 }