image_picker_util.dart 5.6 KB

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