file_downloader.dart 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. for (final item in diff) {
  38. final file = File();
  39. file.uploadedFileID = item["id"];
  40. file.collectionID = item["collectionID"];
  41. if (item["isDeleted"]) {
  42. await FilesDB.instance.deleteFromCollection(
  43. file.uploadedFileID, file.collectionID);
  44. Bus.instance.fire(
  45. CollectionUpdatedEvent(collectionID: file.collectionID));
  46. FileRepository.instance.reloadFiles();
  47. continue;
  48. }
  49. file.updationTime = item["updationTime"];
  50. final existingFile = await FilesDB.instance
  51. .getUploadedFile(file.uploadedFileID, file.collectionID);
  52. if (existingFile != null &&
  53. existingFile.updationTime == file.updationTime) {
  54. continue;
  55. }
  56. file.ownerID = item["ownerID"];
  57. file.isEncrypted = true;
  58. file.encryptedKey = item["encryptedKey"];
  59. file.keyDecryptionNonce = item["keyDecryptionNonce"];
  60. file.fileDecryptionHeader = item["file"]["decryptionHeader"];
  61. file.thumbnailDecryptionHeader =
  62. item["thumbnail"]["decryptionHeader"];
  63. file.metadataDecryptionHeader =
  64. item["metadata"]["decryptionHeader"];
  65. final encodedMetadata = CryptoUtil.decryptChaCha(
  66. Sodium.base642bin(item["metadata"]["encryptedData"]),
  67. decryptFileKey(file),
  68. Sodium.base642bin(file.metadataDecryptionHeader),
  69. );
  70. Map<String, dynamic> metadata =
  71. jsonDecode(utf8.decode(encodedMetadata));
  72. file.applyMetadata(metadata);
  73. files.add(file);
  74. }
  75. return Diff(files, diff.length);
  76. } else {
  77. Bus.instance.fire(RemoteSyncEvent(false));
  78. return Diff(List<File>(), 0);
  79. }
  80. });
  81. }
  82. }
  83. class Diff {
  84. final List<File> updatedFiles;
  85. final int fetchCount;
  86. Diff(this.updatedFiles, this.fetchCount);
  87. }