diff --git a/crowdin.yml b/crowdin.yml index a8dc81708..d28404d5c 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -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 diff --git a/fastlane/metadata/ios/es/description.txt b/fastlane/metadata/ios/es/description.txt new file mode 100644 index 000000000..90ad46cc1 --- /dev/null +++ b/fastlane/metadata/ios/es/description.txt @@ -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 diff --git a/fastlane/metadata/ios/es/keywords.txt b/fastlane/metadata/ios/es/keywords.txt new file mode 100644 index 000000000..c40c3b188 --- /dev/null +++ b/fastlane/metadata/ios/es/keywords.txt @@ -0,0 +1 @@ +fotos,fotografía,familia,privacidad,nube,copia de seguridad,vídeos,foto,encriptación,almacenamiento,álbum,alternativo diff --git a/fastlane/metadata/ios/es/name.txt b/fastlane/metadata/ios/es/name.txt new file mode 100644 index 000000000..1f84427c9 --- /dev/null +++ b/fastlane/metadata/ios/es/name.txt @@ -0,0 +1 @@ +ente Fotos diff --git a/fastlane/metadata/ios/es/subtitle.txt b/fastlane/metadata/ios/es/subtitle.txt new file mode 100644 index 000000000..bec346ddb --- /dev/null +++ b/fastlane/metadata/ios/es/subtitle.txt @@ -0,0 +1 @@ +Almacenamiento de fotos encriptado diff --git a/fastlane/metadata/ios/zh/description.txt b/fastlane/metadata/ios/zh/description.txt new file mode 100644 index 000000000..c0aaf66c2 --- /dev/null +++ b/fastlane/metadata/ios/zh/description.txt @@ -0,0 +1,33 @@ +Ente 是一个简单的应用,可以自动备份和整理您的照片和视频。 + +如果您一直在寻找保护隐私的替代方案来保存您的记忆,那么您来对地方了。 使用 Ente,它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。 + +我们拥有跨所有平台的应用程序,您的照片将以端到端加密 (e2ee) 方式在所有设备之间无缝同步。 + +Ente 也使得与您的亲人分享您的相册变得简单。 您可以直接与其他Ente 用户共享,端到端加密,或公开链接共享。 您可以直接与其他Ente 用户共享,端到端加密,或公开链接共享。 + +您的加密数据存储在多个地点,包括巴黎的一个空洞。 我们认真对待子孙后代,并确保您回忆比您长寿。 + +我们来这里是为了使最安全的照片应用成为新的应用程序,来加入我们的旅程! + +特色 +- 原始质量备份,因为每个像素都是重要的 +- 家庭计划,您可以与家人共享存储 +- 共享文件夹,如果您想让您的伙伴享受您的“摄像头”点击 +- 相册链接,可以用密码保护并设置为过期 +- 能够通过移除已经安全备份的文件释放空间 +- 图像编辑器,添加收尾工作 +- 收藏、隐藏和恢复您的内存,因为它们是宝贵的 +- 从所有主要存储供应商导入单击文件 +- 黑暗主题,因为您的照片看起来很好 +- 2FA,3FA,生物鉴别认证 +- 还有更多的LOT! + +价格 +我们不会永远提供免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente.io找到更多信息。 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente.io找到更多信息。 + +支持 +我们对提供人的支持感到自豪。 我们对提供人的支持感到自豪。 如果您是我们的付费客户,您可以联系Team@ente.io并期待我们的团队在24小时内做出回应。 + +条款 +https://ente.io/terms diff --git a/fastlane/metadata/ios/zh/keywords.txt b/fastlane/metadata/ios/zh/keywords.txt new file mode 100644 index 000000000..d5697a19c --- /dev/null +++ b/fastlane/metadata/ios/zh/keywords.txt @@ -0,0 +1 @@ +照片,摄影,家庭,隐私,云端,备份,视频,照片,加密,储存,相册,选择 diff --git a/fastlane/metadata/ios/zh/name.txt b/fastlane/metadata/ios/zh/name.txt new file mode 100644 index 000000000..3725f8ebb --- /dev/null +++ b/fastlane/metadata/ios/zh/name.txt @@ -0,0 +1 @@ +ente 照片 diff --git a/fastlane/metadata/ios/zh/subtitle.txt b/fastlane/metadata/ios/zh/subtitle.txt new file mode 100644 index 000000000..efaec9293 --- /dev/null +++ b/fastlane/metadata/ios/zh/subtitle.txt @@ -0,0 +1 @@ +加密照片存储 diff --git a/fastlane/metadata/playstore/en-US/video.txt b/fastlane/metadata/playstore/en-US/video.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/fastlane/metadata/playstore/es/full_description.txt b/fastlane/metadata/playstore/es/full_description.txt new file mode 100644 index 000000000..1e10f7250 --- /dev/null +++ b/fastlane/metadata/playstore/es/full_description.txt @@ -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. \ No newline at end of file diff --git a/fastlane/metadata/playstore/es/short_description.txt b/fastlane/metadata/playstore/es/short_description.txt new file mode 100644 index 000000000..3e101c447 --- /dev/null +++ b/fastlane/metadata/playstore/es/short_description.txt @@ -0,0 +1 @@ +Almacenamiento de fotos encriptado - copias de seguridad, organiza y comprte tus fotos y vídeos \ No newline at end of file diff --git a/fastlane/metadata/playstore/es/title.txt b/fastlane/metadata/playstore/es/title.txt new file mode 100644 index 000000000..785d16b51 --- /dev/null +++ b/fastlane/metadata/playstore/es/title.txt @@ -0,0 +1 @@ +ente Fotos \ No newline at end of file diff --git a/fastlane/metadata/playstore/zh/full_description.txt b/fastlane/metadata/playstore/zh/full_description.txt new file mode 100644 index 000000000..88d3c20ad --- /dev/null +++ b/fastlane/metadata/playstore/zh/full_description.txt @@ -0,0 +1,30 @@ +Ente 是一个简单的应用,可以自动备份和整理您的照片和视频。 + +如果您一直在寻找保护隐私的替代方案来保存您的记忆,那么您来对地方了。 使用 Ente,它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。 + +我们拥有跨 Android、iOS、Web 和桌面的应用程序,您的照片将以端到端加密 (e2ee) 方式在所有设备之间无缝同步。 + +Ente 也使得与您的亲人分享您的相册变得简单。 您可以直接与其他Ente 用户共享,端到端加密,或公开链接共享。 您可以直接与其他Ente 用户共享,端到端加密,或公开链接共享。 + +您的加密数据存储在多个地点,包括巴黎的一个空洞。 我们认真对待子孙后代,并确保您回忆比您长寿。 + +我们来这里是为了使最安全的照片应用成为新的应用程序,来加入我们的旅程! + +✨ 特色 +- 原始质量备份,因为每个像素都是重要的 +- 家庭计划,您可以与家人共享存储 +- 共享文件夹,如果您想让您的伙伴享受您的“摄像头”点击 +- 相册链接,可以用密码保护并设置为过期 +- 能够通过移除已经安全备份的文件释放空间 +- 图像编辑器,添加收尾工作 +- 收藏、隐藏和恢复您的内存,因为它们是宝贵的 +- 单击从谷歌、苹果、您的硬盘和更多的软件导入 +- 黑暗主题,因为您的照片看起来很好 +- 2FA,3FA,生物鉴别认证 +- 还有更多的LOT! + +💲 价格 +我们不会永远提供免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente.io找到更多信息。 相反,我们提供您可以自由分享的负担得起的计划。 您可以在 ente.io找到更多信息。 + +🙋 支持 +我们对提供人的支持感到自豪。 我们对提供人的支持感到自豪。 如果您是我们的付费客户,您可以联系Team@ente.io并期待我们的团队在24小时内做出回应。 \ No newline at end of file diff --git a/fastlane/metadata/playstore/zh/short_description.txt b/fastlane/metadata/playstore/zh/short_description.txt new file mode 100644 index 000000000..f4c21f246 --- /dev/null +++ b/fastlane/metadata/playstore/zh/short_description.txt @@ -0,0 +1 @@ +加密照片存储 - 备份、整理和分享您的照片和视频 \ No newline at end of file diff --git a/fastlane/metadata/playstore/zh/title.txt b/fastlane/metadata/playstore/zh/title.txt new file mode 100644 index 000000000..8ad13e2c9 --- /dev/null +++ b/fastlane/metadata/playstore/zh/title.txt @@ -0,0 +1 @@ +ente 照片 \ No newline at end of file diff --git a/lib/db/file_updation_db.dart b/lib/db/file_updation_db.dart index 08acf2529..5d69fe8b4 100644 --- a/lib/db/file_updation_db.dart +++ b/lib/db/file_updation_db.dart @@ -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 _createTable() { return [ diff --git a/lib/db/files_db.dart b/lib/db/files_db.dart index ab6b34d88..4a8aaec4a 100644 --- a/lib/db/files_db.dart +++ b/lib/db/files_db.dart @@ -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> 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> getFilesForLocalIDs( diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index e41255a63..44da4c2c8 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -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: [], ); } diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index de087e693..35efb963d 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -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", diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index fc6ea37d3..6554002e2 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -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", diff --git a/lib/l10n/intl_zh.arb b/lib/l10n/intl_zh.arb index 9b640f20a..a09428f86 100644 --- a/lib/l10n/intl_zh.arb +++ b/lib/l10n/intl_zh.arb @@ -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 才能加密和保存文件", diff --git a/lib/services/local_file_update_service.dart b/lib/services/local_file_update_service.dart index cb3211004..7cdec9c4a 100644 --- a/lib/services/local_file_update_service.dart +++ b/lib/services/local_file_update_service.dart @@ -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? _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 _migrationFilesWithBadLocationCord() async { + if (_prefs.containsKey(isBadLocationCordMigrationDone)) { + return; + } + await _importForBadLocationCord(); + const int singleRunLimit = 10; + final List processedIDs = []; + try { + final localIDs = await _fileUpdationDB.getLocalIDsForPotentialReUpload( + singleRunLimit, + FileUpdationDB.badLocationCord, + ); + if (localIDs.isEmpty) { + // everything is done + await _prefs.setBool(isBadLocationCordMigrationDone, true); + return; + } + + final List enteFiles = await FilesDB.instance + .getFilesForLocalIDs(localIDs, Configuration.instance.getUserID()!); + // fine localIDs which are not present in enteFiles + final List missingLocalIDs = []; + for (String localID in localIDs) { + if (enteFiles.firstWhereOrNull((e) => e.localID == localID) == null) { + missingLocalIDs.add(localID); + } + } + processedIDs.addAll(missingLocalIDs); + + final List remoteFilesToUpdate = []; + final Map> 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 _importForBadLocationCord() async { + if (_prefs.containsKey(isBadLocationCordImportDone)) { + return; + } + _logger.info('_importForBadLocationCord'); + final EnteWatch watch = EnteWatch("_importForBadLocationCord"); + final int ownerID = Configuration.instance.getUserID()!; + final List localIDs = await FilesDB.instance + .getFilesWithLocationUploadedBtw20AprTo15May2023(ownerID); + + await _fileUpdationDB.insertMultiple( + localIDs, + FileUpdationDB.badLocationCord, + ); + watch.log("imported ${localIDs.length} files"); + await _prefs.setBool(isBadLocationCordImportDone, true); + } } diff --git a/lib/services/search_service.dart b/lib/services/search_service.dart index d4d21e221..d65451d6c 100644 --- a/lib/services/search_service.dart +++ b/lib/services/search_service.dart @@ -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, List> result = {}; + final bool showNoLocationTag = query.length > 2 && + "No Location Tag".toLowerCase().startsWith(query.toLowerCase()); final List 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 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, List> entry in result.entries) { if (entry.value.isNotEmpty) { diff --git a/lib/ui/viewer/search/search_widget.dart b/lib/ui/viewer/search/search_widget.dart index ed206f486..ea1513e08 100644 --- a/lib/ui/viewer/search/search_widget.dart +++ b/lib/ui/viewer/search/search_widget.dart @@ -221,13 +221,6 @@ class _SearchWidgetState extends State { 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); diff --git a/pubspec.yaml b/pubspec.yaml index cbf0dd179..2b2e436ac 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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' diff --git a/scripts/bump_version.sh b/scripts/bump_version.sh new file mode 100755 index 000000000..b147e5e15 --- /dev/null +++ b/scripts/bump_version.sh @@ -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 \ No newline at end of file