file_sync_util.dart 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import 'dart:convert';
  2. import 'dart:math';
  3. import 'package:collection/collection.dart';
  4. import 'package:computer/computer.dart';
  5. import 'package:logging/logging.dart';
  6. import 'package:photo_manager/photo_manager.dart';
  7. import 'package:photos/models/file.dart';
  8. final _logger = Logger("FileSyncUtil");
  9. Future<List<File>> getDeviceFiles(
  10. int fromTime, int toTime, Computer computer) async {
  11. final pathEntities = await _getGalleryList(fromTime, toTime);
  12. List<File> files = [];
  13. AssetPathEntity recents;
  14. for (AssetPathEntity pathEntity in pathEntities) {
  15. if (pathEntity.name == "Recent" || pathEntity.name == "Recents") {
  16. recents = pathEntity;
  17. } else {
  18. files = await _computeFiles(pathEntity, fromTime, files, computer);
  19. }
  20. }
  21. if (recents != null) {
  22. files = await _computeFiles(recents, fromTime, files, computer);
  23. }
  24. files.sort(
  25. (first, second) => first.creationTime.compareTo(second.creationTime));
  26. return files;
  27. }
  28. Future<List<LocalAsset>> getAllLocalAssets() async {
  29. final filterOptionGroup = FilterOptionGroup();
  30. final assetPaths = await PhotoManager.getAssetPathList(
  31. hasAll: true,
  32. type: RequestType.common,
  33. filterOption: filterOptionGroup,
  34. );
  35. final List<LocalAsset> assets = [];
  36. for (final assetPath in assetPaths) {
  37. for (final asset in await assetPath.assetList) {
  38. assets.add(LocalAsset(asset.id, assetPath.name));
  39. }
  40. }
  41. return assets;
  42. }
  43. Future<List<File>> convertToFiles(
  44. List<LocalAsset> assets, Computer computer) async {
  45. final List<LocalAsset> recents = [];
  46. final List<LocalAssetEntity> entities = [];
  47. for (final asset in assets) {
  48. if (asset.path == "Recent" || asset.path == "Recents") {
  49. recents.add(asset);
  50. } else {
  51. entities.add(
  52. LocalAssetEntity(await AssetEntity.fromId(asset.id), asset.path));
  53. }
  54. }
  55. // Ignore duplicate items in recents
  56. for (final recent in recents) {
  57. bool presentInOthers = false;
  58. for (final entity in entities) {
  59. if (recent.id == entity.entity.id) {
  60. presentInOthers = true;
  61. break;
  62. }
  63. }
  64. if (!presentInOthers) {
  65. entities.add(
  66. LocalAssetEntity(await AssetEntity.fromId(recent.id), recent.path));
  67. }
  68. }
  69. return await computer.compute(_getFilesFromAssets, param: entities);
  70. }
  71. Future<List<AssetPathEntity>> _getGalleryList(
  72. final int fromTime, final int toTime) async {
  73. final filterOptionGroup = FilterOptionGroup();
  74. filterOptionGroup.setOption(AssetType.image, FilterOption(needTitle: true));
  75. filterOptionGroup.setOption(AssetType.video, FilterOption(needTitle: true));
  76. filterOptionGroup.createTimeCond = DateTimeCond(
  77. min: DateTime.fromMicrosecondsSinceEpoch(fromTime),
  78. max: DateTime.fromMicrosecondsSinceEpoch(toTime),
  79. );
  80. filterOptionGroup.updateTimeCond = DateTimeCond(
  81. min: DateTime.fromMicrosecondsSinceEpoch(fromTime),
  82. max: DateTime.fromMicrosecondsSinceEpoch(toTime),
  83. );
  84. final galleryList = await PhotoManager.getAssetPathList(
  85. hasAll: true,
  86. type: RequestType.common,
  87. filterOption: filterOptionGroup,
  88. );
  89. galleryList.sort((s1, s2) {
  90. return s2.assetCount.compareTo(s1.assetCount);
  91. });
  92. return galleryList;
  93. }
  94. Future<List<File>> _computeFiles(AssetPathEntity pathEntity, int fromTime,
  95. List<File> files, Computer computer) async {
  96. final args = Map<String, dynamic>();
  97. args["pathEntity"] = pathEntity;
  98. args["assetList"] = await pathEntity.assetList;
  99. args["fromTime"] = fromTime;
  100. args["files"] = files;
  101. return await computer.compute(_getFiles, param: args);
  102. }
  103. Future<List<File>> _getFiles(Map<String, dynamic> args) async {
  104. final pathEntity = args["pathEntity"];
  105. final assetList = args["assetList"];
  106. final fromTime = args["fromTime"];
  107. final files = args["files"];
  108. for (AssetEntity entity in assetList) {
  109. if (max(entity.createDateTime.microsecondsSinceEpoch,
  110. entity.modifiedDateTime.microsecondsSinceEpoch) >
  111. fromTime) {
  112. try {
  113. final file = await File.fromAsset(pathEntity.name, entity);
  114. if (!files.contains(file)) {
  115. files.add(file);
  116. }
  117. } catch (e) {
  118. _logger.severe(e);
  119. }
  120. }
  121. }
  122. return files;
  123. }
  124. Future<List<File>> _getFilesFromAssets(List<LocalAssetEntity> assets) async {
  125. final List<File> files = [];
  126. for (final asset in assets) {
  127. files.add(await File.fromAsset(
  128. asset.path,
  129. asset.entity,
  130. ));
  131. }
  132. return files;
  133. }
  134. class LocalAsset {
  135. final String id;
  136. final String path;
  137. LocalAsset(
  138. this.id,
  139. this.path,
  140. );
  141. }
  142. class LocalAssetEntity {
  143. final AssetEntity entity;
  144. final String path;
  145. LocalAssetEntity(this.entity, this.path);
  146. }