diff_fetcher.dart 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import 'dart:convert';
  2. import 'package:dio/dio.dart';
  3. import 'package:flutter_sodium/flutter_sodium.dart';
  4. import 'package:logging/logging.dart';
  5. import 'package:photos/core/configuration.dart';
  6. import 'package:photos/core/event_bus.dart';
  7. import 'package:photos/core/network.dart';
  8. import 'package:photos/db/files_db.dart';
  9. import 'package:photos/events/collection_updated_event.dart';
  10. import 'package:photos/events/remote_sync_event.dart';
  11. import 'package:photos/models/file.dart';
  12. import 'package:photos/repositories/file_repository.dart';
  13. import 'package:photos/utils/crypto_util.dart';
  14. import 'package:photos/utils/file_util.dart';
  15. class DiffFetcher {
  16. final _logger = Logger("FileDownloader");
  17. final _dio = Network.instance.getDio();
  18. Future<Diff> getEncryptedFilesDiff(
  19. int collectionID, int sinceTime, int limit) async {
  20. return _dio
  21. .get(
  22. Configuration.instance.getHttpEndpoint() + "/collections/diff",
  23. options: Options(
  24. headers: {"X-Auth-Token": Configuration.instance.getToken()}),
  25. queryParameters: {
  26. "collectionID": collectionID,
  27. "sinceTime": sinceTime,
  28. "limit": limit,
  29. },
  30. )
  31. .catchError((e) => _logger.severe(e))
  32. .then((response) async {
  33. final files = List<File>();
  34. if (response != null) {
  35. Bus.instance.fire(RemoteSyncEvent(true));
  36. final diff = response.data["diff"] as List;
  37. final startTime = DateTime.now();
  38. final existingFiles =
  39. await FilesDB.instance.getUploadedFileIDs(collectionID);
  40. for (final item in diff) {
  41. final file = File();
  42. file.uploadedFileID = item["id"];
  43. file.collectionID = item["collectionID"];
  44. if (item["isDeleted"]) {
  45. await FilesDB.instance.deleteFromCollection(
  46. file.uploadedFileID, file.collectionID);
  47. Bus.instance.fire(
  48. CollectionUpdatedEvent(collectionID: file.collectionID));
  49. FileRepository.instance.reloadFiles();
  50. continue;
  51. }
  52. file.updationTime = item["updationTime"];
  53. if (existingFiles.contains(file.uploadedFileID)) {
  54. final existingFile = await FilesDB.instance
  55. .getUploadedFile(file.uploadedFileID, file.collectionID);
  56. if (existingFile != null &&
  57. existingFile.updationTime == file.updationTime) {
  58. continue;
  59. }
  60. }
  61. file.ownerID = item["ownerID"];
  62. file.encryptedKey = item["encryptedKey"];
  63. file.keyDecryptionNonce = item["keyDecryptionNonce"];
  64. file.fileDecryptionHeader = item["file"]["decryptionHeader"];
  65. file.thumbnailDecryptionHeader =
  66. item["thumbnail"]["decryptionHeader"];
  67. file.metadataDecryptionHeader =
  68. item["metadata"]["decryptionHeader"];
  69. final encodedMetadata = CryptoUtil.decryptChaCha(
  70. Sodium.base642bin(item["metadata"]["encryptedData"]),
  71. decryptFileKey(file),
  72. Sodium.base642bin(file.metadataDecryptionHeader),
  73. );
  74. Map<String, dynamic> metadata =
  75. jsonDecode(utf8.decode(encodedMetadata));
  76. file.applyMetadata(metadata);
  77. files.add(file);
  78. }
  79. final endTime = DateTime.now();
  80. _logger.info("time for parsing " +
  81. files.length.toString() +
  82. ": " +
  83. Duration(
  84. microseconds: (endTime.microsecondsSinceEpoch -
  85. startTime.microsecondsSinceEpoch))
  86. .inMilliseconds
  87. .toString());
  88. return Diff(files, diff.length);
  89. } else {
  90. Bus.instance.fire(RemoteSyncEvent(false));
  91. return Diff(List<File>(), 0);
  92. }
  93. });
  94. }
  95. }
  96. class Diff {
  97. final List<File> updatedFiles;
  98. final int fetchCount;
  99. Diff(this.updatedFiles, this.fetchCount);
  100. }