Merge pull request #56 from ente-io/force_sync_old_clients

Force pull since the time archive was released
This commit is contained in:
Neeraj Gupta 2021-09-24 12:23:42 +05:30 committed by GitHub
commit bf02ed214f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 106 additions and 36 deletions

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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

View file

@ -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);
}