photo_preview_controller.dart 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. import 'dart:async';
  2. import 'package:clean/base/base_controller.dart';
  3. import 'package:clean/data/bean/photos_type.dart';
  4. import 'package:clean/module/image_picker/image_picker_util.dart';
  5. import 'package:clean/module/locations_photo/locations_single_photo_controller.dart';
  6. import 'package:clean/module/people_photo/people_photo_controller.dart';
  7. import 'package:clean/module/people_photo/photo_group.dart';
  8. import 'package:clean/module/photo_preview/phtoto_selected_preview_view.dart';
  9. import 'package:clean/module/screenshots_blurry/screenshots_controller.dart';
  10. import 'package:clean/module/similar_photo/similar_photo_controller.dart';
  11. import 'package:clean/utils/file_utils.dart';
  12. import 'package:clean/utils/toast_util.dart';
  13. import 'package:flutter/Material.dart';
  14. import 'package:flutter_card_swiper/flutter_card_swiper.dart';
  15. import 'package:get/get.dart';
  16. import 'package:wechat_assets_picker/wechat_assets_picker.dart';
  17. class PhotoPreviewController extends BaseController {
  18. Rx<CardSwiperController> cardSwiperController = CardSwiperController().obs;
  19. final RxList<AssetEntity> photoGroups = <AssetEntity>[].obs;
  20. final RxSet<String> selectedPhotosIds = <String>{}.obs;
  21. final RxBool isSwiperEnd = false.obs;
  22. RxInt groupIndex = 0.obs;
  23. late PhotosType photosType;
  24. late String? currentImageId;
  25. RxDouble selectedFilesSize = 0.0.obs;
  26. RxInt selectedFileCount = 0.obs;
  27. @override
  28. void onInit() {
  29. super.onInit();
  30. isSwiperEnd.value = false;
  31. print('PhotoPreviewController onInit');
  32. _getArgs(); // 获取传递的参数
  33. _initData(); // 初始化数据
  34. WidgetsBinding.instance.addPostFrameCallback((_) {
  35. if (currentImageId != null) {
  36. for (int i = 0; i < photoGroups.length; i++) {
  37. if (photoGroups[i].id == currentImageId) {
  38. print('photoGroups[i].id ${photoGroups[i].id},i $i');
  39. groupIndex.value = i;
  40. cardSwiperController.value.moveTo(i);
  41. break;
  42. }
  43. }
  44. }
  45. });
  46. }
  47. // 获取参数
  48. void _getArgs() {
  49. photosType = parameters?['photosType'];
  50. currentImageId = parameters?['currentImageId'];
  51. }
  52. void _initData() {
  53. photoGroups.clear();
  54. selectedPhotosIds.clear();
  55. switch (photosType) {
  56. case PhotosType.peoplePhotos:
  57. photoGroups.assignAll(ImagePickerUtil.peoplePhotos);
  58. selectedPhotosIds.assignAll(ImagePickerUtil.selectedPeoplePhotosIds);
  59. selectedFileCount.value =
  60. ImagePickerUtil.selectedPeoplePhotosIds.length;
  61. break;
  62. case PhotosType.screenshots:
  63. photoGroups.assignAll(ImagePickerUtil.screenshotPhotos);
  64. selectedPhotosIds
  65. .assignAll(ImagePickerUtil.selectedScreenshotPhotosIds);
  66. selectedFileCount.value =
  67. ImagePickerUtil.selectedScreenshotPhotosIds.length;
  68. break;
  69. case PhotosType.similarPhotos:
  70. for (var group in ImagePickerUtil.similarPhotos) {
  71. photoGroups.addAll(group);
  72. }
  73. selectedPhotosIds.assignAll(ImagePickerUtil.selectedSimilarPhotosIds);
  74. selectedFileCount.value =
  75. ImagePickerUtil.selectedSimilarPhotosIds.length;
  76. break;
  77. case PhotosType.locationPhotos:
  78. for (var group in ImagePickerUtil.locationPhotos.values) {
  79. photoGroups.addAll(group);
  80. }
  81. selectedPhotosIds.assignAll(ImagePickerUtil.selectedLocationPhotosIds);
  82. selectedFileCount.value =
  83. ImagePickerUtil.selectedLocationPhotosIds.length;
  84. break;
  85. case PhotosType.blurryPhotos:
  86. photoGroups.assignAll(ImagePickerUtil.blurryPhotos);
  87. selectedPhotosIds.assignAll(ImagePickerUtil.selectedBlurryPhotosIds);
  88. selectedFileCount.value =
  89. ImagePickerUtil.selectedBlurryPhotosIds.length;
  90. break;
  91. }
  92. updateSelectedFilesSize();
  93. }
  94. void restoreSelections() async {
  95. photoGroups.removeWhere((element) => selectedPhotosIds.contains(element.id));
  96. selectedPhotosIds.clear();
  97. if (photoGroups.isNotEmpty) {
  98. WidgetsBinding.instance.addPostFrameCallback((_) {
  99. groupIndex.value = 0;
  100. cardSwiperController.value.moveTo(0);
  101. });
  102. }
  103. updateSelectedFilesSize();
  104. selectedFileCount.value = selectedPhotosIds.length;
  105. }
  106. Future<void> updateSelectedFilesSize() async {
  107. double totalSize = 0;
  108. // 通过selectedPhotosIds获取选中的图片,然后计算大小
  109. for (var id in selectedPhotosIds) {
  110. final entity = await AssetEntity.fromId(id);
  111. if (entity != null) {
  112. final file = await entity.file;
  113. if (file != null) {
  114. totalSize += await file.length();
  115. }
  116. }
  117. }
  118. selectedFilesSize.value = totalSize / 1024; // Convert to KB
  119. }
  120. void recoverSelectPhoto() {
  121. cardSwiperController.value.undo();
  122. }
  123. void clickSelect() {
  124. cardSwiperController.value.swipe(CardSwiperDirection.left);
  125. }
  126. @override
  127. void onClose() {
  128. super.onClose();
  129. // 清理操作,释放资源
  130. cardSwiperController.value.dispose();
  131. }
  132. void clickBack() {
  133. _saveSelectedPhotos(photosType);
  134. Get.back();
  135. }
  136. // // 保存选择的图片ID列表
  137. void _saveSelectedPhotos(PhotosType type) {
  138. switch (type) {
  139. case PhotosType.peoplePhotos:
  140. ImagePickerUtil.selectedPeoplePhotosIds.assignAll(selectedPhotosIds);
  141. PeoplePhotoController controller = Get.find<PeoplePhotoController>();
  142. controller.restoreSelections();
  143. break;
  144. case PhotosType.screenshots:
  145. ImagePickerUtil.selectedScreenshotPhotosIds
  146. .assignAll(selectedPhotosIds);
  147. ScreenShotsController controller = Get.find<ScreenShotsController>();
  148. controller.restoreSelections();
  149. break;
  150. case PhotosType.similarPhotos:
  151. ImagePickerUtil.selectedSimilarPhotosIds.assignAll(selectedPhotosIds);
  152. SimilarPhotoController controller = Get.find<SimilarPhotoController>();
  153. controller.restoreSelections();
  154. break;
  155. case PhotosType.locationPhotos:
  156. ImagePickerUtil.selectedLocationPhotosIds.assignAll(selectedPhotosIds);
  157. LocationsSinglePhotoController controller =
  158. Get.find<LocationsSinglePhotoController>();
  159. controller.restoreSelections();
  160. break;
  161. case PhotosType.blurryPhotos:
  162. ImagePickerUtil.selectedBlurryPhotosIds.assignAll(selectedPhotosIds);
  163. ScreenShotsController controller = Get.find<ScreenShotsController>();
  164. controller.restoreSelections();
  165. break;
  166. }
  167. }
  168. void clickUnselect() {
  169. print("clickUnselect");
  170. cardSwiperController.value.swipe(CardSwiperDirection.right);
  171. }
  172. FutureOr<bool> onSwipe(
  173. int previousIndex,
  174. int? currentIndex,
  175. CardSwiperDirection direction,
  176. ) {
  177. print(
  178. 'The card $previousIndex was swiped to the ${direction.name}. Now the card $currentIndex is on top',
  179. );
  180. if (currentIndex != null) {
  181. groupIndex.value = currentIndex;
  182. }
  183. // 如果direction是left,
  184. if (direction == CardSwiperDirection.left) {
  185. // 先看看图片id是不是在selectedPhotosIds里面,如果在,不处理,如果不在,添加到selectedPhotosIds里面
  186. if (!selectedPhotosIds.contains(photoGroups[previousIndex].id)) {
  187. print(
  188. 'add photoGroups[groupIndex.value].id ${photoGroups[previousIndex].id}');
  189. selectedPhotosIds.add(photoGroups[previousIndex].id);
  190. }
  191. } else if (direction == CardSwiperDirection.right) {
  192. // 先看看图片id是不是在selectedPhotosIds里面,如果在,在selectedPhotosIds移除,不处理,如果不在,不处理
  193. if (selectedPhotosIds.contains(photoGroups[previousIndex].id)) {
  194. print(
  195. 'remove photoGroups[groupIndex.value].id ${photoGroups[previousIndex].id}');
  196. selectedPhotosIds.remove(photoGroups[previousIndex].id);
  197. }
  198. }
  199. selectedFileCount.value = selectedPhotosIds.length;
  200. updateSelectedFilesSize();
  201. return true;
  202. }
  203. bool onSwiperUndo(
  204. int? previousIndex,
  205. int currentIndex,
  206. CardSwiperDirection direction,
  207. ) {
  208. print(
  209. 'The card $currentIndex was swiped back to the ${direction.name}. Now the card $previousIndex is on top');
  210. groupIndex.value = currentIndex;
  211. // 撤销之前左滑的操作
  212. if (direction == CardSwiperDirection.left) {
  213. print(
  214. 'photoGroups[groupIndex.value].id ${photoGroups[groupIndex.value].id}');
  215. if (selectedPhotosIds.contains(photoGroups[groupIndex.value].id)) {
  216. selectedPhotosIds.remove(photoGroups[groupIndex.value].id);
  217. }
  218. }
  219. selectedFileCount.value = selectedPhotosIds.length;
  220. updateSelectedFilesSize();
  221. return true;
  222. }
  223. onSwiperEnd() {
  224. isSwiperEnd.value = true;
  225. print('onSwiperEnd');
  226. PhotoSelectedPreviewPage.start(photosType, selectedPhotosIds);
  227. }
  228. clickDelete() async {
  229. print('clickDelete');
  230. switch (photosType) {
  231. case PhotosType.peoplePhotos:
  232. ImagePickerUtil.selectedPeoplePhotosIds.assignAll(selectedPhotosIds);
  233. break;
  234. case PhotosType.screenshots:
  235. ImagePickerUtil.selectedScreenshotPhotosIds
  236. .assignAll(selectedPhotosIds);
  237. break;
  238. case PhotosType.similarPhotos:
  239. ImagePickerUtil.selectedSimilarPhotosIds.assignAll(selectedPhotosIds);
  240. break;
  241. case PhotosType.locationPhotos:
  242. ImagePickerUtil.selectedLocationPhotosIds.assignAll(selectedPhotosIds);
  243. break;
  244. case PhotosType.blurryPhotos:
  245. ImagePickerUtil.selectedBlurryPhotosIds.assignAll(selectedPhotosIds);
  246. break;
  247. }
  248. if (selectedPhotosIds.isNotEmpty) {
  249. // 获取要删除的资产
  250. final assetsToDelete = photoGroups
  251. .where(
  252. (asset) => selectedPhotosIds.contains(asset.id),
  253. )
  254. .toList();
  255. // 调用方法会返回被删除的资源,如果全部失败会返回空列表。
  256. final List<String> result = await PhotoManager.editor.deleteWithIds(
  257. assetsToDelete.map((e) => e.id).toList(),
  258. );
  259. print('PhotoPreviewController result $result');
  260. // 比较result和selectedPhotosIds,如果result和selectedPhotosIds相等,说明删除成功,走下面的逻辑
  261. // 如果不相等,说明有删除失败的,走else逻辑
  262. if (result.length == selectedPhotosIds.length) {
  263. switch (photosType) {
  264. case PhotosType.peoplePhotos:
  265. ImagePickerUtil.updatePhotoGroupDate(photosType,ImagePickerUtil.selectedPeoplePhotosIds);
  266. break;
  267. case PhotosType.screenshots:
  268. ImagePickerUtil.updatePhotoGroupDate(photosType,ImagePickerUtil.selectedScreenshotPhotosIds);
  269. break;
  270. case PhotosType.similarPhotos:
  271. ImagePickerUtil.updatePhotoGroupDate(photosType,ImagePickerUtil.selectedSimilarPhotosIds);
  272. break;
  273. case PhotosType.locationPhotos:
  274. ImagePickerUtil.updatePhotoGroupDate(photosType,ImagePickerUtil.selectedLocationPhotosIds);
  275. break;
  276. case PhotosType.blurryPhotos:
  277. ImagePickerUtil.updatePhotoGroupDate(photosType,ImagePickerUtil.selectedBlurryPhotosIds);
  278. break;
  279. }
  280. restoreSelections();
  281. } else {
  282. // 删除失败
  283. ToastUtil.show("Delete failed");
  284. }
  285. }
  286. }
  287. }