Merge branch 'main' into photo_integration

This commit is contained in:
Neeraj Gupta 2023-05-01 16:19:06 +05:30
commit b3c0ec3941
No known key found for this signature in database
GPG key ID: 3C5A1684DC1729E1
7 changed files with 69 additions and 43 deletions

View file

@ -4,7 +4,7 @@ ente 是一个简单的应用程序来备份和分享您的照片和视频。
我们在Android、iOS、web 和桌面上有开源应用, 和您的照片将以端到端加密方式无缝同步 (e2ee)。
即使您不是亲人,也可以轻松地与您的个人分享您的相册。 即使您不是亲人,也可以轻松地与您的个人分享您的相册。 您可以分享可公开查看的链接,他们可以通过添加照片来查看您的相册并进行协作,即使没有帐户或应用。
如果你一直在寻找一个隐私友好的可以替代Google Photos你已经来到了正确的地方。 使用 Ente它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。 使用 Ente它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。 即使您不是亲人,也可以轻松地与您的个人分享您的相册。 即使您不是亲人,也可以轻松地与您的个人分享您的相册。 您可以分享可公开查看的链接,他们可以通过添加照片来查看您的相册并进行协作,即使没有帐户或应用。
您的加密数据已复制到三个不同的地点,包括巴黎的一个铺面掩体。 我们认真对待子孙后代,并确保您回忆比您长寿。 我们认真对待子孙后代,并确保您回忆比您长寿。
@ -30,7 +30,7 @@ ente 是一个简单的应用程序来备份和分享您的照片和视频。
ente requests for certain permissions to serve the purpose of a photo storage provider, which can be reviewed here: https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md
价格
我们不会永远提供免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente. 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente.io找到更多信息。
我们不会永远提供免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente. 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente.io找到更多信息。 您可以在 ente.io找到更多信息。
支持
我们对提供人的支持感到自豪。 我们对提供人的支持感到自豪。 如果您是我们的付费客户您可以联系Team@ente.io并期待我们的团队在24小时内做出回应。

View file

@ -3,6 +3,7 @@ import 'dart:io';
import "package:adaptive_theme/adaptive_theme.dart";
import 'package:background_fetch/background_fetch.dart';
import "package:computer/computer.dart";
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
@ -153,6 +154,8 @@ Future<void> _init(bool isBackground, {String via = ''}) async {
} else {
AppLifecycleService.instance.onAppInForeground('init via: $via');
}
// Start workers asynchronously. No need to wait for them to start
Computer.shared().turnOn(workersCount: 4, verbose: kDebugMode);
CryptoUtil.init();
await NotificationService.instance.init();
await NetworkClient.instance.init();

View file

