import 'dart:async'; import 'dart:io'; import 'package:classify_photo/classify_photo.dart'; import 'package:clean/widget/multi_segment_circle_indicator.dart'; import 'package:disk_space/disk_space.dart'; import 'package:flutter/Material.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:wechat_assets_picker/wechat_assets_picker.dart'; import '../../module/image_picker/image_picker_util.dart'; import '../utils/toast_util.dart'; class PhotoScanHandler { static final _photoClassify = ClassifyPhoto(); static RxBool isSimilarScanned = false.obs; static RxBool isPeopleScanned = false.obs; static RxBool isScreenShotScanned = false.obs; static RxBool isBlurryScanned = false.obs; // 人物图片 static RxList peoplePhotos = [].obs; // 地点图片 static Rx locationPhoto = Rx(null); // 截图照片 static Rx screenshotPhoto = Rx(null); // 模糊照片 static Rx blurryPhoto = Rx(null); // 相似照片 static RxList similarPhotos = [].obs; // 添加一个标志来跟踪当前扫描状态 bool _isScanningCancelled = false; List _scanningTasks = []; static Rx totalSpace = 0.0.obs; static Rx usedSpace = 0.0.obs; static Rx photoSpace = 0.0.obs; static Rx freeSpace = 0.0.obs; static Rx totalSpaceStr = "0.0 GB".obs; static Rx usedSpaceStr = "0.0 GB".obs; static Rx photoSpaceStr = "0.0 GB".obs; static Rx freeSpaceStr = "0.0 GB".obs; // 计算已用存储百分比 static double get usedSpacePercentage => (usedSpace.value / totalSpace.value) * 100; // 计算照片占用存储百分比 static double get photoSpacePercentage => (photoSpace.value / totalSpace.value) * 100; // 计算可用存储百分比 static double get freeSpacePercentage => (freeSpace.value / totalSpace.value) * 100; static List get pieDataList => [ PieData("PhotoSpace", photoSpacePercentage, Colors.blue), PieData("OtherUsed", usedSpacePercentage - photoSpacePercentage, Colors.red), PieData("totalSpace", totalSpace.value, Colors.grey.withOpacity(0.1)), ]; // 存储是否扫描完成 static RxBool isStorageScanned = false.obs; // 监听照片库变化 void _listenToPhotoLibraryChanges() { PhotoManager.addChangeCallback((change) { print("照片库发生变化: $change"); // 取消当前正在进行的扫描 _cancelCurrentScan(); // 延迟一小段时间后重新开始扫描 Future.delayed(Duration(milliseconds: 500), () { _restartScan(); }); }); // 开始监听 PhotoManager.startChangeNotify(); } // 取消当前扫描 void _cancelCurrentScan() { _isScanningCancelled = true; // 取消所有正在进行的异步任务 for (var subscription in _scanningTasks) { subscription.cancel(); } _scanningTasks.clear(); print("已取消当前扫描任务"); } // 重新开始扫描 void _restartScan() { _isScanningCancelled = false; isSimilarScanned.value = false; isPeopleScanned.value = false; isBlurryScanned.value = false; isScreenShotScanned.value = false; // 清除之前的结果 similarPhotos.clear(); peoplePhotos.clear(); locationPhoto.value = null; screenshotPhoto.value = null; blurryPhoto.value = null; print("开始重新扫描照片"); // 重新开始扫描流程 startScanningProcess(); } // 开始扫描过程 Future startScanningProcess() async { // 确保在开始新扫描前取消标志被重置 _isScanningCancelled = false; // 清空之前的任务 _scanningTasks.clear(); try { // 按顺序执行扫描任务 print('开始顺序扫描照片'); // 1. 先扫描截图照片 if (!_isScanningCancelled) { var screenTask = _handleScreenPhotosWithCancellation(); _scanningTasks.add(screenTask); // 等待截图扫描完成 await Future.delayed(Duration(milliseconds: 500)); } // 2. 再扫描模糊照片 if (!_isScanningCancelled) { var blurryTask = _handleBlurryPhotosWithCancellation(); _scanningTasks.add(blurryTask); // 等待模糊照片扫描完成 await Future.delayed(Duration(milliseconds: 500)); } // 3. 然后扫描人物照片 if (!_isScanningCancelled) { var peopleTask = _handlePeoplePhotosWithCancellation(); _scanningTasks.add(peopleTask); // 等待人物照片扫描完成 await Future.delayed(Duration(milliseconds: 500)); } // 4. 最后扫描相似照片 if (!_isScanningCancelled) { var similarTask = _handleSimilarPhotosWithCancellation(); _scanningTasks.add(similarTask); } print('所有扫描任务已启动'); } catch (e) { print('扫描过程中出错: $e'); } } Future getStorageInfo() async { if (Platform.isAndroid) { // 延迟3秒 Future.delayed(const Duration(seconds: 3), () { isStorageScanned.value = true; totalSpace.value = 200.0; usedSpace.value = 50.0; photoSpace.value = 30.0; freeSpace.value = 150.0; }); } final totalSpaceGB = (await DiskSpace.getTotalDiskSpace ?? 0) / 1000; final freeSpaceGB = (await DiskSpace.getFreeDiskSpace ?? 0) / 1024; final usedSpaceGB = ((await DiskSpace.getTotalDiskSpace ?? 0) - (await DiskSpace.getFreeDiskSpace ?? 0)) / 1024; totalSpaceStr.value = ImagePickerUtil.formatFileSize( (await DiskSpace.getTotalDiskSpace ?? 0).round(), decimals: 1); freeSpaceStr.value = ImagePickerUtil.formatFileSize( (await DiskSpace.getFreeDiskSpace ?? 0).round(), decimals: 1); usedSpaceStr.value = ImagePickerUtil.formatFileSize( ((await DiskSpace.getTotalDiskSpace ?? 0) - (await DiskSpace.getFreeDiskSpace ?? 0)).round(), decimals: 1); totalSpace.value = totalSpaceGB.round().toDouble(); freeSpace.value = freeSpaceGB; usedSpace.value = usedSpaceGB; final classifyPhoto = ClassifyPhoto(); try { final storageInfo = await classifyPhoto.getStorageInfo(); // 转换为 GB final totalSpaceGB = storageInfo['totalSpace']! / (1000 * 1000 * 1000); final freeSpaceGB = storageInfo['freeSpace']! / (1024 * 1024 * 1024); final usedSpaceGB = storageInfo['usedSpace']! / (1024 * 1024 * 1024); final photoSpaceGB = storageInfo['photoSpace']! / (1024 * 1024 * 1024); totalSpaceStr.value = ImagePickerUtil.formatFileSize( storageInfo['totalSpace']!, decimals: 1); freeSpaceStr.value = ImagePickerUtil.formatFileSize( storageInfo['freeSpace']!, decimals: 1); usedSpaceStr.value = ImagePickerUtil.formatFileSize( storageInfo['usedSpace']!, decimals: 1); photoSpaceStr.value = ImagePickerUtil.formatFileSize( storageInfo['photoSpace']!, decimals: 1); totalSpace.value = totalSpaceGB.round().toDouble(); freeSpace.value = freeSpaceGB; usedSpace.value = usedSpaceGB; photoSpace.value = photoSpaceGB; print('总容量: $totalSpaceStr'); print('可用空间: $freeSpaceStr'); print('已用空间: $usedSpaceStr'); print('照片占用: $photoSpaceStr'); isStorageScanned.value = true; } catch (e) { print('获取存储信息失败: $e'); } } /// 执行所有的照片处理操作 Future handleAllPhotos() async { // var request = Platform.isIOS // ? await Permission.photos.request() // : await Permission.storage.request(); // // if (request.isGranted) { // PhotoManager.clearFileCache(); // await handleScreenPhotos(); // await handleBlurryPhotos(); // await handlePeoplePhotos(); // await handleSimilarPhotos(); // if (Platform.isAndroid) { // await handleAndroidPhotos(); // } // } else if (request.isPermanentlyDenied) { // ToastUtil.show("Please enable the album permission"); // openAppSettings(); // } else { // ToastUtil.show("Please enable the album permission"); // // isSimilarScanned.value = false; // isPeopleScanned.value = false; // isBlurryScanned.value = false; // isScreenShotScanned.value = false; // } var currentStatus = await Permission.photos.status; if (currentStatus.isGranted) { // 已有完全权限,直接扫描 PhotoManager.clearFileCache(); // _listenToPhotoLibraryChanges(); // 添加监听 await handleScreenPhotos(); await handleBlurryPhotos(); await handlePeoplePhotos(); await handleSimilarPhotos(); } else if (currentStatus.isLimited) { // 已有有限权限,显示自定义弹窗 PhotoManager.clearFileCache(); await handleScreenPhotos(); await handleBlurryPhotos(); await handlePeoplePhotos(); await handleSimilarPhotos(); } else { // 未授权,请求权限 var result = await Permission.photos.request(); if (result.isGranted || result.isLimited) { PhotoManager.clearFileCache(); getStorageInfo(); await handleScreenPhotos(); await handleBlurryPhotos(); await handlePeoplePhotos(); await handleSimilarPhotos(); } else { isSimilarScanned.value = true; isPeopleScanned.value = true; isBlurryScanned.value = true; isScreenShotScanned.value = true; } } } // 可取消的截图照片扫描 StreamSubscription _handleScreenPhotosWithCancellation() { var controller = StreamController(); Future task() async { if (_isScanningCancelled) { controller.add(false); return; } try { print('开始获取截图照片'); final photoClassify = ClassifyPhoto(); final photos = await photoClassify.getScreenshots(); if (_isScanningCancelled) { controller.add(false); return; } print('获取截图照片完成: ${photos?.length ?? 0} 组照片'); isScreenShotScanned.value = true; if (photos != null) { await ImagePickerUtil.updatePhotos(photos); if (ImagePickerUtil.screenshotPhotos.isNotEmpty) { var asset = ImagePickerUtil.screenshotPhotos.first; screenshotPhoto.value = asset; } } controller.add(true); } catch (e) { print('获取截图照片失败: $e'); controller.add(false); } } task(); return controller.stream.listen((success) { controller.close(); }); } // 可取消的模糊照片扫描 StreamSubscription _handleBlurryPhotosWithCancellation() { var controller = StreamController(); Future task() async { if (_isScanningCancelled) { controller.add(false); return; } try { print('开始获取模糊照片'); final photoClassify = ClassifyPhoto(); final photos = await photoClassify.getBlurryPhotos(); if (_isScanningCancelled) { controller.add(false); return; } print('获取模糊照片完成: ${photos?.length ?? 0} 组照片'); isBlurryScanned.value = true; if (photos != null) { await ImagePickerUtil.updatePhotos(photos); if (ImagePickerUtil.blurryPhotos.isNotEmpty) { var asset = ImagePickerUtil.blurryPhotos.first; blurryPhoto.value = asset; } } controller.add(true); } catch (e) { print('获取模糊照片失败: $e'); controller.add(false); } } task(); return controller.stream.listen((success) { controller.close(); }); } // 可取消的人物照片扫描 StreamSubscription _handlePeoplePhotosWithCancellation() { var controller = StreamController(); Future task() async { if (_isScanningCancelled) { controller.add(false); return; } try { print('开始获取人物照片'); final photoClassify = ClassifyPhoto(); final photos = await photoClassify.getPeoplePhotos(); if (_isScanningCancelled) { controller.add(false); return; } print('获取人物照片完成: ${photos?.length ?? 0} 组照片'); isPeopleScanned.value = true; if (photos != null) { await ImagePickerUtil.updatePhotos(photos); // 处理人物照片 peoplePhotos.clear(); if (ImagePickerUtil.peoplePhotos.isNotEmpty) { for (var personPhotos in ImagePickerUtil.peoplePhotos) { if (_isScanningCancelled) break; peoplePhotos.add(personPhotos); if (peoplePhotos.length == 2) { break; } } } } controller.add(true); } catch (e) { print('获取人物照片失败: $e'); controller.add(false); } } task(); return controller.stream.listen((success) { controller.close(); }); } // 可取消的相似照片扫描 StreamSubscription _handleSimilarPhotosWithCancellation() { var controller = StreamController(); Future task() async { if (_isScanningCancelled) { controller.add(false); return; } try { print('开始获取相似照片'); final photoClassify = ClassifyPhoto(); final photos = await photoClassify.getSimilarPhotos(); if (_isScanningCancelled) { controller.add(false); return; } print('获取相似照片完成: ${photos?.length ?? 0} 组照片'); isSimilarScanned.value = true; if (photos != null) { await ImagePickerUtil.updatePhotos(photos); similarPhotos.clear(); if (ImagePickerUtil.similarPhotos.isNotEmpty) { for (var group in ImagePickerUtil.similarPhotos) { if (_isScanningCancelled) break; for (var asset in group) { similarPhotos.add(asset); if (similarPhotos.length == 4) { break; } } if (similarPhotos.length == 4) { break; } } } } controller.add(true); } catch (e) { print('获取相似照片失败: $e'); controller.add(false); } } task(); return controller.stream.listen((success) { controller.close(); }); } /// 截图照片 Future handleScreenPhotos() async { try { final photos = await _photoClassify.getScreenshots(); print('获取截图照片完成: ${photos?.length ?? 0} 组照片'); isScreenShotScanned.value = true; if (photos != null) { await ImagePickerUtil.updatePhotos(photos); if (ImagePickerUtil.screenshotPhotos.isNotEmpty) { var asset = ImagePickerUtil.screenshotPhotos.first; screenshotPhoto.value = asset; } } } catch (e, stackTrace) { print('获取截图失败: $e\n$stackTrace'); } isScreenShotScanned.value = true; return true; } /// 模糊照片 Future handleBlurryPhotos() async { try { final photos = await _photoClassify.getBlurryPhotos(); print('获取模糊照片完成: ${photos?.length ?? 0} 组照片'); isBlurryScanned.value = true; if (photos != null) { await ImagePickerUtil.updatePhotos(photos); if (ImagePickerUtil.blurryPhotos.isNotEmpty) { var asset = ImagePickerUtil.blurryPhotos.first; blurryPhoto.value = asset; } return true; } } catch (e, stackTrace) { print('获取模糊失败: $e\n$stackTrace'); } isBlurryScanned.value = true; return true; } /// 人物照片 Future handlePeoplePhotos() async { try { final photos = await _photoClassify.getPeoplePhotos(); print('获取人物照片完成: ${photos?.length ?? 0} 组照片'); isPeopleScanned.value = true; if (photos != null) { await ImagePickerUtil.updatePhotos(photos); // 处理人物照片 peoplePhotos.clear(); if (ImagePickerUtil.peoplePhotos.isNotEmpty) { for (var personPhotos in ImagePickerUtil.peoplePhotos) { peoplePhotos.add(personPhotos); if (peoplePhotos.length == 2) { break; } } } return true; } } catch (e, stackTrace) { print('获取人物失败: $e\n$stackTrace'); } isPeopleScanned.value = true; return true; } /// 相似照片 Future handleSimilarPhotos() async { try { print('开始获取相似照片'); final photos = await _photoClassify.getSimilarPhotos(); print('获取相似照片完成: ${photos?.length ?? 0} 组照片'); isSimilarScanned.value = true; if (photos != null) { await ImagePickerUtil.updatePhotos(photos); similarPhotos.clear(); if (ImagePickerUtil.similarPhotos.isNotEmpty) { for (var group in ImagePickerUtil.similarPhotos) { for (var asset in group) { similarPhotos.add(asset); if (similarPhotos.length == 4) { break; } } } } return true; } } catch (e, stackTrace) { print('获取相似失败: $e\n$stackTrace'); } isSimilarScanned.value = true; return true; } /// Android平台处理方式 Future handleAndroidPhotos() async { final List result = await ImagePickerUtil.loadAssets(); ImagePickerUtil.peoplePhotos.value = result ?? []; ImagePickerUtil.locationPhotos['location'] = result ?? []; ImagePickerUtil.screenshotPhotos.value = result ?? []; ImagePickerUtil.similarPhotos.add(result ?? []); ImagePickerUtil.blurryPhotos.value = result ?? []; print("handleAndroidPhotos $result"); print( "ImagePickerUtil.peoplePhotos.value ${ImagePickerUtil.peoplePhotos .length}"); isSimilarScanned.value = true; isPeopleScanned.value = true; isBlurryScanned.value = true; isScreenShotScanned.value = true; similarPhotos.clear(); if (ImagePickerUtil.similarPhotos.isNotEmpty) { for (var group in ImagePickerUtil.similarPhotos) { print( " ImagePickerUtil.similarPhotos ${ImagePickerUtil.similarPhotos .length}"); for (var asset in group) { similarPhotos.add(asset); if (similarPhotos.length == 4) { break; } } } } peoplePhotos.clear(); if (ImagePickerUtil.peoplePhotos.isNotEmpty) { for (var personPhotos in ImagePickerUtil.peoplePhotos) { peoplePhotos.add(personPhotos); if (peoplePhotos.length == 2) { break; } } } if (ImagePickerUtil.blurryPhotos.isNotEmpty) { var asset = ImagePickerUtil.blurryPhotos.first; blurryPhoto.value = asset; } if (ImagePickerUtil.screenshotPhotos.isNotEmpty) { var asset = ImagePickerUtil.screenshotPhotos.first; screenshotPhoto.value = asset; } } }