similar_photo_controller.dart 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import 'dart:io';
  2. import 'package:get/get.dart';
  3. import 'package:path_provider/path_provider.dart';
  4. import 'package:path/path.dart' as p;
  5. class PhotoGroup {
  6. final String title;
  7. final int imageCount;
  8. final RxBool isSelected;
  9. final List<String> images;
  10. final RxList<bool> selectedImages;
  11. int get selectedCount => selectedImages.where((selected) => selected).length;
  12. PhotoGroup({
  13. required this.title,
  14. required this.imageCount,
  15. required bool isSelected,
  16. required this.images,
  17. }) : isSelected = isSelected.obs,
  18. selectedImages = List.generate(imageCount, (_) => isSelected).obs;
  19. void toggleSelectAll(bool value) {
  20. isSelected.value = value;
  21. selectedImages.assignAll(List.generate(images.length, (_) => value));
  22. }
  23. }
  24. class SimilarPhotoController extends GetxController {
  25. final RxList<PhotoGroup> photoGroups = <PhotoGroup>[].obs;
  26. static final Map<String, List<bool>> _savedSelections = {};
  27. static bool _hasInitializedSelections = false;
  28. int get selectedFileCount =>
  29. photoGroups.fold(0, (sum, group) => sum + group.selectedCount);
  30. double get selectedFilesSize {
  31. double totalSize = 0;
  32. for (var group in photoGroups) {
  33. for (int i = 0; i < group.images.length; i++) {
  34. if (group.selectedImages[i]) {
  35. totalSize += File(group.images[i]).lengthSync();
  36. }
  37. }
  38. }
  39. return totalSize / 1024; // Convert to KB
  40. }
  41. void toggleImageSelection(String groupTitle, int imageIndex) {
  42. final group = photoGroups.firstWhere((g) => g.title == groupTitle);
  43. group.selectedImages[imageIndex] = !group.selectedImages[imageIndex];
  44. group.isSelected.value = group.selectedImages.every((selected) => selected);
  45. _saveSelections();
  46. }
  47. void toggleGroupSelection(String groupTitle) {
  48. final group = photoGroups.firstWhere((g) => g.title == groupTitle);
  49. final newValue = !group.isSelected.value;
  50. group.toggleSelectAll(newValue);
  51. _saveSelections();
  52. }
  53. void _saveSelections() {
  54. for (var group in photoGroups) {
  55. _savedSelections[group.title] = group.selectedImages.toList();
  56. }
  57. _hasInitializedSelections = true;
  58. }
  59. void _restoreSelections() {
  60. for (var group in photoGroups) {
  61. // 这里假设每次页面加载时,已选择的状态会保存在 `RxList<bool>` 中。
  62. group.isSelected.value =
  63. group.selectedImages.every((selected) => selected);
  64. }
  65. }
  66. @override
  67. void onInit() {
  68. super.onInit();
  69. loadPhotosFromDirectory().then((_) {
  70. if (_hasInitializedSelections) {
  71. _restoreSelections();
  72. }
  73. });
  74. }
  75. Future<void> loadPhotosFromDirectory() async {
  76. try {
  77. final Directory appDir = await getApplicationDocumentsDirectory();
  78. final String photosPath = '${appDir.path}/photos';
  79. final Directory photosDir = Directory(photosPath);
  80. if (!await photosDir.exists()) {
  81. return;
  82. }
  83. final List<Directory> subDirs = await photosDir
  84. .list()
  85. .where((entity) => entity is Directory)
  86. .map((e) => e as Directory)
  87. .toList();
  88. for (final dir in subDirs) {
  89. final List<FileSystemEntity> files = await dir
  90. .list()
  91. .where((entity) =>
  92. entity is File &&
  93. ['.jpg', '.jpeg', '.png']
  94. .contains(p.extension(entity.path).toLowerCase()))
  95. .toList();
  96. if (files.isNotEmpty) {
  97. photoGroups.add(PhotoGroup(
  98. title: 'photo: ${files.length}',
  99. imageCount: files.length,
  100. isSelected: false,
  101. images: files.map((file) => file.path).toList(),
  102. ));
  103. }
  104. }
  105. } catch (e) {
  106. print('Error loading photos: $e');
  107. }
  108. }
  109. }