files_service.dart 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import 'package:dio/dio.dart';
  2. import 'package:logging/logging.dart';
  3. import 'package:path/path.dart';
  4. import 'package:photos/core/configuration.dart';
  5. import 'package:photos/core/network/network.dart';
  6. import 'package:photos/db/files_db.dart';
  7. import 'package:photos/extensions/list.dart';
  8. import 'package:photos/models/file.dart';
  9. import 'package:photos/models/magic_metadata.dart';
  10. import 'package:photos/services/file_magic_service.dart';
  11. import 'package:photos/utils/date_time_util.dart';
  12. class FilesService {
  13. late Dio _enteDio;
  14. late Logger _logger;
  15. late FilesDB _filesDB;
  16. late Configuration _config;
  17. FilesService._privateConstructor() {
  18. _enteDio = NetworkClient.instance.enteDio;
  19. _logger = Logger("FilesService");
  20. _filesDB = FilesDB.instance;
  21. _config = Configuration.instance;
  22. }
  23. static final FilesService instance = FilesService._privateConstructor();
  24. Future<int> getFileSize(int uploadedFileID) async {
  25. try {
  26. final response = await _enteDio.post(
  27. "/files/size",
  28. data: {
  29. "fileIDs": [uploadedFileID]
  30. },
  31. );
  32. return response.data["size"];
  33. } catch (e) {
  34. _logger.severe(e);
  35. rethrow;
  36. }
  37. }
  38. Future<void> bulkEditTime(
  39. List<File> files,
  40. EditTimeSource source,
  41. ) async {
  42. final ListMatch<File> result = files.splitMatch(
  43. (element) => element.isUploaded,
  44. );
  45. final List<File> uploadedFiles = result.matched;
  46. // editTime For LocalFiles
  47. final List<File> localOnlyFiles = result.unmatched;
  48. for (File localFile in localOnlyFiles) {
  49. final timeResult = _parseTime(localFile, source);
  50. if (timeResult != null) {
  51. localFile.creationTime = timeResult;
  52. }
  53. }
  54. await _filesDB.insertMultiple(localOnlyFiles);
  55. final List<File> remoteFilesToUpdate = [];
  56. final Map<int, Map<String, int>> fileIDToUpdateMetadata = {};
  57. for (File remoteFile in uploadedFiles) {
  58. // discard files not owned by user and also dedupe already processed
  59. // files
  60. if (remoteFile.ownerID != _config.getUserID()! ||
  61. fileIDToUpdateMetadata.containsKey(remoteFile.uploadedFileID!)) {
  62. continue;
  63. }
  64. final timeResult = _parseTime(remoteFile, source);
  65. if (timeResult != null) {
  66. remoteFilesToUpdate.add(remoteFile);
  67. fileIDToUpdateMetadata[remoteFile.uploadedFileID!] = {
  68. pubMagicKeyEditedTime: timeResult,
  69. };
  70. }
  71. }
  72. if (remoteFilesToUpdate.isNotEmpty) {
  73. await FileMagicService.instance.updatePublicMagicMetadata(
  74. remoteFilesToUpdate,
  75. null,
  76. metadataUpdateMap: fileIDToUpdateMetadata,
  77. );
  78. }
  79. }
  80. int? _parseTime(File file, EditTimeSource source) {
  81. assert(
  82. source == EditTimeSource.fileName,
  83. "edit source ${source.name} is not supported yet",
  84. );
  85. final timeResult = parseDateTimeFromFileNameV2(
  86. basenameWithoutExtension(file.title ?? ""),
  87. );
  88. return timeResult?.microsecondsSinceEpoch;
  89. }
  90. }
  91. enum EditTimeSource {
  92. // parse the time from fileName
  93. fileName,
  94. // parse the time from exif data of file.
  95. exif,
  96. // use the which user provided as input
  97. manualFix,
  98. // adjust the time of selected photos by +/- time.
  99. // required for cases when the original device in which photos were taken
  100. // had incorrect time (quite common with physical cameras)
  101. manualAdjusted,
  102. }