|
|
@@ -1,6 +1,10 @@
|
|
|
+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';
|
|
|
@@ -31,186 +35,629 @@ class PhotoScanHandler {
|
|
|
// 相似照片
|
|
|
static RxList<AssetEntity> similarPhotos = <AssetEntity>[].obs;
|
|
|
|
|
|
- /// 执行所有的照片处理操作
|
|
|
- static Future<void> 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;
|
|
|
+ // 添加一个标志来跟踪当前扫描状态
|
|
|
+ bool _isScanningCancelled = false;
|
|
|
+
|
|
|
+ List<StreamSubscription> _scanningTasks = [];
|
|
|
+
|
|
|
+ static Rx<double> totalSpace = 0.0.obs;
|
|
|
+ static Rx<double> usedSpace = 0.0.obs;
|
|
|
+ static Rx<double> photoSpace = 0.0.obs;
|
|
|
+ static Rx<double> freeSpace = 0.0.obs;
|
|
|
+
|
|
|
+ static Rx<String> totalSpaceStr = "0.0 GB".obs;
|
|
|
+ static Rx<String> usedSpaceStr = "0.0 GB".obs;
|
|
|
+ static Rx<String> photoSpaceStr = "0.0 GB".obs;
|
|
|
+ static Rx<String> 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<PieData> 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("已取消当前扫描任务");
|
|
|
}
|
|
|
|
|
|
- /// 截图照片
|
|
|
- static Future<bool> handleScreenPhotos() async {
|
|
|
+// 重新开始扫描
|
|
|
+ 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<void> startScanningProcess() async {
|
|
|
+ // 确保在开始新扫描前取消标志被重置
|
|
|
+ _isScanningCancelled = false;
|
|
|
+
|
|
|
+ // 清空之前的任务
|
|
|
+ _scanningTasks.clear();
|
|
|
+
|
|
|
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;
|
|
|
- }
|
|
|
+ // 按顺序执行扫描任务
|
|
|
+ print('开始顺序扫描照片');
|
|
|
+
|
|
|
+ // 1. 先扫描截图照片
|
|
|
+ if (!_isScanningCancelled) {
|
|
|
+ var screenTask = _handleScreenPhotosWithCancellation();
|
|
|
+ _scanningTasks.add(screenTask);
|
|
|
+ // 等待截图扫描完成
|
|
|
+ await Future.delayed(Duration(milliseconds: 500));
|
|
|
}
|
|
|
- } catch (e, stackTrace) {
|
|
|
- print('获取截图失败: $e\n$stackTrace');
|
|
|
+
|
|
|
+ // 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');
|
|
|
}
|
|
|
- isScreenShotScanned.value = true;
|
|
|
- return true;
|
|
|
}
|
|
|
|
|
|
- /// 模糊照片
|
|
|
- static Future<bool> handleBlurryPhotos() async {
|
|
|
+ Future<void> 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 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;
|
|
|
+ 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<void> 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;
|
|
|
}
|
|
|
- return true;
|
|
|
}
|
|
|
- } catch (e, stackTrace) {
|
|
|
- print('获取模糊失败: $e\n$stackTrace');
|
|
|
- }
|
|
|
- isBlurryScanned.value = true;
|
|
|
- return true;
|
|
|
}
|
|
|
|
|
|
- /// 人物照片
|
|
|
- static Future<bool> 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;
|
|
|
+ // 可取消的截图照片扫描
|
|
|
+ StreamSubscription _handleScreenPhotosWithCancellation() {
|
|
|
+ var controller = StreamController<bool>();
|
|
|
+
|
|
|
+ Future<void> 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);
|
|
|
}
|
|
|
- return true;
|
|
|
}
|
|
|
- } catch (e, stackTrace) {
|
|
|
- print('获取人物失败: $e\n$stackTrace');
|
|
|
+
|
|
|
+ task();
|
|
|
+
|
|
|
+ return controller.stream.listen((success) {
|
|
|
+ controller.close();
|
|
|
+ });
|
|
|
}
|
|
|
- isPeopleScanned.value = true;
|
|
|
- return true;
|
|
|
- }
|
|
|
|
|
|
- /// 相似照片
|
|
|
- static Future<bool> 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;
|
|
|
- }
|
|
|
+// 可取消的模糊照片扫描
|
|
|
+ StreamSubscription _handleBlurryPhotosWithCancellation() {
|
|
|
+ var controller = StreamController<bool>();
|
|
|
+
|
|
|
+ Future<void> 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);
|
|
|
}
|
|
|
- return true;
|
|
|
}
|
|
|
- } catch (e, stackTrace) {
|
|
|
- print('获取相似失败: $e\n$stackTrace');
|
|
|
+
|
|
|
+ task();
|
|
|
+
|
|
|
+ return controller.stream.listen((success) {
|
|
|
+ controller.close();
|
|
|
+ });
|
|
|
}
|
|
|
- isSimilarScanned.value = true;
|
|
|
- return true;
|
|
|
- }
|
|
|
|
|
|
- /// Android平台处理方式
|
|
|
- static Future<void> handleAndroidPhotos() async {
|
|
|
- final List<AssetEntity> result = await ImagePickerUtil.loadAssets();
|
|
|
- ImagePickerUtil.peoplePhotos.value = result ?? [];
|
|
|
- ImagePickerUtil.locationPhotos['location'] = result ?? [];
|
|
|
- ImagePickerUtil.screenshotPhotos.value = result ?? [];
|
|
|
- const int batchSize = 10;
|
|
|
- for (int i = 0; i < result.length; i += batchSize) {
|
|
|
- int end = (i + batchSize < result.length) ? i + batchSize : result.length;
|
|
|
- List<AssetEntity> batch = result.sublist(i, end);
|
|
|
- ImagePickerUtil.similarPhotos.add(batch);
|
|
|
+// 可取消的人物照片扫描
|
|
|
+ StreamSubscription _handlePeoplePhotosWithCancellation() {
|
|
|
+ var controller = StreamController<bool>();
|
|
|
+
|
|
|
+ Future<void> 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();
|
|
|
+ });
|
|
|
}
|
|
|
- ImagePickerUtil.blurryPhotos.value = result ?? [];
|
|
|
|
|
|
- print("handleAndroidPhotos $result");
|
|
|
- print(
|
|
|
- "ImagePickerUtil.peoplePhotos.value ${ImagePickerUtil.peoplePhotos.length}");
|
|
|
+// 可取消的相似照片扫描
|
|
|
+ StreamSubscription _handleSimilarPhotosWithCancellation() {
|
|
|
+ var controller = StreamController<bool>();
|
|
|
|
|
|
- isSimilarScanned.value = true;
|
|
|
- isPeopleScanned.value = true;
|
|
|
- isBlurryScanned.value = true;
|
|
|
- isScreenShotScanned.value = true;
|
|
|
+ Future<void> task() async {
|
|
|
+ if (_isScanningCancelled) {
|
|
|
+ controller.add(false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- 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;
|
|
|
+ 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();
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- peoplePhotos.clear();
|
|
|
- if (ImagePickerUtil.peoplePhotos.isNotEmpty) {
|
|
|
- for (var personPhotos in ImagePickerUtil.peoplePhotos) {
|
|
|
- peoplePhotos.add(personPhotos);
|
|
|
- if (peoplePhotos.length == 2) {
|
|
|
- break;
|
|
|
+ /// 截图照片
|
|
|
+ Future<bool> 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<bool> 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;
|
|
|
}
|
|
|
|
|
|
- if (ImagePickerUtil.blurryPhotos.isNotEmpty) {
|
|
|
- var asset = ImagePickerUtil.blurryPhotos.first;
|
|
|
- blurryPhoto.value = asset;
|
|
|
+ /// 人物照片
|
|
|
+ Future<bool> 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<bool> 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;
|
|
|
}
|
|
|
|
|
|
- if (ImagePickerUtil.screenshotPhotos.isNotEmpty) {
|
|
|
- var asset = ImagePickerUtil.screenshotPhotos.first;
|
|
|
- screenshotPhoto.value = asset;
|
|
|
+ /// Android平台处理方式
|
|
|
+ Future<void> handleAndroidPhotos() async {
|
|
|
+ final List<AssetEntity> 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;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
-}
|