@ -16,7 +16,6 @@ const assetFetchPageSize = 2000;
Future<Tuple2<List<LocalPathAsset>, List<File>>> getLocalPathAssetsAndFiles(
int fromTime,
int toTime,
Computer computer,
) async {
final pathEntities = await _getGalleryList(
updateFromTime: fromTime,
@ -31,17 +30,24 @@ Future<Tuple2<List<LocalPathAsset>, List<File>>> getLocalPathAssetsAndFiles(
final List<File> uniqueFiles = [];
for (AssetPathEntity pathEntity in pathEntities) {
final List<AssetEntity> assetsInPath = await _getAllAssetLists(pathEntity);
final Tuple2<Set<String>, List<File>> result = await computer.compute(
_getLocalIDsAndFilesFromAssets,
param: <String, dynamic>{
"pathEntity": pathEntity,
"fromTime": fromTime,
"alreadySeenLocalIDs": alreadySeenLocalIDs,
"assetList": assetsInPath,
},
);
alreadySeenLocalIDs.addAll(result.item1);
uniqueFiles.addAll(result.item2);
late Tuple2<Set<String>, List<File>> result;
if (assetsInPath.isEmpty) {
result = const Tuple2({}, []);
} else {
result = await Computer.shared().compute(
_getLocalIDsAndFilesFromAssets,
param: <String, dynamic>{
"pathEntity": pathEntity,
"fromTime": fromTime,
"alreadySeenLocalIDs": alreadySeenLocalIDs,
"assetList": assetsInPath,
},
taskName:
"getLocalPathAssetsAndFiles-${pathEntity.name}-count-${assetsInPath.length}",
);
alreadySeenLocalIDs.addAll(result.item1);
uniqueFiles.addAll(result.item2);
}
localPathAssets.add(
LocalPathAsset(
localIDs: result.item1,
@ -118,15 +124,17 @@ Future<LocalDiffResult> getDiffWithLocal(
Set<String> existingIDs, // localIDs of files already imported in app
Map<String, Set<String>> pathToLocalIDs,
Set<String> invalidIDs,
Computer computer,
) async {
final Map<String, dynamic> args = <String, dynamic>{};
args['assets'] = assets;
args['existingIDs'] = existingIDs;
args['invalidIDs'] = invalidIDs;
args['pathToLocalIDs'] = pathToLocalIDs;
final LocalDiffResult diffResult =
await computer.compute(_getLocalAssetsDiff, param: args);
final LocalDiffResult diffResult = await Computer.shared().compute(
_getLocalAssetsDiff,
param: args,
taskName: "getLocalAssetsDiff",
);
if (diffResult.localPathAssets != null) {
diffResult.uniqueLocalFiles =
await _convertLocalAssetsToUniqueFiles(diffResult.localPathAssets!);

View file

@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:io';
import 'package:computer/computer.dart';
import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart';
import 'package:photo_manager/photo_manager.dart';
@ -24,7 +23,6 @@ import 'package:tuple/tuple.dart';
class LocalSyncService {
final _logger = Logger("LocalSyncService");
final _db = FilesDB.instance;
final Computer _computer = Computer();
late SharedPreferences _prefs;
Completer<void>? _existingSync;
@ -47,7 +45,6 @@ class LocalSyncService {
if (!AppLifecycleService.instance.isForeground) {
await PhotoManager.setIgnorePermissionCheck(true);
}
await _computer.turnOn(workersCount: 1);
if (hasGrantedPermissions()) {
_registerChangeCallback();
}
@ -164,7 +161,6 @@ class LocalSyncService {
existingLocalFileIDs,
pathToLocalIDs,
invalidIDs,
_computer,
);
bool hasAnyMappingChanged = false;
if (localDiffResult.newPathToLocalIDs?.isNotEmpty ?? false) {
@ -268,17 +264,18 @@ class LocalSyncService {
required int toTime,
}) async {
final Tuple2<List<LocalPathAsset>, List<File>> result =
await getLocalPathAssetsAndFiles(fromTime, toTime, _computer);
// Update the mapping for device path_id to local file id. Also, keep track
// of newly discovered device paths
await FilesDB.instance.insertLocalAssets(
result.item1,
shouldAutoBackup: Configuration.instance.hasSelectedAllFoldersForBackup(),
);
await getLocalPathAssetsAndFiles(fromTime, toTime);
final List<File> files = result.item2;
if (files.isNotEmpty) {
// Update the mapping for device path_id to local file id. Also, keep track
// of newly discovered device paths
await FilesDB.instance.insertLocalAssets(
result.item1,
shouldAutoBackup:
Configuration.instance.hasSelectedAllFoldersForBackup(),
);
_logger.info(
"Loaded ${files.length} photos from " +
DateTime.fromMicrosecondsSinceEpoch(fromTime).toString() +

View file

@ -166,10 +166,10 @@ Uint8List chachaDecryptData(Map<String, dynamic> args) {
}
class CryptoUtil {
static final Computer _computer = Computer();
// Note: workers are turned on during app startup.
static final Computer _computer = Computer.shared();
static init() {
_computer.turnOn(workersCount: 4);
Sodium.init();
}
@ -231,7 +231,11 @@ class CryptoUtil {
args["cipher"] = cipher;
args["nonce"] = nonce;
args["key"] = key;
return _computer.compute(cryptoSecretboxOpenEasy, param: args);
return _computer.compute(
cryptoSecretboxOpenEasy,
param: args,
taskName: "decrypt",
);
}
// Decrypts the given cipher, with the given key and nonce using XSalsa20
@ -262,7 +266,11 @@ class CryptoUtil {
final args = <String, dynamic>{};
args["source"] = source;
args["key"] = key;
return _computer.compute(chachaEncryptData, param: args);
return _computer.compute(
chachaEncryptData,
param: args,
taskName: "encryptChaCha",
);
}
// Decrypts the given source, with the given key and header using XChaCha20
@ -277,7 +285,11 @@ class CryptoUtil {
args["source"] = source;
args["key"] = key;
args["header"] = header;
return _computer.compute(chachaDecryptData, param: args);
return _computer.compute(
chachaDecryptData,
param: args,
taskName: "decryptChaCha",
);
}
// Encrypts the file at sourceFilePath, with the key (if provided) and a
@ -293,7 +305,8 @@ class CryptoUtil {
args["sourceFilePath"] = sourceFilePath;
args["destinationFilePath"] = destinationFilePath;
args["key"] = key;
return _computer.compute(chachaEncryptFile, param: args);
return _computer.compute(chachaEncryptFile,
param: args, taskName: "encryptFile");
}
// Decrypts the file at sourceFilePath, with the given key and header using
@ -309,7 +322,8 @@ class CryptoUtil {
args["destinationFilePath"] = destinationFilePath;
args["header"] = header;
args["key"] = key;
return _computer.compute(chachaDecryptFile, param: args);
return _computer.compute(chachaDecryptFile,
param: args, taskName: "decryptFile");
}
// Generates and returns a 256-bit key.
@ -391,7 +405,7 @@ class CryptoUtil {
return DerivedKeyResult(key, memLimit, opsLimit);
}
// Derives a key for a given password, salt, memLimit and opsLimit using
// Derives a key for a given password, salt, memLimit and opsLimit using
// Argon2id, v1.3.
static Future<Uint8List> deriveKey(
Uint8List password,
@ -407,6 +421,7 @@ class CryptoUtil {
"memLimit": memLimit,
"opsLimit": opsLimit,
},
taskName: "deriveKey",
);
}
@ -417,6 +432,7 @@ class CryptoUtil {
param: {
"sourceFilePath": source.path,
},
taskName: "fileHash",
);
}
}

View file

@ -275,11 +275,12 @@ packages:
computer:
dependency: "direct main"
description:
name: computer
sha256: "3df9f1ef497aaf69e066b00f4441726eb28037dc33e97b5d56393967f92c5fe8"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
path: "."
ref: HEAD
resolved-ref: "82e365fed8a1a76f6eea0220de98389eed7b0445"
url: "https://github.com/ente-io/computer.git"
source: git
version: "3.2.1"
confetti:
dependency: "direct main"
description:

View file

@ -28,7 +28,8 @@ dependencies:
chewie:
path: thirdparty/chewie
collection: # dart
computer: ^2.0.0
computer:
git: "https://github.com/ente-io/computer.git"
confetti: ^0.6.0
connectivity_plus: ^3.0.3
crypto: ^3.0.2