Merge branch 'main' into custom_radius

This commit is contained in:
ashilkn 2023-04-27 13:02:41 +05:30
commit c7fbb550fc
27 changed files with 370 additions and 19 deletions

View file

@ -1,12 +1,21 @@
project_id_env: CROWDIN_PROJECT_ID
api_token_env: CROWDIN_PERSONAL_TOKEN
preserve_hierarchy: true
files:
- source: /lib/l10n/intl_en.arb
translation: /lib/l10n/intl_%two_letters_code%.arb
- source: fastlane/metadata/playstore/en-US/*.txt
translation: fastlane/metadata/playstore/%two_letters_code%/%original_file_name%.txt
- source: fastlane/metadata/android/en-US/*.txt
translation: fastlane/metadata/android/%two_letters_code%/%original_file_name%.txt
- source: fastlane/metadata/ios/en-US/*.txt
translation: fastlane/metadata/ios/%two_letters_code%/%original_file_name%.txt
dest: /%original_file_name%
type: arb
- source: /fastlane/metadata/playstore/en-US/*.txt
translation: /fastlane/metadata/playstore/%two_letters_code%/%original_file_name%
dest: /playstore/%original_file_name%
type: txt
- source: /fastlane/metadata/android/en-US/*.txt
translation: /translations/%two_letters_code%/%original_file_name%
dest: /fdroid/%original_file_name%
type: txt
- source: /fastlane/metadata/ios/en-US/*.txt
translation: /fastlane/metadata/ios/%two_letters_code%/%original_file_name%
dest: /appstore/%original_file_name%
type: txt

View file

@ -0,0 +1,33 @@
Ente es una aplicación simple que guarda automáticamente copias de segurida y organiza tus fotos y vídeos.
Si has estado buscando una alternativa pro-privacidad para guardar tus recuerdos, has llegado al sitio adecuado. Con Ente, se almacenan cifradas de extremo a extremo (e2ee). Esto significa que solo tú puedes verlas.
Tenemos aplicaciones en todas las plataformas, y tus fotos se sincronizarán perfectamente entre todos tus dispositivos encriptadas de extremo a extremo (e2ee).
Ente también facitila compartir tus álbumes con tus seres queridos. También puedes compartirlos directamente con otros usuarios de Ente cifrados de extremo a extremo, o publicarlos en enlaces visibles.
Tus datos encriptados se almacenan en varias ubicaciones, incluyendo un refugio antiaréreo en París. Nos tomamos en serio la posternidad y hacemos posible asegurar que tus memorias te sobreviven.
Estamos aquí para hacer la aplicación de fotos más segura de todas.
CARACTERÍSTICAS
- Copias de seguridad de calidad original, porque cada píxel es importante
- Planes familiares, para que puedas compartir el almacenamiento con tu familia
- Carpetas compartidas, por si quieres que tu pareja disfrute de tus 'clicks'
- Enlaces al álbum, que se pueden proteger con una contraseña y programar para que expiren
- Capacidad para liberar espacio, eliminando archivos de los que ya tienes una copia de seguridad
- Editor de imagen, para añadir retoques finales
- Marca como favoritos, oculta y revive tus recuerdos, porque son preciosos
- Importa en un click desde todos los proveedores de almacenamiento principales
- Tema oscuro, porque tus fotos quedan bien con él
- 2FA, 3FA, autenticación biométrica
- ¡Y mucho más!
PRECIOS
No ofrecemos planes gratis para siempre, porque es importante para nosotros seguir siendo sostenibles y resistir a la prueba del tiempo. En su lugar, ofrecemos planes asequibles que puedes compartir libremente con tu familia. Puedes encontrar más información en ente.io.
SOPORTE
Estamos orgullosos de ofrecer apoyo humano. Si eres un cliente de pago, puedes contactar con team@ente.io y esperar una respuesta de nuestro equipo en 24 horas.
TÉRMINOS
https://ente.io/terms

View file

@ -0,0 +1 @@
fotos,fotografía,familia,privacidad,nube,copia de seguridad,vídeos,foto,encriptación,almacenamiento,álbum,alternativo

View file

@ -0,0 +1 @@
ente Fotos

View file

@ -0,0 +1 @@
Almacenamiento de fotos encriptado

View file

@ -0,0 +1,33 @@
Ente 是一个简单的应用,可以自动备份和整理您的照片和视频。
如果您一直在寻找保护隐私的替代方案来保存您的记忆,那么您来对地方了。 使用 Ente它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。
我们拥有跨所有平台的应用程序,您的照片将以端到端加密 (e2ee) 方式在所有设备之间无缝同步。
Ente 也使得与您的亲人分享您的相册变得简单。 您可以直接与其他Ente 用户共享,端到端加密,或公开链接共享。 您可以直接与其他Ente 用户共享,端到端加密,或公开链接共享。
您的加密数据存储在多个地点,包括巴黎的一个空洞。 我们认真对待子孙后代,并确保您回忆比您长寿。
我们来这里是为了使最安全的照片应用成为新的应用程序,来加入我们的旅程!
特色
- 原始质量备份,因为每个像素都是重要的
- 家庭计划,您可以与家人共享存储
- 共享文件夹,如果您想让您的伙伴享受您的“摄像头”点击
- 相册链接,可以用密码保护并设置为过期
- 能够通过移除已经安全备份的文件释放空间
- 图像编辑器,添加收尾工作
- 收藏、隐藏和恢复您的内存,因为它们是宝贵的
- 从所有主要存储供应商导入单击文件
- 黑暗主题,因为您的照片看起来很好
- 2FA3FA生物鉴别认证
- 还有更多的LOT
价格
我们不会永远提供免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente.io找到更多信息。 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente.io找到更多信息。
支持
我们对提供人的支持感到自豪。 我们对提供人的支持感到自豪。 如果您是我们的付费客户您可以联系Team@ente.io并期待我们的团队在24小时内做出回应。
条款
https://ente.io/terms

View file

@ -0,0 +1 @@
照片,摄影,家庭,隐私,云端,备份,视频,照片,加密,储存,相册,选择

View file

@ -0,0 +1 @@
ente 照片

View file

@ -0,0 +1 @@
加密照片存储

View file

@ -0,0 +1,30 @@
Ente es una aplicación simple que guarda automáticamente copias de segurida y organiza tus fotos y vídeos.
Si has estado buscando una alternativa pro-privacidad para guardar tus recuerdos, has llegado al sitio adecuado. Con Ente, se almacenan cifradas de extremo a extremo (e2ee). Esto significa que solo tú puedes verlas.
Tenemos aplicaciones en Android, iOS, web y escritorio, y tus fotos se sincronizarán perfectamente entre todos tus dispositivos encriptadas de extremo a extremo (e2ee).
Ente también facitila compartir tus álbumes con tus seres queridos. También puedes compartirlos directamente con otros usuarios de Ente cifrados de extremo a extremo, o publicarlos en enlaces visibles.
Tus datos encriptados se almacenan en varias ubicaciones, incluyendo un refugio antiaréreo en París. Nos tomamos en serio la posternidad y hacemos posible asegurar que tus memorias te sobreviven.
Estamos aquí para hacer la aplicación de fotos más segura de todas.
✨ CARACTERÍSTICAS
- Copias de seguridad de calidad original, porque cada píxel es importante
- Planes familiares, para que puedas compartir el almacenamiento con tu familia
- Carpetas compartidas, por si quieres que tu pareja disfrute de tus 'clicks'
- Enlaces al álbum, que se pueden proteger con una contraseña y programar para que expiren
- Capacidad para liberar espacio, eliminando archivos de los que ya tienes una copia de seguridad
- Editor de imagen, para añadir retoques finales
- Marca como favoritos, oculta y revive tus recuerdos, porque son preciosos
- Importa en un click desde Google, Apple, tu disco duro y más
- Tema oscuro, porque tus fotos quedan bien con él
- 2FA, 3FA, autenticación biométrica
- ¡Y mucho más!
💲 PRECIOS
No ofrecemos planes gratis para siempre, porque es importante para nosotros seguir siendo sostenibles y resistir a la prueba del tiempo. En su lugar, ofrecemos planes asequibles que puedes compartir libremente con tu familia. Puedes encontrar más información en ente.io.
🙋 SOPORTE
Estamos orgullosos de ofrecer apoyo humano. Si eres un cliente de pago, puedes contactar con team@ente.io y esperar una respuesta de nuestro equipo en 24 horas.

View file

@ -0,0 +1 @@
Almacenamiento de fotos encriptado - copias de seguridad, organiza y comprte tus fotos y vídeos

View file

@ -0,0 +1 @@
ente Fotos

View file

@ -0,0 +1,30 @@
Ente 是一个简单的应用,可以自动备份和整理您的照片和视频。
如果您一直在寻找保护隐私的替代方案来保存您的记忆,那么您来对地方了。 使用 Ente它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。
我们拥有跨 Android、iOS、Web 和桌面的应用程序,您的照片将以端到端加密 (e2ee) 方式在所有设备之间无缝同步。
Ente 也使得与您的亲人分享您的相册变得简单。 您可以直接与其他Ente 用户共享,端到端加密,或公开链接共享。 您可以直接与其他Ente 用户共享,端到端加密,或公开链接共享。
您的加密数据存储在多个地点,包括巴黎的一个空洞。 我们认真对待子孙后代,并确保您回忆比您长寿。
我们来这里是为了使最安全的照片应用成为新的应用程序,来加入我们的旅程!
✨ 特色
- 原始质量备份,因为每个像素都是重要的
- 家庭计划,您可以与家人共享存储
- 共享文件夹,如果您想让您的伙伴享受您的“摄像头”点击
- 相册链接,可以用密码保护并设置为过期
- 能够通过移除已经安全备份的文件释放空间
- 图像编辑器,添加收尾工作
- 收藏、隐藏和恢复您的内存,因为它们是宝贵的
- 单击从谷歌、苹果、您的硬盘和更多的软件导入
- 黑暗主题,因为您的照片看起来很好
- 2FA3FA生物鉴别认证
- 还有更多的LOT
💲 价格
我们不会永远提供免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente.io找到更多信息。 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente.io找到更多信息。
🙋 支持
我们对提供人的支持感到自豪。 我们对提供人的支持感到自豪。 如果您是我们的付费客户您可以联系Team@ente.io并期待我们的团队在24小时内做出回应。

View file

@ -0,0 +1 @@
加密照片存储 - 备份、整理和分享您的照片和视频

View file

@ -0,0 +1 @@
ente 照片

View file

@ -21,6 +21,10 @@ class FileUpdationDB {
// did not extracted the location to include it in the file metadata
static const missingLocationV2 = 'missingLocationV2';
// refers to the patching of files which had location in exif but the app
// mapped the location to a wrong location
static const badLocationCord = 'badLocationCord';
// SQL code to create the database table
static List<String> _createTable() {
return [

View file

@ -1395,6 +1395,32 @@ class FilesDB {
return result;
}
// returns the localID of all files which are uploaded and belong to the
// user and upload time is greater than 20 April 2023 epoch time and less than
// 15 May 2023 epoch time
Future<List<String>> getFilesWithLocationUploadedBtw20AprTo15May2023(
int ownerID) async {
final db = await database;
final result = await db.query(
filesTable,
columns: [columnLocalID],
distinct: true,
where: ''
'($columnUploadedFileID IS NOT NULL'
' AND $columnUploadedFileID IS NOT -1)'
' AND $columnOwnerID = ?'
' AND $columnUpdationTime > ? AND $columnUpdationTime < ? '
'AND ($columnLatitude IS NOT NULL AND $columnLongitude IS NOT NULL) '
'AND ($columnLongitude IS NOT 0.0 AND $columnLongitude IS NOT 0.0)',
whereArgs: [
ownerID,
1681952400000000,
1684112400000000,
],
);
return result.map((row) => row[columnLocalID].toString()).toList();
}
// For given list of localIDs and ownerID, get a list of uploaded files
// owned by given user
Future<List<File>> getFilesForLocalIDs(

View file

@ -4495,7 +4495,8 @@ class S {
return Intl.message(
'Raise ticket',
name: 'raiseTicket',
desc: '',
desc:
'Button text for raising a support tickets in case of unhandled errors during backup',
args: [],
);
}

View file

@ -622,6 +622,11 @@
"storageLimitExceeded": "Storage limit exceeded",
"upgrade": "Upgrade",
"raiseTicket": "Raise ticket",
"@raiseTicket": {
"description": "Button text for raising a support tickets in case of unhandled errors during backup",
"type": "text"
},
"backupFailed": "Backup failed",
"couldNotBackUpTryLater": "We could not backup your data.\nWe will retry later.",
"enteCanEncryptAndPreserveFilesOnlyIfYouGrant": "ente can encrypt and preserve files only if you grant access to them",

View file

@ -622,6 +622,10 @@
"storageLimitExceeded": "Límite de datos excedido",
"upgrade": "Mejorar",
"raiseTicket": "Generar ticket",
"@raiseTicket": {
"description": "Button text for raising a support tickets in case of unhandled errors during backup",
"type": "text"
},
"backupFailed": "La copia de seguridad ha fallado",
"couldNotBackUpTryLater": "No pudimos hacer una copia de seguridad de tus datos.\nVolveremos a intentarlo más tarde.",
"enteCanEncryptAndPreserveFilesOnlyIfYouGrant": "ente puede cifrar y preservar archivos sólo si concede acceso a ellos",

View file

@ -622,6 +622,10 @@
"storageLimitExceeded": "已超出存储限制",
"upgrade": "升级",
"raiseTicket": "提升工单",
"@raiseTicket": {
"description": "Button text for raising a support tickets in case of unhandled errors during backup",
"type": "text"
},
"backupFailed": "备份失败",
"couldNotBackUpTryLater": "我们无法备份您的数据。\n我们将稍后再试。",
"enteCanEncryptAndPreserveFilesOnlyIfYouGrant": "只有您授予访问权限ente 才能加密和保存文件",

View file

@ -27,14 +27,16 @@ class LocalFileUpdateService {
late FileUpdationDB _fileUpdationDB;
late SharedPreferences _prefs;
late Logger _logger;
static const isLocationMigrationComplete = "fm_isLocationMigrationComplete";
static const isLocalImportDone = "fm_IsLocalImportDone";
static const isBadCreationTimeImportDone = 'fm_badCreationTime';
static const isBadCreationTimeMigrationComplete =
'fm_badCreationTimeCompleted';
static const isMissingLocationV2ImportDone = "fm_missingLocationV2ImportDone";
static const isMissingLocationV2MigrationDone =
"fm_missingLocationV2MigrationDone";
static const isBadLocationCordImportDone = "fm_badLocationImportDone";
static const isBadLocationCordMigrationDone = "fm_badLocationMigrationDone";
Completer<void>? _existingMigration;
LocalFileUpdateService._privateConstructor() {
@ -64,6 +66,7 @@ class LocalFileUpdateService {
if (Platform.isAndroid) {
await _migrationForFixingBadCreationTime();
await _migrationFilesWithMissingLocationV2();
await _migrationFilesWithBadLocationCord();
}
} catch (e, s) {
_logger.severe('failed to perform migration', e, s);
@ -234,7 +237,7 @@ class LocalFileUpdateService {
);
if (localIDs.isEmpty) {
// everything is done
await _prefs.setBool(isBadCreationTimeMigrationComplete, true);
await _prefs.setBool(isMissingLocationV2MigrationDone, true);
return;
}
@ -305,4 +308,97 @@ class LocalFileUpdateService {
watch.log("imported ${localIDs.length} files");
await _prefs.setBool(isMissingLocationV2ImportDone, true);
}
Future<void> _migrationFilesWithBadLocationCord() async {
if (_prefs.containsKey(isBadLocationCordMigrationDone)) {
return;
}
await _importForBadLocationCord();
const int singleRunLimit = 10;
final List<String> processedIDs = [];
try {
final localIDs = await _fileUpdationDB.getLocalIDsForPotentialReUpload(
singleRunLimit,
FileUpdationDB.badLocationCord,
);
if (localIDs.isEmpty) {
// everything is done
await _prefs.setBool(isBadLocationCordMigrationDone, true);
return;
}
final List<ente.File> enteFiles = await FilesDB.instance
.getFilesForLocalIDs(localIDs, Configuration.instance.getUserID()!);
// fine localIDs which are not present in enteFiles
final List<String> missingLocalIDs = [];
for (String localID in localIDs) {
if (enteFiles.firstWhereOrNull((e) => e.localID == localID) == null) {
missingLocalIDs.add(localID);
}
}
processedIDs.addAll(missingLocalIDs);
final List<ente.File> remoteFilesToUpdate = [];
final Map<int, Map<String, double>> fileIDToUpdateMetadata = {};
for (ente.File file in enteFiles) {
final Location? location = await tryLocationFromExif(file);
if (location != null &&
(location.latitude ?? 0) != 0.0 &&
(location.longitude ?? 0) != 0.0) {
// check if the location is already correct
if (file.location != null &&
file.location?.longitude == location.latitude &&
file.location?.longitude == location.longitude) {
processedIDs.add(file.localID!);
} else {
remoteFilesToUpdate.add(file);
fileIDToUpdateMetadata[file.uploadedFileID!] = {
pubMagicKeyLat: location.latitude!,
pubMagicKeyLong: location.longitude!
};
}
} else if (file.localID != null) {
processedIDs.add(file.localID!);
}
}
if (remoteFilesToUpdate.isNotEmpty) {
await FileMagicService.instance.updatePublicMagicMetadata(
remoteFilesToUpdate,
null,
metadataUpdateMap: fileIDToUpdateMetadata,
);
for (ente.File file in remoteFilesToUpdate) {
if (file.localID != null) {
processedIDs.add(file.localID!);
}
}
}
} catch (e) {
_logger.severe("Failed to fix bad location cord", e);
} finally {
await _fileUpdationDB.deleteByLocalIDs(
processedIDs,
FileUpdationDB.badLocationCord,
);
}
}
Future<void> _importForBadLocationCord() async {
if (_prefs.containsKey(isBadLocationCordImportDone)) {
return;
}
_logger.info('_importForBadLocationCord');
final EnteWatch watch = EnteWatch("_importForBadLocationCord");
final int ownerID = Configuration.instance.getUserID()!;
final List<String> localIDs = await FilesDB.instance
.getFilesWithLocationUploadedBtw20AprTo15May2023(ownerID);
await _fileUpdationDB.insertMultiple(
localIDs,
FileUpdationDB.badLocationCord,
);
watch.log("imported ${localIDs.length} files");
await _prefs.setBool(isBadLocationCordImportDone, true);
}
}

View file

@ -15,6 +15,7 @@ import 'package:photos/models/search/album_search_result.dart';
import 'package:photos/models/search/generic_search_result.dart';
import 'package:photos/models/search/search_result.dart';
import 'package:photos/services/collections_service.dart';
import "package:photos/services/feature_flag_service.dart";
import "package:photos/services/location_service.dart";
import "package:photos/states/location_screen_state.dart";
import "package:photos/ui/viewer/location/location_screen.dart";
@ -233,6 +234,8 @@ class SearchService {
final locationTagEntities =
(await LocationService.instance.getLocationTags());
final Map<LocalEntity<LocationTag>, List<File>> result = {};
final bool showNoLocationTag = query.length > 2 &&
"No Location Tag".toLowerCase().startsWith(query.toLowerCase());
final List<GenericSearchResult> searchResults = [];
@ -241,7 +244,7 @@ class SearchService {
result[tag] = [];
}
}
if (result.isEmpty) {
if (result.isEmpty && !showNoLocationTag) {
return searchResults;
}
final allFiles = await _getAllFiles();
@ -258,6 +261,35 @@ class SearchService {
}
}
}
if (showNoLocationTag) {
_logger.fine("finding photos with no location");
// find files that have location but the file's location is not inside
// any location tag
final noLocationTagFiles = allFiles.where((file) {
if (!file.hasLocation) {
return false;
}
for (LocalEntity<LocationTag> tag in locationTagEntities) {
if (LocationService.instance.isFileInsideLocationTag(
tag.item.centerPoint,
file.location!,
tag.item.radius,
)) {
return false;
}
}
return true;
}).toList();
if (noLocationTagFiles.isNotEmpty) {
searchResults.add(
GenericSearchResult(
ResultType.fileType,
"No Location Tag",
noLocationTagFiles,
),
);
}
}
for (MapEntry<LocalEntity<LocationTag>, List<File>> entry
in result.entries) {
if (entry.value.isNotEmpty) {

View file

@ -221,13 +221,6 @@ class _SearchWidgetState extends State<SearchWidget> {
await _searchService.getCollectionSearchResults(query);
allResults.addAll(collectionResults);
// if (FeatureFlagService.instance.isInternalUserOrDebugBuild() &&
// query.startsWith("l:")) {
// final locationResults = await _searchService
// .getLocationSearchResults(query.replaceAll("l:", ""));
// allResults.addAll(locationResults);
// }
final monthResults = await _searchService.getMonthSearchResults(query);
allResults.addAll(monthResults);

View file

@ -12,7 +12,7 @@ description: ente photos application
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.7.43+443
version: 0.7.44+444
environment:
sdk: '>=2.17.0 <3.0.0'

41
scripts/bump_version.sh Executable file
View file

@ -0,0 +1,41 @@
#!/bin/bash
# Exit immediately if a command exits with a non-zero status
set -e
# Go to the project root directory
cd "$(dirname "$0")/.."
# Check that the current branch is main
if [[ $(git rev-parse --abbrev-ref HEAD) != "main" ]]; then
echo "Error: Not on main branch"
exit 1
fi
# Check that there are no uncommitted changes
if [[ $(git diff-index --quiet HEAD --) != 0 ]]; then
echo "Error: There are uncommitted changes"
exit 1
fi
# Pull the latest changes from main branch
git pull origin main
# Create a new branch with the current date and time as a suffix
new_branch="bump-version-$(date +'%Y%m%d%H%M%S')"
git checkout -b "$new_branch"
# Find the version line in pubspec.yaml
version_line=$(grep -E '^version:' pubspec.yaml)
# Extract and bump the version number and code
new_version=$(echo $version_line | awk -F '[.+]' '{printf "version: 0.%s.%d+%d", $2, $3+1, $4+1}')
# Replace the version line in pubspec.yaml (macOS compatible)
sed -i '' "s/$version_line/$new_version/" pubspec.yaml
# Commit the version bump with new_version in the commit message
git add pubspec.yaml
git commit -m "Bump version to $new_version"
gh pr create --fill -r ashilkn --base main