trash_sync_service.dart 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import 'package:dio/dio.dart';
  2. import 'package:logging/logging.dart';
  3. import 'package:photos/core/configuration.dart';
  4. import 'package:photos/core/network.dart';
  5. import 'package:photos/db/files_db.dart';
  6. import 'package:photos/db/ignore_files_db.dart';
  7. import 'package:photos/db/trash_db.dart';
  8. import 'package:photos/models/ignored_file.dart';
  9. import 'package:photos/models/trash_file.dart';
  10. import 'package:photos/models/trash_item_request.dart';
  11. import 'package:photos/utils/trash_diff_fetcher.dart';
  12. import 'package:shared_preferences/shared_preferences.dart';
  13. class TrashSyncService {
  14. final _logger = Logger("TrashSyncService");
  15. final _diffFetcher = TrashDiffFetcher();
  16. final _filesDB = FilesDB.instance;
  17. final _trashDB = TrashDB.instance;
  18. static const kDiffLimit = 2500;
  19. static const kLastTrashSyncTime = "last_trash_sync_timex";
  20. SharedPreferences _prefs;
  21. TrashSyncService._privateConstructor();
  22. static final TrashSyncService instance =
  23. TrashSyncService._privateConstructor();
  24. final _dio = Network.instance.getDio();
  25. Future<void> init() async {
  26. _prefs = await SharedPreferences.getInstance();
  27. }
  28. Future<void> syncTrash() async {
  29. final lastSyncTime = getSyncTime();
  30. _logger.fine('sync trash sinceTime : $lastSyncTime');
  31. var diff = await _diffFetcher.getTrashFilesDiff(lastSyncTime, kDiffLimit);
  32. if (diff.trashedFiles.isNotEmpty) {
  33. _logger.fine("inserting ${diff.trashedFiles.length} items in trash");
  34. await _trashDB.insertMultiple(diff.trashedFiles);
  35. }
  36. if (diff.deletedFiles.isNotEmpty) {
  37. _logger.fine("discard ${diff.deletedFiles.length} deleted items");
  38. await _trashDB
  39. .delete(diff.deletedFiles.map((e) => e.uploadedFileID).toList());
  40. }
  41. if (diff.restoredFiles.isNotEmpty) {
  42. _logger.fine("discard ${diff.restoredFiles.length} restored items");
  43. await _trashDB
  44. .delete(diff.restoredFiles.map((e) => e.uploadedFileID).toList());
  45. }
  46. await _updateIgnoredFiles(diff);
  47. if (diff.lastSyncedTimeStamp != 0) {
  48. await setSyncTime(diff.lastSyncedTimeStamp);
  49. }
  50. if (diff.fetchCount == kDiffLimit) {
  51. return await syncTrash();
  52. }
  53. }
  54. Future<void> _updateIgnoredFiles(Diff diff) async {
  55. final ignoredFiles = <IgnoredFile>[];
  56. for (TrashFile t in diff.trashedFiles) {
  57. final file = IgnoredFile.fromTrashItem(t);
  58. if (file != null) {
  59. ignoredFiles.add(file);
  60. }
  61. }
  62. for (TrashFile t in diff.deletedFiles) {
  63. final file = IgnoredFile.fromTrashItem(t);
  64. if (file != null) {
  65. ignoredFiles.add(file);
  66. }
  67. }
  68. if (ignoredFiles.isNotEmpty) {
  69. _logger.fine('updating ${ignoredFiles.length} ignored files ');
  70. await IgnoreFilesDB.instance.insertMultiple(ignoredFiles);
  71. }
  72. }
  73. Future<void> setSyncTime(int time) async {
  74. if (time == null) {
  75. return _prefs.remove(kLastTrashSyncTime);
  76. }
  77. return _prefs.setInt(kLastTrashSyncTime, time);
  78. }
  79. int getSyncTime() {
  80. return _prefs.getInt(kLastTrashSyncTime) ?? 0;
  81. }
  82. Future<void> trashFilesOnServer(List<TrashRequest> trashRequestItems) async {
  83. final params = <String, dynamic>{};
  84. final includedFileIDs = <int>{};
  85. params["items"] = [];
  86. for (final item in trashRequestItems) {
  87. if (!includedFileIDs.contains(item.fileID)) {
  88. params["items"].add(item.toJson());
  89. includedFileIDs.add(item.fileID);
  90. }
  91. }
  92. return await _dio.post(
  93. Configuration.instance.getHttpEndpoint() + "/files/trash",
  94. options: Options(
  95. headers: {
  96. "X-Auth-Token": Configuration.instance.getToken(),
  97. },
  98. ),
  99. data: params,
  100. );
  101. }
  102. Future<void> deleteFromTrash(List<TrashFile> trashedFiles) async {
  103. final params = <String, dynamic>{};
  104. final uniqueFileIds =
  105. trashedFiles.map((e) => e.uploadedFileID).toSet().toList();
  106. params["fileIDs"] = [];
  107. for (final fileID in uniqueFileIds) {
  108. params["fileIDs"].add(fileID);
  109. }
  110. try {
  111. await _dio.post(
  112. Configuration.instance.getHttpEndpoint() + "/trash/delete",
  113. options: Options(
  114. headers: {
  115. "X-Auth-Token": Configuration.instance.getToken(),
  116. },
  117. ),
  118. data: params,
  119. );
  120. _trashDB.delete(uniqueFileIds);
  121. } catch (e, s) {
  122. _logger.severe("failed to delete from trash", e, s);
  123. rethrow;
  124. }
  125. }
  126. }