image_picker_util.dart 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import 'dart:io';
  2. import 'dart:math';
  3. import 'package:clean/data/bean/photos_type.dart';
  4. import 'package:clean/model/asset_group.dart';
  5. import 'package:clean/module/people_photo/photo_group.dart';
  6. import 'package:get/get.dart';
  7. import 'package:photo_manager/photo_manager.dart';
  8. class ImagePickerUtil {
  9. ImagePickerUtil._();
  10. static const RequestType permissionType = RequestType.image;
  11. static final RxInt similarPhotoCount = 0.obs;
  12. // 全局存储不同类型的照片
  13. // 截图图片
  14. static final RxList<AssetEntity> screenshotPhotos = <AssetEntity>[].obs;
  15. // 模糊图片
  16. static final RxList<AssetEntity> blurryPhotos = <AssetEntity>[].obs;
  17. // 相似图片
  18. static final RxList<List<AssetEntity>> similarPhotos =
  19. <List<AssetEntity>>[].obs;
  20. // 地点图片
  21. static final RxMap<String, List<AssetEntity>> locationPhotos =
  22. <String, List<AssetEntity>>{}.obs;
  23. // 人物图片
  24. static final RxList<AssetEntity> peoplePhotos = <AssetEntity>[].obs;
  25. static final RxSet<String> selectedScreenshotPhotosIds = <String>{}.obs;
  26. static final RxSet<String> selectedSimilarPhotosIds = <String>{}.obs;
  27. static final RxSet<String> selectedLocationPhotosIds = <String>{}.obs;
  28. static final RxSet<String> selectedPeoplePhotosIds = <String>{}.obs;
  29. static final RxSet<String> selectedBlurryPhotosIds = <String>{}.obs;
  30. // 添加大小信息的变量
  31. static final Rx<int> screenshotsSize = 0.obs;
  32. static final Rx<int> blurrySize = 0.obs;
  33. static final Rx<int> locationsSize = 0.obs;
  34. static final Rx<int> peopleSize = 0.obs;
  35. static final Rx<int> similarPhotosSize = 0.obs;
  36. // 清除所有照片数据
  37. static void clearAllPhotos() {
  38. similarPhotoCount.value = 0;
  39. screenshotPhotos.clear();
  40. blurryPhotos.clear();
  41. similarPhotos.clear();
  42. locationPhotos.clear();
  43. peoplePhotos.clear();
  44. }
  45. // 更新删除后的照片数据
  46. static Future<void> updatePhotoGroupDate(PhotosType photosType) async {
  47. switch (photosType) {
  48. case PhotosType.screenshots:
  49. // 去除包含在selectedScreenshotPhotosIds中的screenshotPhotos
  50. screenshotPhotos.removeWhere((element) => selectedScreenshotPhotosIds.contains(element.id));
  51. selectedScreenshotPhotosIds.clear();
  52. print(screenshotPhotos);
  53. break;
  54. case PhotosType.similarPhotos:
  55. // 去除包含在selectedSimilarPhotosIds中的similarPhotos
  56. for (var group in similarPhotos) {
  57. group.removeWhere(
  58. (element) => selectedSimilarPhotosIds.contains(element.id));
  59. }
  60. selectedSimilarPhotosIds.clear();
  61. break;
  62. case PhotosType.locationPhotos:
  63. // 去除包含在selectedLocationPhotosIds中的locationPhotos
  64. for (var group in locationPhotos.values) {
  65. group.removeWhere(
  66. (element) => selectedLocationPhotosIds.contains(element.id));
  67. }
  68. selectedLocationPhotosIds.clear();
  69. break;
  70. case PhotosType.peoplePhotos:
  71. // 去除包含在selectedPeoplePhotosIds中的peoplePhotos
  72. peoplePhotos.removeWhere(
  73. (element) => selectedPeoplePhotosIds.contains(element.id));
  74. selectedPeoplePhotosIds.clear();
  75. break;
  76. case PhotosType.blurryPhotos:
  77. // 去除包含在selectedBlurryPhotosIds中的blurryPhotos
  78. blurryPhotos.removeWhere(
  79. (element) => selectedBlurryPhotosIds.contains(element.id));
  80. selectedBlurryPhotosIds.clear();
  81. break;
  82. }
  83. }
  84. // 更新照片数据
  85. static Future<void> updatePhotos(
  86. List<Map<String, dynamic>> photoGroups) async {
  87. clearAllPhotos();
  88. for (var group in photoGroups) {
  89. String type = group['type'] as String;
  90. Map<dynamic, dynamic> groupData = group['group'] as Map<dynamic, dynamic>;
  91. List<dynamic> photos = groupData['photos'] as List<dynamic>;
  92. int totalSize = groupData['totalSize'] as int;
  93. int count = groupData['count'] as int;
  94. switch (type) {
  95. case 'screenshots':
  96. screenshotPhotos.value = await _convertToAssetEntities(photos);
  97. screenshotsSize.value = totalSize;
  98. break;
  99. case 'similar':
  100. similarPhotos.add(await _convertToAssetEntities(photos));
  101. similarPhotosSize.value = totalSize;
  102. similarPhotoCount.value = count;
  103. break;
  104. case 'location':
  105. String location = group['name'] as String;
  106. locationPhotos[location] = await _convertToAssetEntities(photos);
  107. locationsSize.value = totalSize;
  108. break;
  109. case 'people':
  110. peoplePhotos.value = await _convertToAssetEntities(photos);
  111. peopleSize.value = totalSize;
  112. break;
  113. case 'blurry':
  114. blurryPhotos.value = await _convertToAssetEntities(photos);
  115. blurrySize.value = totalSize;
  116. break;
  117. }
  118. }
  119. }
  120. // 将原始照片数据转换为 AssetEntity 列表
  121. static Future<List<AssetEntity>> _convertToAssetEntities(
  122. List<dynamic> photos) async {
  123. List<AssetEntity> entities = [];
  124. for (var photo in photos) {
  125. final entity = await AssetEntity.fromId(photo['id'] as String);
  126. if (entity != null) {
  127. entities.add(entity);
  128. }
  129. }
  130. return entities;
  131. }
  132. //申请权限
  133. static Future<bool> requestPermissionExtend() async {
  134. final PermissionState ps = await PhotoManager.requestPermissionExtend(
  135. requestOption: const PermissionRequestOption(
  136. androidPermission: AndroidPermission(
  137. type: permissionType,
  138. mediaLocation: false,
  139. )));
  140. return ps.hasAccess;
  141. }
  142. //判断是否有权限
  143. static Future<bool> hasPermission() async {
  144. final PermissionState ps = await PhotoManager.getPermissionState(
  145. requestOption: const PermissionRequestOption(
  146. androidPermission: AndroidPermission(
  147. type: permissionType,
  148. mediaLocation: false,
  149. )));
  150. return ps.hasAccess;
  151. }
  152. static String formatFileSize(int bytes, {int decimals = 2}) {
  153. if (bytes <= 0) return '0 B';
  154. const suffixes = ['B', 'KB', 'MB', 'GB', 'TB'];
  155. var i = (log(bytes) / log(1024)).floor();
  156. // 确保不超过数组范围
  157. i = i < suffixes.length ? i : suffixes.length - 1;
  158. // 计算实际大小
  159. final size = bytes / pow(1024, i);
  160. // 格式化数字,处理小数点位数
  161. String sizeStr;
  162. if (size >= 100) {
  163. // 大于100的只保留整数
  164. sizeStr = size.round().toString();
  165. } else {
  166. // 小于100的保留指定小数位
  167. sizeStr = size.toStringAsFixed(decimals);
  168. }
  169. // 移除末尾的0和不必要的小数点
  170. sizeStr = sizeStr.replaceAll(RegExp(r'\.?0+$'), '');
  171. return '$sizeStr ${suffixes[i]}';
  172. }
  173. /// 直接转换为 GB 单位
  174. static String formatToGB(int bytes, {int decimals = 2}) {
  175. if (bytes <= 0) return '0 GB';
  176. final gb = bytes / pow(1024, 3); // 直接转换为 GB
  177. // 格式化数字,处理小数点位数
  178. String sizeStr;
  179. if (gb >= 100) {
  180. // 大于100的只保留整数
  181. sizeStr = gb.round().toString();
  182. } else {
  183. // 小于100的保留指定小数位
  184. sizeStr = gb.toStringAsFixed(decimals);
  185. }
  186. // 移除末尾的0和不必要的小数点
  187. sizeStr = sizeStr.replaceAll(RegExp(r'\.?0+$'), '');
  188. return '$sizeStr GB';
  189. }
  190. /// 格式化存储大小
  191. static String formatSize(double sizeInGB) {
  192. if (sizeInGB < 0.001) {
  193. // 小于 1MB
  194. return '${(sizeInGB * 1024 * 1024).toStringAsFixed(1)} ';
  195. } else if (sizeInGB < 1) {
  196. // 小于 1GB
  197. return '${(sizeInGB * 1024).toStringAsFixed(1)} ';
  198. } else if (sizeInGB < 1024) {
  199. // 小于 1TB
  200. return '${sizeInGB.toStringAsFixed(1)} ';
  201. } else {
  202. // 大于等于 1TB
  203. return '${(sizeInGB / 1024).toStringAsFixed(1)} ';
  204. }
  205. }
  206. }