Merge pull request #56 from ente-io/force_sync_old_clients
Force pull since the time archive was released
This commit is contained in:
commit
bf02ed214f
|
@ -233,7 +233,8 @@ class CollectionsService {
|
|||
|
||||
Future<void> rename(Collection collection, String newName) async {
|
||||
try {
|
||||
final encryptedName = CryptoUtil.encryptSync(utf8.encode(newName), getCollectionKey(collection.id));
|
||||
final encryptedName = CryptoUtil.encryptSync(
|
||||
utf8.encode(newName), getCollectionKey(collection.id));
|
||||
await _dio.post(
|
||||
Configuration.instance.getHttpEndpoint() + "/collections/rename",
|
||||
data: {
|
||||
|
@ -330,7 +331,23 @@ class CollectionsService {
|
|||
return collection;
|
||||
}
|
||||
|
||||
Future<void> addToCollection(int collectionID, List<File> files) {
|
||||
Future<void> addToCollection(int collectionID, List<File> files) async {
|
||||
final containsUploadedFile = files.firstWhere(
|
||||
(element) => element.uploadedFileID != null,
|
||||
orElse: () => null) !=
|
||||
null;
|
||||
if (containsUploadedFile) {
|
||||
final existingFileIDsInCollection =
|
||||
await FilesDB.instance.getUploadedFileIDs(collectionID);
|
||||
files.removeWhere((element) =>
|
||||
element.uploadedFileID != null &&
|
||||
existingFileIDsInCollection.contains(element.uploadedFileID));
|
||||
if (files.isEmpty) {
|
||||
_logger.info("nothing to add to the collection");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final params = <String, dynamic>{};
|
||||
params["collectionID"] = collectionID;
|
||||
for (final file in files) {
|
||||
|
@ -348,22 +365,33 @@ class CollectionsService {
|
|||
file.uploadedFileID, file.encryptedKey, file.keyDecryptionNonce)
|
||||
.toMap());
|
||||
}
|
||||
return _dio
|
||||
.post(
|
||||
Configuration.instance.getHttpEndpoint() + "/collections/add-files",
|
||||
data: params,
|
||||
options:
|
||||
Options(headers: {"X-Auth-Token": Configuration.instance.getToken()}),
|
||||
)
|
||||
.then((value) async {
|
||||
|
||||
try {
|
||||
await _dio.post(
|
||||
Configuration.instance.getHttpEndpoint() + "/collections/add-files",
|
||||
data: params,
|
||||
options: Options(
|
||||
headers: {"X-Auth-Token": Configuration.instance.getToken()}),
|
||||
);
|
||||
await _filesDB.insertMultiple(files);
|
||||
Bus.instance.fire(CollectionUpdatedEvent(collectionID, files));
|
||||
});
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> move(
|
||||
int toCollectionID, int fromCollectionID, List<File> files) {
|
||||
int toCollectionID, int fromCollectionID, List<File> files) async {
|
||||
_validateMoveRequest(toCollectionID, fromCollectionID, files);
|
||||
final existingUploadedIDs =
|
||||
await FilesDB.instance.getUploadedFileIDs(toCollectionID);
|
||||
files.removeWhere((element) =>
|
||||
element.uploadedFileID != null &&
|
||||
existingUploadedIDs.contains(element.uploadedFileID));
|
||||
if (files.isEmpty) {
|
||||
_logger.info("nothing to move to collection");
|
||||
return;
|
||||
}
|
||||
final params = <String, dynamic>{};
|
||||
params["toCollectionID"] = toCollectionID;
|
||||
params["fromCollectionID"] = fromCollectionID;
|
||||
|
@ -471,6 +499,10 @@ class CollectionsService {
|
|||
Sodium.base642bin(collection.attributes.pathDecryptionNonce)));
|
||||
}
|
||||
|
||||
bool hasSyncedCollections() {
|
||||
return _prefs.containsKey(_collectionsSyncTimeKey);
|
||||
}
|
||||
|
||||
Collection _getCollectionWithDecryptedName(Collection collection) {
|
||||
if (collection.encryptedName != null &&
|
||||
collection.encryptedName.isNotEmpty) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
|
@ -16,6 +17,7 @@ import 'package:photos/services/local_sync_service.dart';
|
|||
import 'package:photos/utils/diff_fetcher.dart';
|
||||
import 'package:photos/utils/file_uploader.dart';
|
||||
import 'package:photos/utils/file_util.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class RemoteSyncService {
|
||||
final _logger = Logger("RemoteSyncService");
|
||||
|
@ -24,22 +26,46 @@ class RemoteSyncService {
|
|||
final _collectionsService = CollectionsService.instance;
|
||||
final _diffFetcher = DiffFetcher();
|
||||
int _completedUploads = 0;
|
||||
SharedPreferences _prefs;
|
||||
|
||||
static const kDiffLimit = 2500;
|
||||
static const kHasSyncedArchiveKey = "has_synced_archive";
|
||||
static const kArchiveFeatureReleaseTime = 1632100000000000;
|
||||
|
||||
static final RemoteSyncService instance =
|
||||
RemoteSyncService._privateConstructor();
|
||||
|
||||
RemoteSyncService._privateConstructor();
|
||||
|
||||
Future<void> init() async {}
|
||||
Future<void> init() async {
|
||||
_prefs = await SharedPreferences.getInstance();
|
||||
}
|
||||
|
||||
Future<void> sync({bool silently = false}) async {
|
||||
if (!Configuration.instance.hasConfiguredAccount()) {
|
||||
_logger.info("Skipping remote sync since account is not configured");
|
||||
return;
|
||||
}
|
||||
|
||||
bool isFirstSync = !_collectionsService.hasSyncedCollections();
|
||||
await _collectionsService.sync();
|
||||
|
||||
if (isFirstSync || _hasSyncedArchive()) {
|
||||
await _syncUpdatedCollections(silently);
|
||||
} else {
|
||||
await _resyncAllCollectionsSinceTime(kArchiveFeatureReleaseTime);
|
||||
}
|
||||
if (!_hasSyncedArchive()) {
|
||||
await _markArchiveAsSynced();
|
||||
}
|
||||
|
||||
bool hasUploadedFiles = await _uploadDiff();
|
||||
if (hasUploadedFiles) {
|
||||
sync(silently: true);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _syncUpdatedCollections(bool silently) async {
|
||||
final updatedCollections =
|
||||
await _collectionsService.getCollectionsToBeSynced();
|
||||
|
||||
|
@ -47,21 +73,24 @@ class RemoteSyncService {
|
|||
Bus.instance.fire(SyncStatusUpdate(SyncStatus.applying_remote_diff));
|
||||
}
|
||||
for (final c in updatedCollections) {
|
||||
await _syncCollectionDiff(c.id);
|
||||
_collectionsService.setCollectionSyncTime(c.id, c.updationTime);
|
||||
}
|
||||
bool hasUploadedFiles = await _uploadDiff();
|
||||
if (hasUploadedFiles) {
|
||||
sync(silently: true);
|
||||
await _syncCollectionDiff(
|
||||
c.id, _collectionsService.getCollectionSyncTime(c.id));
|
||||
await _collectionsService.setCollectionSyncTime(c.id, c.updationTime);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _syncCollectionDiff(int collectionID) async {
|
||||
Future<void> _resyncAllCollectionsSinceTime(int sinceTime) async {
|
||||
final collections = _collectionsService.getCollections();
|
||||
for (final c in collections) {
|
||||
await _syncCollectionDiff(c.id,
|
||||
min(_collectionsService.getCollectionSyncTime(c.id), sinceTime));
|
||||
await _collectionsService.setCollectionSyncTime(c.id, c.updationTime);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _syncCollectionDiff(int collectionID, int sinceTime) async {
|
||||
final diff = await _diffFetcher.getEncryptedFilesDiff(
|
||||
collectionID,
|
||||
_collectionsService.getCollectionSyncTime(collectionID),
|
||||
kDiffLimit,
|
||||
);
|
||||
collectionID, sinceTime, kDiffLimit);
|
||||
if (diff.updatedFiles.isNotEmpty) {
|
||||
await _storeDiff(diff.updatedFiles, collectionID);
|
||||
_logger.info("Updated " +
|
||||
|
@ -71,9 +100,10 @@ class RemoteSyncService {
|
|||
Bus.instance.fire(LocalPhotosUpdatedEvent(diff.updatedFiles));
|
||||
Bus.instance
|
||||
.fire(CollectionUpdatedEvent(collectionID, diff.updatedFiles));
|
||||
if (diff.fetchCount == kDiffLimit) {
|
||||
return await _syncCollectionDiff(collectionID);
|
||||
}
|
||||
}
|
||||
if (diff.fetchCount == kDiffLimit) {
|
||||
return await _syncCollectionDiff(collectionID,
|
||||
_collectionsService.getCollectionSyncTime(collectionID));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,4 +283,12 @@ class RemoteSyncService {
|
|||
" was uploaded from device but added to a new collection on remote.",
|
||||
);
|
||||
}
|
||||
|
||||
bool _hasSyncedArchive() {
|
||||
return _prefs.containsKey(kHasSyncedArchiveKey);
|
||||
}
|
||||
|
||||
Future<bool> _markArchiveAsSynced() {
|
||||
return _prefs.setBool(kHasSyncedArchiveKey, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,7 +272,6 @@ class _CreateCollectionPageState extends State<CreateCollectionPage> {
|
|||
await FilesDB.instance.insertMultiple(localFiles);
|
||||
} else {
|
||||
for (final file in widget.selectedFiles.files) {
|
||||
await FilesDB.instance.insert(file);
|
||||
final currentFile = await FilesDB.instance.getFile(file.generatedID);
|
||||
if (currentFile.uploadedFileID == null) {
|
||||
final uploadedFile = (await FileUploader.instance
|
||||
|
|
|
@ -49,21 +49,20 @@ class DiffFetcher {
|
|||
if (existingFiles.contains(file.uploadedFileID)) {
|
||||
await FilesDB.instance.deleteFromCollection(
|
||||
file.uploadedFileID, file.collectionID);
|
||||
Bus.instance.fire(
|
||||
CollectionUpdatedEvent(file.collectionID, [file]));
|
||||
Bus.instance
|
||||
.fire(CollectionUpdatedEvent(file.collectionID, [file]));
|
||||
Bus.instance.fire(LocalPhotosUpdatedEvent([file]));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
file.updationTime = item["updationTime"];
|
||||
if (existingFiles.contains(file.uploadedFileID)) {
|
||||
final existingFile = await FilesDB.instance
|
||||
.getUploadedFile(file.uploadedFileID, file.collectionID);
|
||||
if (existingFile != null &&
|
||||
existingFile.updationTime == file.updationTime) {
|
||||
continue;
|
||||
if (existingFile != null) {
|
||||
file.generatedID = existingFile.generatedID;
|
||||
}
|
||||
}
|
||||
file.updationTime = item["updationTime"];
|
||||
file.ownerID = item["ownerID"];
|
||||
file.encryptedKey = item["encryptedKey"];
|
||||
file.keyDecryptionNonce = item["keyDecryptionNonce"];
|
||||
|
@ -84,11 +83,13 @@ class DiffFetcher {
|
|||
file.applyMetadata(metadata);
|
||||
if (item['magicMetadata'] != null) {
|
||||
final utfEncodedMmd = await CryptoUtil.decryptChaCha(
|
||||
Sodium.base642bin(item['magicMetadata']['data']), fileDecryptionKey,
|
||||
Sodium.base642bin(item['magicMetadata']['data']),
|
||||
fileDecryptionKey,
|
||||
Sodium.base642bin(item['magicMetadata']['header']));
|
||||
file.mMdEncodedJson = utf8.decode(utfEncodedMmd);
|
||||
file.mMdVersion = item['magicMetadata']['version'];
|
||||
file.magicMetadata = MagicMetadata.fromEncodedJson(file.mMdEncodedJson);
|
||||
file.magicMetadata =
|
||||
MagicMetadata.fromEncodedJson(file.mMdEncodedJson);
|
||||
}
|
||||
files.add(file);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue