From f910da0964e8217b59aa3b3f50cd987a092e5cf4 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 20 Nov 2023 13:28:27 +0530 Subject: [PATCH 01/10] Handle loginKey and keyDerivation err during SRP based login --- lib/core/errors.dart | 4 +- lib/generated/intl/messages_cs.dart | 1 + lib/generated/intl/messages_de.dart | 1 + lib/generated/intl/messages_en.dart | 9 +- lib/generated/intl/messages_es.dart | 1 + lib/generated/intl/messages_fr.dart | 66 +++++- lib/generated/intl/messages_it.dart | 1 + lib/generated/intl/messages_ko.dart | 1 + lib/generated/intl/messages_nl.dart | 1 + lib/generated/intl/messages_no.dart | 1 + lib/generated/intl/messages_pl.dart | 1 + lib/generated/intl/messages_pt.dart | 1 + lib/generated/intl/messages_zh.dart | 42 +++- lib/generated/l10n.dart | 24 ++- lib/l10n/intl_en.arb | 4 +- lib/services/user_service.dart | 201 +++++++----------- .../account/login_pwd_verification_page.dart | 100 ++++++++- lib/utils/crypto_util.dart | 151 +++++++------ 18 files changed, 400 insertions(+), 210 deletions(-) diff --git a/lib/core/errors.dart b/lib/core/errors.dart index 634988e0d..a9e175b88 100644 --- a/lib/core/errors.dart +++ b/lib/core/errors.dart @@ -7,8 +7,8 @@ enum InvalidReason { livePhotoVideoMissing, thumbnailMissing, unknown, - } + extension InvalidReasonExn on InvalidReason { bool get isLivePhotoErr => this == InvalidReason.livePhotoToImageTypeChanged || @@ -73,6 +73,8 @@ class InvalidStateError extends AssertionError { class KeyDerivationError extends Error {} +class LoginKeyDerivationError extends Error {} + class SrpSetupNotCompleteError extends Error {} class SharingNotPermittedForFreeAccountsError extends Error {} diff --git a/lib/generated/intl/messages_cs.dart b/lib/generated/intl/messages_cs.dart index 815bedb4a..a0b3b9f7d 100644 --- a/lib/generated/intl/messages_cs.dart +++ b/lib/generated/intl/messages_cs.dart @@ -24,6 +24,7 @@ class MessageLookup extends MessageLookupByLibrary { static Map _notInlinedMessages(_) => { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Add to hidden album"), + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "deleteConfirmDialogBody": MessageLookupByLibrary.simpleMessage( "This account is linked to other ente apps, if you use any.\\n\\nYour uploaded data, across all ente apps, will be scheduled for deletion, and your account will be permanently deleted."), "fileTypes": MessageLookupByLibrary.simpleMessage("File types"), diff --git a/lib/generated/intl/messages_de.dart b/lib/generated/intl/messages_de.dart index 1c31ebad2..1b935485f 100644 --- a/lib/generated/intl/messages_de.dart +++ b/lib/generated/intl/messages_de.dart @@ -442,6 +442,7 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Support kontaktieren"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Weiter"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage( "Mit kostenloser Testversion fortfahren"), diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 5cbdf629e..ad75c50ab 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -441,6 +441,7 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Contact support"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "contents": MessageLookupByLibrary.simpleMessage("Contents"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continue"), "continueOnFreeTrial": @@ -879,6 +880,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("No hidden photos or videos"), "noImagesWithLocation": MessageLookupByLibrary.simpleMessage("No images with location"), + "noInternetConnection": + MessageLookupByLibrary.simpleMessage("No internet connection"), "noPhotosAreBeingBackedUpRightNow": MessageLookupByLibrary.simpleMessage( "No photos are being backed up right now"), @@ -926,7 +929,6 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailedTalkToProvider": m33, "paymentFailedWithReason": m34, "pendingSync": MessageLookupByLibrary.simpleMessage("Pending sync"), - "people": MessageLookupByLibrary.simpleMessage("People"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage("People using your code"), "permDeleteWarning": MessageLookupByLibrary.simpleMessage( @@ -950,6 +952,9 @@ class MessageLookup extends MessageLookupByLibrary { "playStoreFreeTrialValidTill": m35, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore subscription"), + "pleaseCheckYourInternetConnectionAndTryAgain": + MessageLookupByLibrary.simpleMessage( + "Please check your internet connection and try again."), "pleaseContactSupportAndWeWillBeHappyToHelp": MessageLookupByLibrary.simpleMessage( "Please contact support@ente.io and we will be happy to help!"), @@ -1120,7 +1125,7 @@ class MessageLookup extends MessageLookupByLibrary { "Albums, file names, and types"), "searchHint4": MessageLookupByLibrary.simpleMessage("Location"), "searchHint5": MessageLookupByLibrary.simpleMessage( - "Coming soon: Photo contents, faces"), + "Coming soon: Faces & magic search ✨"), "searchHintText": MessageLookupByLibrary.simpleMessage( "Albums, months, days, years, ..."), "searchLocationEmptySection": MessageLookupByLibrary.simpleMessage( diff --git a/lib/generated/intl/messages_es.dart b/lib/generated/intl/messages_es.dart index 9d6829d71..499277175 100644 --- a/lib/generated/intl/messages_es.dart +++ b/lib/generated/intl/messages_es.dart @@ -398,6 +398,7 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Contactar con soporte"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuar"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage( "Continuar con el plan gratuito"), diff --git a/lib/generated/intl/messages_fr.dart b/lib/generated/intl/messages_fr.dart index 264b5dd96..79391df74 100644 --- a/lib/generated/intl/messages_fr.dart +++ b/lib/generated/intl/messages_fr.dart @@ -140,6 +140,9 @@ class MessageLookup extends MessageLookupByLibrary { static String m41(endDate) => "Renouvellement le ${endDate}"; + static String m64(count) => + "${Intl.plural(count, one: '${count} résultat trouvé', other: '${count} résultats trouvés')}"; + static String m42(count) => "${count} sélectionné(s)"; static String m43(count, yourCount) => @@ -189,6 +192,8 @@ class MessageLookup extends MessageLookupByLibrary { static String m59(count) => "${Intl.plural(count, zero: '0 jour', one: '1 jour', other: '${count} jours')}"; + static String m65(endDate) => "Valable jusqu\'au ${endDate}"; + static String m60(email) => "Vérifier ${email}"; static String m61(email) => @@ -223,6 +228,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ajouter la localisation"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Ajouter"), "addMore": MessageLookupByLibrary.simpleMessage("Ajouter Plus"), + "addNew": MessageLookupByLibrary.simpleMessage("Ajouter un nouveau"), + "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage( + "Détails des modules complémentaires"), + "addOns": + MessageLookupByLibrary.simpleMessage("Modules complémentaires"), "addPhotos": MessageLookupByLibrary.simpleMessage("Ajouter des photos"), "addSelected": MessageLookupByLibrary.simpleMessage("Ajouter la sélection"), @@ -233,6 +243,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ajouter à un album masqué"), "addViewer": MessageLookupByLibrary.simpleMessage("Ajouter un observateur"), + "addYourPhotosNow": MessageLookupByLibrary.simpleMessage( + "Ajoutez vos photos maintenant"), "addedAs": MessageLookupByLibrary.simpleMessage("Ajouté comme"), "addedBy": m1, "addedSuccessfullyTo": m2, @@ -356,6 +368,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Paramètres de la sauvegarde"), "backupVideos": MessageLookupByLibrary.simpleMessage("Sauvegarde des vidéos"), + "blackFridaySale": + MessageLookupByLibrary.simpleMessage("Offre Black Friday"), "blog": MessageLookupByLibrary.simpleMessage("Blog"), "cachedData": MessageLookupByLibrary.simpleMessage("Données mises en cache"), @@ -446,6 +460,8 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Contacter l\'assistance"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), + "contents": MessageLookupByLibrary.simpleMessage("Contenus"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuer"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage( "Poursuivre avec la version d\'essai gratuite"), @@ -510,7 +526,7 @@ class MessageLookup extends MessageLookupByLibrary { "Ceci supprimera tous les albums vides. Ceci est utile lorsque vous voulez réduire l\'encombrement dans votre liste d\'albums."), "deleteAll": MessageLookupByLibrary.simpleMessage("Tout Supprimer"), "deleteConfirmDialogBody": MessageLookupByLibrary.simpleMessage( - "This account is linked to other ente apps, if you use any.\\n\\nYour uploaded data, across all ente apps, will be scheduled for deletion, and your account will be permanently deleted."), + "Ce compte est lié à d\'autres applications ente, si vous en utilisez une.\\n\\nVos données téléchargées, dans toutes les applications ente, seront planifiées pour suppression, et votre compte sera définitivement supprimé."), "deleteEmailRequest": MessageLookupByLibrary.simpleMessage( "Veuillez envoyer un e-mail à account-deletion@ente.io à partir de votre adresse e-mail enregistrée."), "deleteEmptyAlbums": @@ -658,6 +674,7 @@ class MessageLookup extends MessageLookupByLibrary { "exportLogs": MessageLookupByLibrary.simpleMessage("Exporter les logs"), "exportYourData": MessageLookupByLibrary.simpleMessage("Exportez vos données"), + "faces": MessageLookupByLibrary.simpleMessage("Visages"), "failedToApplyCode": MessageLookupByLibrary.simpleMessage( "Impossible d\'appliquer le code"), "failedToCancel": @@ -689,7 +706,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ajouter une description..."), "fileSavedToGallery": MessageLookupByLibrary.simpleMessage( "Fichier enregistré dans la galerie"), - "fileTypes": MessageLookupByLibrary.simpleMessage("File types"), + "fileTypes": MessageLookupByLibrary.simpleMessage("Types de fichiers"), + "fileTypesAndNames": + MessageLookupByLibrary.simpleMessage("Types et noms de fichiers"), "filesBackedUpFromDevice": m19, "filesBackedUpInAlbum": m20, "filesDeleted": @@ -729,6 +748,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Accorder la permission"), "groupNearbyPhotos": MessageLookupByLibrary.simpleMessage( "Grouper les photos à proximité"), + "hearUsExplanation": MessageLookupByLibrary.simpleMessage( + "Nous ne suivons pas les installations d\'applications. Il serait utile que vous nous disiez comment vous nous avez trouvés !"), + "hearUsWhereTitle": MessageLookupByLibrary.simpleMessage( + "Comment avez-vous entendu parler de Ente? (facultatif)"), "hidden": MessageLookupByLibrary.simpleMessage("Masqué"), "hide": MessageLookupByLibrary.simpleMessage("Masquer"), "hiding": MessageLookupByLibrary.simpleMessage("Masquage en cours..."), @@ -810,6 +833,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkHasExpired": MessageLookupByLibrary.simpleMessage("Le lien a expiré"), "linkNeverExpires": MessageLookupByLibrary.simpleMessage("Jamais"), + "livePhotos": MessageLookupByLibrary.simpleMessage("Photos en direct"), "loadMessage1": MessageLookupByLibrary.simpleMessage( "Vous pouvez partager votre abonnement avec votre famille"), "loadMessage2": MessageLookupByLibrary.simpleMessage( @@ -876,7 +900,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Sécurité moyenne"), "modifyYourQueryOrTrySearchingFor": MessageLookupByLibrary.simpleMessage( - "Modify your query, or try searching for"), + "Modifiez votre requête, ou essayez de rechercher"), + "moments": MessageLookupByLibrary.simpleMessage("Souvenirs"), "monthly": MessageLookupByLibrary.simpleMessage("Mensuel"), "moveItem": m30, "moveToAlbum": @@ -966,9 +991,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Supprimer définitivement"), "permanentlyDeleteFromDevice": MessageLookupByLibrary.simpleMessage( "Supprimer définitivement de l\'appareil ?"), + "photoDescriptions": + MessageLookupByLibrary.simpleMessage("Descriptions de la photo"), "photoGridSize": MessageLookupByLibrary.simpleMessage("Taille de la grille photo"), "photoSmallCase": MessageLookupByLibrary.simpleMessage("photo"), + "photos": MessageLookupByLibrary.simpleMessage("Photos"), "photosAddedByYouWillBeRemovedFromTheAlbum": MessageLookupByLibrary.simpleMessage( "Les photos ajoutées par vous seront retirées de l\'album"), @@ -1136,12 +1164,36 @@ class MessageLookup extends MessageLookupByLibrary { "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( "Scannez ce code-barres avec\nvotre application d\'authentification"), + "searchAlbumsEmptySection": + MessageLookupByLibrary.simpleMessage("Albums"), "searchByAlbumNameHint": MessageLookupByLibrary.simpleMessage("Nom de l\'album"), "searchByExamples": MessageLookupByLibrary.simpleMessage( "• Noms d\'albums (par exemple \"Caméra\")\n• Types de fichiers (par exemple \"Vidéos\", \".gif\")\n• Années et mois (par exemple \"2022\", \"Janvier\")\n• Vacances (par exemple \"Noël\")\n• Descriptions de photos (par exemple \"#fun\")"), + "searchCaptionEmptySection": MessageLookupByLibrary.simpleMessage( + "Ajoutez des descriptions comme \"#trip\" dans les infos photo pour les retrouver ici plus rapidement"), + "searchDatesEmptySection": MessageLookupByLibrary.simpleMessage( + "Recherche par date, mois ou année"), + "searchFaceEmptySection": MessageLookupByLibrary.simpleMessage( + "Trouver toutes les photos d\'une personne"), + "searchFileTypesAndNamesEmptySection": + MessageLookupByLibrary.simpleMessage("Types et noms de fichiers"), + "searchHint1": MessageLookupByLibrary.simpleMessage( + "Recherche rapide, sur l\'appareil"), + "searchHint2": MessageLookupByLibrary.simpleMessage( + "Dates des photos, descriptions"), + "searchHint3": MessageLookupByLibrary.simpleMessage( + "Albums, noms de fichiers et types"), + "searchHint4": MessageLookupByLibrary.simpleMessage("Emplacement"), + "searchHint5": MessageLookupByLibrary.simpleMessage( + "Bientôt: Visages & recherche magique ✨"), "searchHintText": MessageLookupByLibrary.simpleMessage( "Albums, mois, jours, années, ..."), + "searchLocationEmptySection": MessageLookupByLibrary.simpleMessage( + "Grouper les photos qui sont prises dans un certain angle d\'une photo"), + "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( + "Invitez des gens, et vous verrez ici toutes les photos qu\'ils partagent"), + "searchResultCount": m64, "security": MessageLookupByLibrary.simpleMessage("Sécurité"), "selectAlbum": MessageLookupByLibrary.simpleMessage("Sélectionner album"), @@ -1400,6 +1452,8 @@ class MessageLookup extends MessageLookupByLibrary { "upgrade": MessageLookupByLibrary.simpleMessage("Améliorer"), "uploadingFilesToAlbum": MessageLookupByLibrary.simpleMessage( "Envoi des fichiers vers l\'album..."), + "upto50OffUntil4thDec": MessageLookupByLibrary.simpleMessage( + "Jusqu\'à 50% de réduction, jusqu\'au 4ème déc."), "usableReferralStorageInfo": MessageLookupByLibrary.simpleMessage( "Le stockage utilisable est limité par votre offre actuelle. Le stockage excédentaire deviendra automatiquement utilisable lorsque vous mettez à niveau votre offre."), "usePublicLinksForPeopleNotOnEnte": MessageLookupByLibrary.simpleMessage( @@ -1409,6 +1463,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage( "Utiliser la photo sélectionnée"), "usedSpace": MessageLookupByLibrary.simpleMessage("Mémoire utilisée"), + "validTill": m65, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "La vérification a échouée, veuillez réessayer"), @@ -1426,8 +1481,11 @@ class MessageLookup extends MessageLookupByLibrary { "verifyingRecoveryKey": MessageLookupByLibrary.simpleMessage( "Vérification de la clé de récupération..."), "videoSmallCase": MessageLookupByLibrary.simpleMessage("vidéo"), + "videos": MessageLookupByLibrary.simpleMessage("Vidéos"), "viewActiveSessions": MessageLookupByLibrary.simpleMessage( "Afficher les sessions actives"), + "viewAddOnButton": MessageLookupByLibrary.simpleMessage( + "Afficher les modules complémentaires"), "viewAll": MessageLookupByLibrary.simpleMessage("Tout afficher"), "viewAllExifData": MessageLookupByLibrary.simpleMessage( "Visualiser toutes les données EXIF"), @@ -1481,7 +1539,7 @@ class MessageLookup extends MessageLookupByLibrary { "youHaveSuccessfullyFreedUp": m63, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Votre compte a été supprimé"), - "yourMap": MessageLookupByLibrary.simpleMessage("Your map"), + "yourMap": MessageLookupByLibrary.simpleMessage("Votre carte"), "yourPlanWasSuccessfullyDowngraded": MessageLookupByLibrary.simpleMessage( "Votre plan a été rétrogradé avec succès"), diff --git a/lib/generated/intl/messages_it.dart b/lib/generated/intl/messages_it.dart index 1659be2cb..359f6d569 100644 --- a/lib/generated/intl/messages_it.dart +++ b/lib/generated/intl/messages_it.dart @@ -446,6 +446,7 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Contatta il supporto"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continua"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage("Continua la prova gratuita"), diff --git a/lib/generated/intl/messages_ko.dart b/lib/generated/intl/messages_ko.dart index 653419bae..7c5259342 100644 --- a/lib/generated/intl/messages_ko.dart +++ b/lib/generated/intl/messages_ko.dart @@ -24,6 +24,7 @@ class MessageLookup extends MessageLookupByLibrary { static Map _notInlinedMessages(_) => { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Add to hidden album"), + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "deleteConfirmDialogBody": MessageLookupByLibrary.simpleMessage( "This account is linked to other ente apps, if you use any.\\n\\nYour uploaded data, across all ente apps, will be scheduled for deletion, and your account will be permanently deleted."), "fileTypes": MessageLookupByLibrary.simpleMessage("File types"), diff --git a/lib/generated/intl/messages_nl.dart b/lib/generated/intl/messages_nl.dart index f2f316213..90ac6a215 100644 --- a/lib/generated/intl/messages_nl.dart +++ b/lib/generated/intl/messages_nl.dart @@ -441,6 +441,7 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Contacteer klantenservice"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Doorgaan"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage( "Doorgaan met gratis proefversie"), diff --git a/lib/generated/intl/messages_no.dart b/lib/generated/intl/messages_no.dart index 4de30a91b..d162c4550 100644 --- a/lib/generated/intl/messages_no.dart +++ b/lib/generated/intl/messages_no.dart @@ -33,6 +33,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Bekreft sletting av konto"), "confirmDeletePrompt": MessageLookupByLibrary.simpleMessage( "Ja, jeg ønsker å slette denne kontoen og all dataen dens permanent."), + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "deleteAccount": MessageLookupByLibrary.simpleMessage("Slett konto"), "deleteAccountFeedbackPrompt": MessageLookupByLibrary.simpleMessage( "Vi er lei oss for at du forlater oss. Gi oss gjerne en tilbakemelding så vi kan forbedre oss."), diff --git a/lib/generated/intl/messages_pl.dart b/lib/generated/intl/messages_pl.dart index 6fb8aa6f0..7a567715b 100644 --- a/lib/generated/intl/messages_pl.dart +++ b/lib/generated/intl/messages_pl.dart @@ -50,6 +50,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Powtórz hasło"), "contactSupport": MessageLookupByLibrary.simpleMessage( "Skontaktuj się z pomocą techniczną"), + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Kontynuuj"), "createAccount": MessageLookupByLibrary.simpleMessage("Stwórz konto"), "createNewAccount": diff --git a/lib/generated/intl/messages_pt.dart b/lib/generated/intl/messages_pt.dart index a873f19d4..9ddbbd8d9 100644 --- a/lib/generated/intl/messages_pt.dart +++ b/lib/generated/intl/messages_pt.dart @@ -136,6 +136,7 @@ class MessageLookup extends MessageLookupByLibrary { "Confirme sua chave de recuperação"), "contactSupport": MessageLookupByLibrary.simpleMessage("Falar com o suporte"), + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuar"), "copypasteThisCodentoYourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( diff --git a/lib/generated/intl/messages_zh.dart b/lib/generated/intl/messages_zh.dart index 1e62fea04..9370da75e 100644 --- a/lib/generated/intl/messages_zh.dart +++ b/lib/generated/intl/messages_zh.dart @@ -127,6 +127,9 @@ class MessageLookup extends MessageLookupByLibrary { static String m41(endDate) => "在 ${endDate} 前续费"; + static String m64(count) => + "${Intl.plural(count, other: '已找到 ${count} 个结果')}"; + static String m42(count) => "已选择 ${count} 个"; static String m43(count, yourCount) => "选择了 ${count} 个 (您的 ${yourCount} 个)"; @@ -198,6 +201,7 @@ class MessageLookup extends MessageLookupByLibrary { "addLocation": MessageLookupByLibrary.simpleMessage("添加地点"), "addLocationButton": MessageLookupByLibrary.simpleMessage("添加"), "addMore": MessageLookupByLibrary.simpleMessage("添加更多"), + "addNew": MessageLookupByLibrary.simpleMessage("新建"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("附加组件详情"), "addOns": MessageLookupByLibrary.simpleMessage("附加组件"), "addPhotos": MessageLookupByLibrary.simpleMessage("添加照片"), @@ -206,6 +210,7 @@ class MessageLookup extends MessageLookupByLibrary { "addToEnte": MessageLookupByLibrary.simpleMessage("添加到 ente"), "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("添加到隐藏相册"), "addViewer": MessageLookupByLibrary.simpleMessage("添加查看者"), + "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("立即添加您的照片"), "addedAs": MessageLookupByLibrary.simpleMessage("已添加为"), "addedBy": m1, "addedSuccessfullyTo": m2, @@ -308,6 +313,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("通过移动数据备份"), "backupSettings": MessageLookupByLibrary.simpleMessage("备份设置"), "backupVideos": MessageLookupByLibrary.simpleMessage("备份视频"), + "blackFridaySale": MessageLookupByLibrary.simpleMessage("黑色星期五特惠"), "blog": MessageLookupByLibrary.simpleMessage("博客"), "cachedData": MessageLookupByLibrary.simpleMessage("缓存数据"), "calculating": MessageLookupByLibrary.simpleMessage("正在计算..."), @@ -374,6 +380,8 @@ class MessageLookup extends MessageLookupByLibrary { "contactFamilyAdmin": m9, "contactSupport": MessageLookupByLibrary.simpleMessage("联系支持"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("联系人"), + "contents": MessageLookupByLibrary.simpleMessage("内容"), "continueLabel": MessageLookupByLibrary.simpleMessage("继续"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage("继续免费试用"), "convertToAlbum": MessageLookupByLibrary.simpleMessage("转换为相册"), @@ -535,6 +543,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("此链接已过期。请选择新的过期时间或禁用链接过期。"), "exportLogs": MessageLookupByLibrary.simpleMessage("导出日志"), "exportYourData": MessageLookupByLibrary.simpleMessage("导出您的数据"), + "faces": MessageLookupByLibrary.simpleMessage("人脸"), "failedToApplyCode": MessageLookupByLibrary.simpleMessage("无法应用代码"), "failedToCancel": MessageLookupByLibrary.simpleMessage("取消失败"), "failedToDownloadVideo": MessageLookupByLibrary.simpleMessage("视频下载失败"), @@ -558,6 +567,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("无法将文件保存到相册"), "fileInfoAddDescHint": MessageLookupByLibrary.simpleMessage("添加说明..."), "fileSavedToGallery": MessageLookupByLibrary.simpleMessage("文件已保存到相册"), + "fileTypes": MessageLookupByLibrary.simpleMessage("文件类型"), + "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("文件类型和名称"), "filesBackedUpFromDevice": m19, "filesBackedUpInAlbum": m20, "filesDeleted": MessageLookupByLibrary.simpleMessage("文件已删除"), @@ -655,6 +666,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkExpiry": MessageLookupByLibrary.simpleMessage("链接过期"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("链接已过期"), "linkNeverExpires": MessageLookupByLibrary.simpleMessage("永不"), + "livePhotos": MessageLookupByLibrary.simpleMessage("实况照片"), "loadMessage1": MessageLookupByLibrary.simpleMessage("您可以与家庭分享您的订阅"), "loadMessage2": MessageLookupByLibrary.simpleMessage("到目前为止,我们已经保存了1 000多万个回忆"), @@ -710,8 +722,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("移动端, 网页端, 桌面端"), "moderateStrength": MessageLookupByLibrary.simpleMessage("中等"), "modifyYourQueryOrTrySearchingFor": - MessageLookupByLibrary.simpleMessage( - "Modify your query, or try searching for"), + MessageLookupByLibrary.simpleMessage("修改您的查询,或尝试搜索"), + "moments": MessageLookupByLibrary.simpleMessage("瞬间"), "monthly": MessageLookupByLibrary.simpleMessage("每月"), "moveItem": m30, "moveToAlbum": MessageLookupByLibrary.simpleMessage("移动到相册"), @@ -784,8 +796,10 @@ class MessageLookup extends MessageLookupByLibrary { "permanentlyDelete": MessageLookupByLibrary.simpleMessage("永久删除"), "permanentlyDeleteFromDevice": MessageLookupByLibrary.simpleMessage("要从设备中永久删除吗?"), + "photoDescriptions": MessageLookupByLibrary.simpleMessage("照片说明"), "photoGridSize": MessageLookupByLibrary.simpleMessage("照片网格大小"), "photoSmallCase": MessageLookupByLibrary.simpleMessage("照片"), + "photos": MessageLookupByLibrary.simpleMessage("照片"), "photosAddedByYouWillBeRemovedFromTheAlbum": MessageLookupByLibrary.simpleMessage("您添加的照片将从相册中移除"), "pickCenterPoint": MessageLookupByLibrary.simpleMessage("选择中心点"), @@ -908,10 +922,29 @@ class MessageLookup extends MessageLookupByLibrary { "scanCode": MessageLookupByLibrary.simpleMessage("扫描代码"), "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage("用您的身份验证器应用\n扫描此条码"), + "searchAlbumsEmptySection": MessageLookupByLibrary.simpleMessage("相册"), "searchByAlbumNameHint": MessageLookupByLibrary.simpleMessage("相册名称"), "searchByExamples": MessageLookupByLibrary.simpleMessage( "• 相册名称(例如“相机”)\n• 文件类型(例如“视频”、“.gif”)\n• 年份和月份(例如“2022”、“一月”)\n• 假期(例如“圣诞节”)\n• 照片说明(例如“#和女儿独居,好开心啊”)"), + "searchCaptionEmptySection": MessageLookupByLibrary.simpleMessage( + "在照片信息中添加“#旅游”等描述,以便在此处快速找到它们"), + "searchDatesEmptySection": + MessageLookupByLibrary.simpleMessage("按日期搜索,月份或年份"), + "searchFaceEmptySection": + MessageLookupByLibrary.simpleMessage("查找一个人的所有照片"), + "searchFileTypesAndNamesEmptySection": + MessageLookupByLibrary.simpleMessage("文件类型和名称"), + "searchHint1": MessageLookupByLibrary.simpleMessage("在设备上快速搜索"), + "searchHint2": MessageLookupByLibrary.simpleMessage("照片日期、描述"), + "searchHint3": MessageLookupByLibrary.simpleMessage("相册、文件名和类型"), + "searchHint4": MessageLookupByLibrary.simpleMessage("位置"), + "searchHint5": MessageLookupByLibrary.simpleMessage("即将到来:面部和魔法搜索✨"), "searchHintText": MessageLookupByLibrary.simpleMessage("相册,月,日,年,..."), + "searchLocationEmptySection": + MessageLookupByLibrary.simpleMessage("在照片的一定半径内拍摄的几组照片"), + "searchPeopleEmptySection": + MessageLookupByLibrary.simpleMessage("邀请他人,您将在此看到他们分享的所有照片"), + "searchResultCount": m64, "security": MessageLookupByLibrary.simpleMessage("安全"), "selectAlbum": MessageLookupByLibrary.simpleMessage("选择相册"), "selectAll": MessageLookupByLibrary.simpleMessage("全选"), @@ -1113,6 +1146,8 @@ class MessageLookup extends MessageLookupByLibrary { "upgrade": MessageLookupByLibrary.simpleMessage("升级"), "uploadingFilesToAlbum": MessageLookupByLibrary.simpleMessage("正在将文件上传到相册..."), + "upto50OffUntil4thDec": + MessageLookupByLibrary.simpleMessage("最高五折优惠,直至12月4日。"), "usableReferralStorageInfo": MessageLookupByLibrary.simpleMessage( "可用存储空间受您当前计划的限制。 当您升级您的计划时,超出要求的存储空间将自动变为可用。"), "usePublicLinksForPeopleNotOnEnte": @@ -1133,6 +1168,7 @@ class MessageLookup extends MessageLookupByLibrary { "verifyingRecoveryKey": MessageLookupByLibrary.simpleMessage("正在验证恢复密钥..."), "videoSmallCase": MessageLookupByLibrary.simpleMessage("视频"), + "videos": MessageLookupByLibrary.simpleMessage("视频"), "viewActiveSessions": MessageLookupByLibrary.simpleMessage("查看活动会话"), "viewAddOnButton": MessageLookupByLibrary.simpleMessage("查看附加组件"), "viewAll": MessageLookupByLibrary.simpleMessage("查看全部"), @@ -1178,7 +1214,7 @@ class MessageLookup extends MessageLookupByLibrary { "youHaveSuccessfullyFreedUp": m63, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("您的账户已删除"), - "yourMap": MessageLookupByLibrary.simpleMessage("Your map"), + "yourMap": MessageLookupByLibrary.simpleMessage("您的地图"), "yourPlanWasSuccessfullyDowngraded": MessageLookupByLibrary.simpleMessage("您的计划已成功降级"), "yourPlanWasSuccessfullyUpgraded": diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 523110e70..1c2421f77 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -7995,10 +7995,10 @@ class S { ); } - /// `Coming soon: Photo contents, faces` + /// `Coming soon: Faces & magic search ✨` String get searchHint5 { return Intl.message( - 'Coming soon: Photo contents, faces', + 'Coming soon: Faces & magic search ✨', name: 'searchHint5', desc: '', args: [], @@ -8067,6 +8067,26 @@ class S { args: [], ); } + + /// `No internet connection` + String get noInternetConnection { + return Intl.message( + 'No internet connection', + name: 'noInternetConnection', + desc: '', + args: [], + ); + } + + /// `Please check your internet connection and try again.` + String get pleaseCheckYourInternetConnectionAndTryAgain { + return Intl.message( + 'Please check your internet connection and try again.', + name: 'pleaseCheckYourInternetConnectionAndTryAgain', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index f3fca6a0c..92b293cd9 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1149,5 +1149,7 @@ "@addNew": { "description": "Text to add a new item (location tag, album, caption etc)" }, - "contacts": "Contacts" + "contacts": "Contacts", + "noInternetConnection": "No internet connection", + "pleaseCheckYourInternetConnectionAndTryAgain": "Please check your internet connection and try again." } \ No newline at end of file diff --git a/lib/services/user_service.dart b/lib/services/user_service.dart index 13d085ca2..e52a69984 100644 --- a/lib/services/user_service.dart +++ b/lib/services/user_service.dart @@ -34,11 +34,10 @@ import "package:photos/ui/account/recovery_page.dart"; import 'package:photos/ui/account/two_factor_authentication_page.dart'; import 'package:photos/ui/account/two_factor_recovery_page.dart'; import 'package:photos/ui/account/two_factor_setup_page.dart'; -import "package:photos/ui/components/buttons/button_widget.dart"; +import "package:photos/ui/common/progress_dialog.dart"; import "package:photos/ui/tabs/home_widget.dart"; import 'package:photos/utils/crypto_util.dart'; import 'package:photos/utils/dialog_util.dart'; -import "package:photos/utils/email_util.dart"; import 'package:photos/utils/navigation_util.dart'; import 'package:photos/utils/toast_util.dart'; import "package:pointycastle/export.dart"; @@ -586,120 +585,92 @@ class UserService { BuildContext context, SrpAttributes srpAttributes, String userPassword, + ProgressDialog dialog, ) async { - final dialog = createProgressDialog( - context, - S.of(context).pleaseWait, - isDismissible: true, - ); - await dialog.show(); late Uint8List keyEncryptionKey; - try { - keyEncryptionKey = await CryptoUtil.deriveKey( - utf8.encode(userPassword) as Uint8List, - CryptoUtil.base642bin(srpAttributes.kekSalt), - srpAttributes.memLimit, - srpAttributes.opsLimit, - ); - final loginKey = await CryptoUtil.deriveLoginKey(keyEncryptionKey); - final Uint8List identity = Uint8List.fromList( - utf8.encode(srpAttributes.srpUserID), - ); - final Uint8List salt = base64Decode(srpAttributes.srpSalt); - final Uint8List password = loginKey; - final SecureRandom random = _getSecureRandom(); + _logger.finest('Start deriving key'); + keyEncryptionKey = await CryptoUtil.deriveKey( + utf8.encode(userPassword) as Uint8List, + CryptoUtil.base642bin(srpAttributes.kekSalt), + srpAttributes.memLimit, + srpAttributes.opsLimit, + ); + _logger.finest('keyDerivation done, derive LoginKey'); + final loginKey = await CryptoUtil.deriveLoginKey(keyEncryptionKey); + final Uint8List identity = Uint8List.fromList( + utf8.encode(srpAttributes.srpUserID), + ); + _logger.finest('longinKey derivation done'); + final Uint8List salt = base64Decode(srpAttributes.srpSalt); + final Uint8List password = loginKey; + final SecureRandom random = _getSecureRandom(); - final client = SRP6Client( - group: kDefaultSrpGroup, - digest: Digest('SHA-256'), - random: random, - ); + final client = SRP6Client( + group: kDefaultSrpGroup, + digest: Digest('SHA-256'), + random: random, + ); - final A = client.generateClientCredentials(salt, identity, password); - final createSessionResponse = await _dio.post( - _config.getHttpEndpoint() + "/users/srp/create-session", - data: { - "srpUserID": srpAttributes.srpUserID, - "srpA": base64Encode(SRP6Util.encodeBigInt(A!)), - }, - ); - final String sessionID = createSessionResponse.data["sessionID"]; - final String srpB = createSessionResponse.data["srpB"]; + final A = client.generateClientCredentials(salt, identity, password); + final createSessionResponse = await _dio.post( + _config.getHttpEndpoint() + "/users/srp/create-session", + data: { + "srpUserID": srpAttributes.srpUserID, + "srpA": base64Encode(SRP6Util.encodeBigInt(A!)), + }, + ); + final String sessionID = createSessionResponse.data["sessionID"]; + final String srpB = createSessionResponse.data["srpB"]; - final serverB = SRP6Util.decodeBigInt(base64Decode(srpB)); - // ignore: need to calculate secret to get M1, unused_local_variable - final clientS = client.calculateSecret(serverB); - final clientM = client.calculateClientEvidenceMessage(); - final response = await _dio.post( - _config.getHttpEndpoint() + "/users/srp/verify-session", - data: { - "sessionID": sessionID, - "srpUserID": srpAttributes.srpUserID, - "srpM1": base64Encode(SRP6Util.encodeBigInt(clientM!)), - }, - ); - if (response.statusCode == 200) { - Widget page; - final String twoFASessionID = response.data["twoFactorSessionID"]; - Configuration.instance.setVolatilePassword(userPassword); - if (twoFASessionID.isNotEmpty) { - setTwoFactor(value: true); - page = TwoFactorAuthenticationPage(twoFASessionID); - } else { - await _saveConfiguration(response); - if (Configuration.instance.getEncryptedToken() != null) { - await Configuration.instance.decryptSecretsAndGetKeyEncKey( - userPassword, - Configuration.instance.getKeyAttributes()!, - keyEncryptionKey: keyEncryptionKey, - ); - page = const HomeWidget(); - } else { - throw Exception("unexpected response during email verification"); - } - } - await dialog.hide(); - if (page is HomeWidget) { - Navigator.of(context).popUntil((route) => route.isFirst); - Bus.instance.fire(AccountConfiguredEvent()); - } else { - Navigator.of(context).pushAndRemoveUntil( - MaterialPageRoute( - builder: (BuildContext context) { - return page; - }, - ), - (route) => route.isFirst, + final serverB = SRP6Util.decodeBigInt(base64Decode(srpB)); + // ignore: need to calculate secret to get M1, unused_local_variable + final clientS = client.calculateSecret(serverB); + final clientM = client.calculateClientEvidenceMessage(); + final response = await _dio.post( + _config.getHttpEndpoint() + "/users/srp/verify-session", + data: { + "sessionID": sessionID, + "srpUserID": srpAttributes.srpUserID, + "srpM1": base64Encode(SRP6Util.encodeBigInt(clientM!)), + }, + ); + if (response.statusCode == 200) { + Widget page; + final String twoFASessionID = response.data["twoFactorSessionID"]; + Configuration.instance.setVolatilePassword(userPassword); + if (twoFASessionID.isNotEmpty) { + setTwoFactor(value: true); + page = TwoFactorAuthenticationPage(twoFASessionID); + } else { + await _saveConfiguration(response); + if (Configuration.instance.getEncryptedToken() != null) { + await Configuration.instance.decryptSecretsAndGetKeyEncKey( + userPassword, + Configuration.instance.getKeyAttributes()!, + keyEncryptionKey: keyEncryptionKey, ); + page = const HomeWidget(); + } else { + throw Exception("unexpected response during email verification"); } - } else { - // should never reach here - throw Exception("unexpected response during email verification"); } - } on DioError catch (e, s) { await dialog.hide(); - if (e.response != null && e.response!.statusCode == 401) { - await _showContactSupportDialog( - context, - S.of(context).incorrectPasswordTitle, - S.of(context).pleaseTryAgain, - ); + if (page is HomeWidget) { + Navigator.of(context).popUntil((route) => route.isFirst); + Bus.instance.fire(AccountConfiguredEvent()); } else { - _logger.severe('failed to verify password', e, s); - await _showContactSupportDialog( - context, - S.of(context).oops, - S.of(context).verificationFailedPleaseTryAgain, + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute( + builder: (BuildContext context) { + return page; + }, + ), + (route) => route.isFirst, ); } - } catch (e, s) { - _logger.severe('failed to verify password', e, s); - await dialog.hide(); - await _showContactSupportDialog( - context, - S.of(context).oops, - S.of(context).verificationFailedPleaseTryAgain, - ); + } else { + // should never reach here + throw Exception("unexpected response during email verification"); } } @@ -1164,26 +1135,4 @@ class UserService { rethrow; } } - - Future _showContactSupportDialog( - BuildContext context, - String title, - String message, - ) async { - final dialogChoice = await showChoiceDialog( - context, - title: title, - body: message, - firstButtonLabel: S.of(context).contactSupport, - secondButtonLabel: S.of(context).ok, - ); - if (dialogChoice!.action == ButtonAction.first) { - await sendLogs( - context, - S.of(context).contactSupport, - "support@ente.io", - postShare: () {}, - ); - } - } } diff --git a/lib/ui/account/login_pwd_verification_page.dart b/lib/ui/account/login_pwd_verification_page.dart index f29827a31..e643b9b25 100644 --- a/lib/ui/account/login_pwd_verification_page.dart +++ b/lib/ui/account/login_pwd_verification_page.dart @@ -1,12 +1,17 @@ +import "package:dio/dio.dart"; import "package:flutter/foundation.dart"; import 'package:flutter/material.dart'; +import "package:logging/logging.dart"; import 'package:photos/core/configuration.dart'; +import "package:photos/core/errors.dart"; import "package:photos/generated/l10n.dart"; import "package:photos/models/api/user/srp.dart"; import "package:photos/services/user_service.dart"; import "package:photos/theme/ente_theme.dart"; import 'package:photos/ui/common/dynamic_fab.dart'; +import "package:photos/ui/components/buttons/button_widget.dart"; import "package:photos/utils/dialog_util.dart"; +import "package:photos/utils/email_util.dart"; // LoginPasswordVerificationPage is a page that allows the user to enter their password to verify their identity. // If the password is correct, then the user is either directed to @@ -31,6 +36,7 @@ class _LoginPasswordVerificationPageState String? email; bool _passwordInFocus = false; bool _passwordVisible = false; + final Logger _logger = Logger("LoginPasswordVerificationPage"); @override void initState() { @@ -85,11 +91,7 @@ class _LoginPasswordVerificationPageState buttonText: S.of(context).logInLabel, onPressedFunction: () async { FocusScope.of(context).unfocus(); - await UserService.instance.verifyEmailViaPassword( - context, - widget.srpAttributes, - _passwordController.text, - ); + await verifyPassword(context, _passwordController.text); }, ), floatingActionButtonLocation: fabLocation(), @@ -97,6 +99,94 @@ class _LoginPasswordVerificationPageState ); } + Future verifyPassword(BuildContext context, String password) async { + final dialog = createProgressDialog( + context, + S.of(context).pleaseWait, + isDismissible: true, + ); + await dialog.show(); + try { + await UserService.instance.verifyEmailViaPassword( + context, + widget.srpAttributes, + password, + dialog, + ); + } on DioError catch (e, s) { + await dialog.hide(); + if (e.response != null && e.response!.statusCode == 401) { + _logger.severe('server reject, failed verify SRP login', e, s); + await _showContactSupportDialog( + context, + S.of(context).incorrectPasswordTitle, + S.of(context).pleaseTryAgain, + ); + } else { + _logger.severe('API failure during SRP login', e, s); + if (e.type == DioErrorType.other) { + await _showContactSupportDialog( + context, + S.of(context).noInternetConnection, + S.of(context).pleaseCheckYourInternetConnectionAndTryAgain, + ); + } else { + await _showContactSupportDialog( + context, + S.of(context).somethingWentWrong, + S.of(context).verificationFailedPleaseTryAgain, + ); + } + } + } catch (e, s) { + _logger.severe('error while verifying password', e, s); + await dialog.hide(); + if (e is KeyDerivationError || e is LoginKeyDerivationError) { + final dialogChoice = await showChoiceDialog( + context, + title: S.of(context).recreatePasswordTitle, + body: S.of(context).recreatePasswordBody, + firstButtonLabel: S.of(context).useRecoveryKey, + ); + if (dialogChoice!.action == ButtonAction.first) { + await UserService.instance.sendOtt( + context, + email!, + isResetPasswordScreen: true, + ); + } + return; + } + await _showContactSupportDialog( + context, + S.of(context).oops, + S.of(context).verificationFailedPleaseTryAgain, + ); + } + } + + Future _showContactSupportDialog( + BuildContext context, + String title, + String message, + ) async { + final dialogChoice = await showChoiceDialog( + context, + title: title, + body: message, + firstButtonLabel: S.of(context).contactSupport, + secondButtonLabel: S.of(context).ok, + ); + if (dialogChoice!.action == ButtonAction.first) { + await sendLogs( + context, + S.of(context).contactSupport, + "support@ente.io", + postShare: () {}, + ); + } + } + Widget _getBody() { return Column( children: [ diff --git a/lib/utils/crypto_util.dart b/lib/utils/crypto_util.dart index c2f02b59b..3c6be311b 100644 --- a/lib/utils/crypto_util.dart +++ b/lib/utils/crypto_util.dart @@ -77,7 +77,7 @@ Future cryptoGenericHash(Map args) async { EncryptionResult chachaEncryptData(Map args) { final initPushResult = - Sodium.cryptoSecretstreamXchacha20poly1305InitPush(args["key"]); + Sodium.cryptoSecretstreamXchacha20poly1305InitPush(args["key"]); final encryptedData = Sodium.cryptoSecretstreamXchacha20poly1305Push( initPushResult.state, args["source"], @@ -102,7 +102,7 @@ Future chachaEncryptFile(Map args) async { final inputFile = sourceFile.openSync(mode: FileMode.read); final key = args["key"] ?? Sodium.cryptoSecretstreamXchacha20poly1305Keygen(); final initPushResult = - Sodium.cryptoSecretstreamXchacha20poly1305InitPush(key); + Sodium.cryptoSecretstreamXchacha20poly1305InitPush(key); var bytesRead = 0; var tag = Sodium.cryptoSecretstreamXchacha20poly1305TagMessage; while (tag != Sodium.cryptoSecretstreamXchacha20poly1305TagFinal) { @@ -156,7 +156,7 @@ Future chachaDecryptFile(Map args) async { final buffer = await inputFile.read(chunkSize); bytesRead += chunkSize; final pullResult = - Sodium.cryptoSecretstreamXchacha20poly1305Pull(pullState, buffer, null); + Sodium.cryptoSecretstreamXchacha20poly1305Pull(pullState, buffer, null); await destinationFile.writeAsBytes(pullResult.m, mode: FileMode.append); tag = pullResult.tag; } @@ -190,20 +190,22 @@ class CryptoUtil { Sodium.init(); } - static Uint8List base642bin(String b64, { + static Uint8List base642bin( + String b64, { String? ignore, int variant = Sodium.base64VariantOriginal, }) { return Sodium.base642bin(b64, ignore: ignore, variant: variant); } - static String bin2base64(Uint8List bin, { + static String bin2base64( + Uint8List bin, { bool urlSafe = false, }) { return Sodium.bin2base64( bin, variant: - urlSafe ? Sodium.base64VariantUrlsafe : Sodium.base64VariantOriginal, + urlSafe ? Sodium.base64VariantUrlsafe : Sodium.base64VariantOriginal, ); } @@ -237,9 +239,11 @@ class CryptoUtil { // Decrypts the given cipher, with the given key and nonce using XSalsa20 // (w Poly1305 MAC). - static Future decrypt(Uint8List cipher, - Uint8List key, - Uint8List nonce,) async { + static Future decrypt( + Uint8List cipher, + Uint8List key, + Uint8List nonce, + ) async { final args = {}; args["cipher"] = cipher; args["nonce"] = nonce; @@ -256,9 +260,11 @@ class CryptoUtil { // This function runs on the same thread as the caller, so should be used only // for small amounts of data where thread switching can result in a degraded // user experience - static Uint8List decryptSync(Uint8List cipher, - Uint8List key, - Uint8List nonce,) { + static Uint8List decryptSync( + Uint8List cipher, + Uint8List key, + Uint8List nonce, + ) { final args = {}; args["cipher"] = cipher; args["nonce"] = nonce; @@ -270,8 +276,10 @@ class CryptoUtil { // nonce, using XChaCha20 (w Poly1305 MAC). // This function runs on the isolate pool held by `_computer`. // TODO: Remove "ChaCha", an implementation detail from the function name - static Future encryptChaCha(Uint8List source, - Uint8List key,) async { + static Future encryptChaCha( + Uint8List source, + Uint8List key, + ) async { final args = {}; args["source"] = source; args["key"] = key; @@ -285,9 +293,11 @@ class CryptoUtil { // Decrypts the given source, with the given key and header using XChaCha20 // (w Poly1305 MAC). // TODO: Remove "ChaCha", an implementation detail from the function name - static Future decryptChaCha(Uint8List source, - Uint8List key, - Uint8List header,) async { + static Future decryptChaCha( + Uint8List source, + Uint8List key, + Uint8List header, + ) async { final args = {}; args["source"] = source; args["key"] = key; @@ -304,10 +314,10 @@ class CryptoUtil { // to the destinationFilePath. // If a key is not provided, one is generated and returned. static Future encryptFile( - String sourceFilePath, - String destinationFilePath, { - Uint8List? key, - }) { + String sourceFilePath, + String destinationFilePath, { + Uint8List? key, + }) { final args = {}; args["sourceFilePath"] = sourceFilePath; args["destinationFilePath"] = destinationFilePath; @@ -322,10 +332,11 @@ class CryptoUtil { // Decrypts the file at sourceFilePath, with the given key and header using // XChaCha20 (w Poly1305 MAC), and writes it to the destinationFilePath. static Future decryptFile( - String sourceFilePath, - String destinationFilePath, - Uint8List header, - Uint8List key,) { + String sourceFilePath, + String destinationFilePath, + Uint8List header, + Uint8List key, + ) { final args = {}; args["sourceFilePath"] = sourceFilePath; args["destinationFilePath"] = destinationFilePath; @@ -356,10 +367,10 @@ class CryptoUtil { // Decrypts the input using the given publicKey-secretKey pair static Uint8List openSealSync( - Uint8List input, - Uint8List publicKey, - Uint8List secretKey, - ) { + Uint8List input, + Uint8List publicKey, + Uint8List secretKey, + ) { return Sodium.cryptoBoxSealOpen(input, publicKey, secretKey); } @@ -377,9 +388,9 @@ class CryptoUtil { // At all points, we ensure that the product of these two variables (the area // under the graph that determines the amount of work required) is a constant. static Future deriveSensitiveKey( - Uint8List password, - Uint8List salt, - ) async { + Uint8List password, + Uint8List salt, + ) async { final logger = Logger("pwhash"); int memLimit = Sodium.cryptoPwhashMemlimitSensitive; int opsLimit = Sodium.cryptoPwhashOpslimitSensitive; @@ -407,7 +418,10 @@ class CryptoUtil { return DerivedKeyResult(key, memLimit, opsLimit); } catch (e, s) { logger.warning( - "failed to deriveKey mem: $memLimit, ops: $opsLimit", e, s,); + "failed to deriveKey mem: $memLimit, ops: $opsLimit", + e, + s, + ); } memLimit = (memLimit / 2).round(); opsLimit = opsLimit * 2; @@ -421,9 +435,9 @@ class CryptoUtil { // extra layer of authentication (atop the access token and collection key). // More details @ https://ente.io/blog/building-shareable-links/ static Future deriveInteractiveKey( - Uint8List password, - Uint8List salt, - ) async { + Uint8List password, + Uint8List salt, + ) async { final int memLimit = Sodium.cryptoPwhashMemlimitInteractive; final int opsLimit = Sodium.cryptoPwhashOpslimitInteractive; final key = await deriveKey(password, salt, memLimit, opsLimit); @@ -433,23 +447,23 @@ class CryptoUtil { // Derives a key for a given password, salt, memLimit and opsLimit using // Argon2id, v1.3. static Future deriveKey( - Uint8List password, - Uint8List salt, - int memLimit, - int opsLimit, - ) { + Uint8List password, + Uint8List salt, + int memLimit, + int opsLimit, + ) { try { - return _computer.compute( - cryptoPwHash, - param: { - "password": password, - "salt": salt, - "memLimit": memLimit, - "opsLimit": opsLimit, - }, - taskName: "deriveKey", - ); - } catch(e,s) { + return _computer.compute( + cryptoPwHash, + param: { + "password": password, + "salt": salt, + "memLimit": memLimit, + "opsLimit": opsLimit, + }, + taskName: "deriveKey", + ); + } catch (e, s) { final String errMessage = 'failed to deriveKey memLimit: $memLimit and ' 'opsLimit: $opsLimit'; Logger("CryptoUtilDeriveKey").warning(errMessage, e, s); @@ -461,20 +475,25 @@ class CryptoUtil { // (Key Derivation Function) with the `loginSubKeyId` and // `loginSubKeyLen` and `loginSubKeyContext` as context static Future deriveLoginKey( - Uint8List key, - ) async { - final Uint8List derivedKey = await _computer.compute( - cryptoKdfDeriveFromKey, - param: { - "key": key, - "subkeyId": loginSubKeyId, - "subkeyLen": loginSubKeyLen, - "context": utf8.encode(loginSubKeyContext), - }, - taskName: "deriveLoginKey", - ); - // return the first 16 bytes of the derived key - return derivedKey.sublist(0, 16); + Uint8List key, + ) async { + try { + final Uint8List derivedKey = await _computer.compute( + cryptoKdfDeriveFromKey, + param: { + "key": key, + "subkeyId": loginSubKeyId, + "subkeyLen": loginSubKeyLen, + "context": utf8.encode(loginSubKeyContext), + }, + taskName: "deriveLoginKey", + ); + // return the first 16 bytes of the derived key + return derivedKey.sublist(0, 16); + } catch (e, s) { + Logger("deriveLoginKey").severe("loginKeyDerivation failed", e, s); + throw LoginKeyDerivationError(); + } } // Computes and returns the hash of the source file From 1da9cd6f355f30ee3b4d971e2c730a437e61a61e Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 20 Nov 2023 13:50:25 +0530 Subject: [PATCH 02/10] Trigger regular login when loginKey derivation fails --- .../account/login_pwd_verification_page.dart | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/ui/account/login_pwd_verification_page.dart b/lib/ui/account/login_pwd_verification_page.dart index e643b9b25..a253b1585 100644 --- a/lib/ui/account/login_pwd_verification_page.dart +++ b/lib/ui/account/login_pwd_verification_page.dart @@ -139,9 +139,19 @@ class _LoginPasswordVerificationPageState } } } catch (e, s) { - _logger.severe('error while verifying password', e, s); + _logger.info('error during loginViaPassword', e); await dialog.hide(); - if (e is KeyDerivationError || e is LoginKeyDerivationError) { + if (e is LoginKeyDerivationError) { + _logger.severe('loginKey derivation error', e, s); + // LoginKey err, perform regular login via ott verification + await UserService.instance.sendOtt( + context, + email!, + isCreateAccountScreen: true, + ); + return; + } else if (e is KeyDerivationError) { + // device is not powerful enough to perform derive key final dialogChoice = await showChoiceDialog( context, title: S.of(context).recreatePasswordTitle, @@ -156,12 +166,14 @@ class _LoginPasswordVerificationPageState ); } return; + } else { + _logger.severe('unexpected error while verifying password', e, s); + await _showContactSupportDialog( + context, + S.of(context).oops, + S.of(context).verificationFailedPleaseTryAgain, + ); } - await _showContactSupportDialog( - context, - S.of(context).oops, - S.of(context).verificationFailedPleaseTryAgain, - ); } } From f25a4e59b4a9a210407e8a169283c001cb2d3c44 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Mon, 20 Nov 2023 14:27:01 +0530 Subject: [PATCH 03/10] fix: archived files which are not part of an archived album were coming up in moments --- lib/db/files_db.dart | 3 +++ lib/services/memories_service.dart | 2 ++ 2 files changed, 5 insertions(+) diff --git a/lib/db/files_db.dart b/lib/db/files_db.dart index 8f6c7a6b7..bf5b5991c 100644 --- a/lib/db/files_db.dart +++ b/lib/db/files_db.dart @@ -699,6 +699,7 @@ class FilesDB { Future> getFilesCreatedWithinDurations( List> durations, Set ignoredCollectionIDs, { + int? visibility, String order = 'ASC', }) async { if (durations.isEmpty) { @@ -714,6 +715,8 @@ class FilesDB { ")"; if (index != durations.length - 1) { whereClause += " OR "; + } else if (visibility != null) { + whereClause += ' AND $columnMMdVisibility = $visibility'; } } whereClause += ")"; diff --git a/lib/services/memories_service.dart b/lib/services/memories_service.dart index 1b6cbf476..2bfefcb2f 100644 --- a/lib/services/memories_service.dart +++ b/lib/services/memories_service.dart @@ -8,6 +8,7 @@ import "package:photos/events/files_updated_event.dart"; import "package:photos/events/memories_setting_changed.dart"; import 'package:photos/models/filters/important_items_filter.dart'; import 'package:photos/models/memory.dart'; +import "package:photos/models/metadata/common_keys.dart"; import 'package:photos/services/collections_service.dart'; import "package:shared_preferences/shared_preferences.dart"; @@ -108,6 +109,7 @@ class MemoriesService extends ChangeNotifier { final files = await _filesDB.getFilesCreatedWithinDurations( durations, ignoredCollections, + visibility: visibleVisibility, ); final seenTimes = await _memoriesDB.getSeenTimes(); final List memories = []; From 6af7140be55124a3800e65540036572681f8f508 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 20 Nov 2023 17:06:11 +0530 Subject: [PATCH 04/10] Port lock screen fixes from auth --- lib/ui/tools/lock_screen.dart | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/ui/tools/lock_screen.dart b/lib/ui/tools/lock_screen.dart index 781700b62..6b34fda4f 100644 --- a/lib/ui/tools/lock_screen.dart +++ b/lib/ui/tools/lock_screen.dart @@ -1,6 +1,8 @@ +import "dart:io"; + import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; -import "package:photos/generated/l10n.dart"; +import "package:photos/l10n/l10n.dart"; import 'package:photos/ui/common/gradient_button.dart'; import 'package:photos/ui/tools/app_lock.dart'; import 'package:photos/utils/auth_util.dart'; @@ -21,10 +23,16 @@ class _LockScreenState extends State with WidgetsBindingObserver { @override void initState() { - _logger.info("initState"); + _logger.info("initiatingState"); super.initState(); - _showLockScreen(source: "initState"); WidgetsBinding.instance.addObserver(this); + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + if (isNonMobileIOSDevice()) { + _logger.info('ignore init for non mobile iOS device'); + return; + } + _showLockScreen(source: "postFrameInit"); + }); } @override @@ -45,7 +53,7 @@ class _LockScreenState extends State with WidgetsBindingObserver { SizedBox( width: 180, child: GradientButton( - text: S.of(context).unlock, + text: context.l10n.unlock, iconData: Icons.lock_open_outlined, onTap: () async { _showLockScreen(source: "tapUnlock"); @@ -60,6 +68,14 @@ class _LockScreenState extends State with WidgetsBindingObserver { ); } + bool isNonMobileIOSDevice() { + if (Platform.isAndroid) { + return false; + } + var shortestSide = MediaQuery.of(context).size.shortestSide; + return shortestSide > 600 ? true : false; + } + @override void didChangeAppLifecycleState(AppLifecycleState state) { _logger.info(state.toString()); @@ -73,7 +89,10 @@ class _LockScreenState extends State with WidgetsBindingObserver { if (!_hasAuthenticationFailed && !didAuthInLast5Seconds) { // Show the lock screen again only if the app is resuming from the // background, and not when the lock screen was explicitly dismissed - _showLockScreen(source: "lifeCycle"); + Future.delayed( + Duration.zero, + () => _showLockScreen(source: "lifeCycle"), + ); } else { _hasAuthenticationFailed = false; // Reset failure state } @@ -90,6 +109,7 @@ class _LockScreenState extends State with WidgetsBindingObserver { @override void dispose() { + _logger.info('disposing'); WidgetsBinding.instance.removeObserver(this); super.dispose(); } @@ -101,7 +121,7 @@ class _LockScreenState extends State with WidgetsBindingObserver { _isShowingLockScreen = true; final result = await requestAuthentication( context, - S.of(context).authToViewYourMemories, + context.l10n.authToViewYourMemories, ); _logger.finest("LockScreen Result $result $id"); _isShowingLockScreen = false; @@ -117,6 +137,7 @@ class _LockScreenState extends State with WidgetsBindingObserver { } } } catch (e, s) { + _isShowingLockScreen = false; _logger.severe(e, s); } } From 48400bc4e7306c6fef8c5088bdaa0553885c67c8 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 20 Nov 2023 12:20:24 +0000 Subject: [PATCH 05/10] New Crowdin translations by GitHub Action --- lib/l10n/intl_zh.arb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/l10n/intl_zh.arb b/lib/l10n/intl_zh.arb index 5478e9c8b..948b143c3 100644 --- a/lib/l10n/intl_zh.arb +++ b/lib/l10n/intl_zh.arb @@ -1149,5 +1149,7 @@ "@addNew": { "description": "Text to add a new item (location tag, album, caption etc)" }, - "contacts": "联系人" + "contacts": "联系人", + "noInternetConnection": "无互联网连接", + "pleaseCheckYourInternetConnectionAndTryAgain": "请检查您的互联网连接,然后重试。" } \ No newline at end of file From 81079ac7dcb3b87c1547014597ed93843881cce4 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 20 Nov 2023 18:40:57 +0530 Subject: [PATCH 06/10] Show add-on validity on sub page --- lib/generated/intl/messages_cs.dart | 1 + lib/generated/intl/messages_de.dart | 1 + lib/generated/intl/messages_en.dart | 16 +++-- lib/generated/intl/messages_es.dart | 1 + lib/generated/intl/messages_fr.dart | 66 +++++++++++++++++-- lib/generated/intl/messages_it.dart | 5 +- lib/generated/intl/messages_ko.dart | 1 + lib/generated/intl/messages_nl.dart | 1 + lib/generated/intl/messages_no.dart | 1 + lib/generated/intl/messages_pl.dart | 1 + lib/generated/intl/messages_pt.dart | 1 + lib/generated/intl/messages_zh.dart | 46 +++++++++++-- lib/generated/l10n.dart | 14 +++- lib/l10n/intl_en.arb | 1 + lib/ui/payment/store_subscription_page.dart | 2 +- lib/ui/payment/stripe_subscription_page.dart | 2 +- .../payment/subscription_common_widgets.dart | 47 +++++++++++-- 17 files changed, 182 insertions(+), 25 deletions(-) diff --git a/lib/generated/intl/messages_cs.dart b/lib/generated/intl/messages_cs.dart index 815bedb4a..a0b3b9f7d 100644 --- a/lib/generated/intl/messages_cs.dart +++ b/lib/generated/intl/messages_cs.dart @@ -24,6 +24,7 @@ class MessageLookup extends MessageLookupByLibrary { static Map _notInlinedMessages(_) => { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Add to hidden album"), + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "deleteConfirmDialogBody": MessageLookupByLibrary.simpleMessage( "This account is linked to other ente apps, if you use any.\\n\\nYour uploaded data, across all ente apps, will be scheduled for deletion, and your account will be permanently deleted."), "fileTypes": MessageLookupByLibrary.simpleMessage("File types"), diff --git a/lib/generated/intl/messages_de.dart b/lib/generated/intl/messages_de.dart index 1c31ebad2..1b935485f 100644 --- a/lib/generated/intl/messages_de.dart +++ b/lib/generated/intl/messages_de.dart @@ -442,6 +442,7 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Support kontaktieren"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Weiter"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage( "Mit kostenloser Testversion fortfahren"), diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 5cbdf629e..726f34076 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -23,6 +23,9 @@ class MessageLookup extends MessageLookupByLibrary { static String m0(count) => "${Intl.plural(count, one: 'Add item', other: 'Add items')}"; + static String m64(storageAmount, endDate) => + "Your ${storageAmount} add-on is valid till ${endDate}"; + static String m1(emailOrName) => "Added by ${emailOrName}"; static String m2(albumName) => "Added successfully to ${albumName}"; @@ -137,7 +140,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m41(endDate) => "Renews on ${endDate}"; - static String m64(count) => + static String m65(count) => "${Intl.plural(count, one: '${count} result found', other: '${count} results found')}"; static String m42(count) => "${count} selected"; @@ -190,7 +193,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m59(count) => "${Intl.plural(count, zero: '', one: '1 day', other: '${count} days')}"; - static String m65(endDate) => "Valid till ${endDate}"; + static String m66(endDate) => "Valid till ${endDate}"; static String m60(email) => "Verify ${email}"; @@ -226,6 +229,7 @@ class MessageLookup extends MessageLookupByLibrary { "addNew": MessageLookupByLibrary.simpleMessage("Add new"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Details of add-ons"), + "addOnValidTill": m64, "addOns": MessageLookupByLibrary.simpleMessage("Add-ons"), "addPhotos": MessageLookupByLibrary.simpleMessage("Add photos"), "addSelected": MessageLookupByLibrary.simpleMessage("Add selected"), @@ -441,6 +445,7 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Contact support"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "contents": MessageLookupByLibrary.simpleMessage("Contents"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continue"), "continueOnFreeTrial": @@ -926,7 +931,6 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailedTalkToProvider": m33, "paymentFailedWithReason": m34, "pendingSync": MessageLookupByLibrary.simpleMessage("Pending sync"), - "people": MessageLookupByLibrary.simpleMessage("People"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage("People using your code"), "permDeleteWarning": MessageLookupByLibrary.simpleMessage( @@ -1120,14 +1124,14 @@ class MessageLookup extends MessageLookupByLibrary { "Albums, file names, and types"), "searchHint4": MessageLookupByLibrary.simpleMessage("Location"), "searchHint5": MessageLookupByLibrary.simpleMessage( - "Coming soon: Photo contents, faces"), + "Coming soon: Faces & magic search ✨"), "searchHintText": MessageLookupByLibrary.simpleMessage( "Albums, months, days, years, ..."), "searchLocationEmptySection": MessageLookupByLibrary.simpleMessage( "Group photos that are taken within some radius of a photo"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Invite people, and you\'ll see all photos shared by them here"), - "searchResultCount": m64, + "searchResultCount": m65, "security": MessageLookupByLibrary.simpleMessage("Security"), "selectAlbum": MessageLookupByLibrary.simpleMessage("Select album"), "selectAll": MessageLookupByLibrary.simpleMessage("Select all"), @@ -1376,7 +1380,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("Use selected photo"), "usedSpace": MessageLookupByLibrary.simpleMessage("Used space"), - "validTill": m65, + "validTill": m66, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Verification failed, please try again"), diff --git a/lib/generated/intl/messages_es.dart b/lib/generated/intl/messages_es.dart index 9d6829d71..499277175 100644 --- a/lib/generated/intl/messages_es.dart +++ b/lib/generated/intl/messages_es.dart @@ -398,6 +398,7 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Contactar con soporte"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuar"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage( "Continuar con el plan gratuito"), diff --git a/lib/generated/intl/messages_fr.dart b/lib/generated/intl/messages_fr.dart index 264b5dd96..4a76e7b4e 100644 --- a/lib/generated/intl/messages_fr.dart +++ b/lib/generated/intl/messages_fr.dart @@ -140,6 +140,9 @@ class MessageLookup extends MessageLookupByLibrary { static String m41(endDate) => "Renouvellement le ${endDate}"; + static String m65(count) => + "${Intl.plural(count, one: '${count} résultat trouvé', other: '${count} résultats trouvés')}"; + static String m42(count) => "${count} sélectionné(s)"; static String m43(count, yourCount) => @@ -189,6 +192,8 @@ class MessageLookup extends MessageLookupByLibrary { static String m59(count) => "${Intl.plural(count, zero: '0 jour', one: '1 jour', other: '${count} jours')}"; + static String m66(endDate) => "Valable jusqu\'au ${endDate}"; + static String m60(email) => "Vérifier ${email}"; static String m61(email) => @@ -223,6 +228,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ajouter la localisation"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Ajouter"), "addMore": MessageLookupByLibrary.simpleMessage("Ajouter Plus"), + "addNew": MessageLookupByLibrary.simpleMessage("Ajouter un nouveau"), + "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage( + "Détails des modules complémentaires"), + "addOns": + MessageLookupByLibrary.simpleMessage("Modules complémentaires"), "addPhotos": MessageLookupByLibrary.simpleMessage("Ajouter des photos"), "addSelected": MessageLookupByLibrary.simpleMessage("Ajouter la sélection"), @@ -233,6 +243,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ajouter à un album masqué"), "addViewer": MessageLookupByLibrary.simpleMessage("Ajouter un observateur"), + "addYourPhotosNow": MessageLookupByLibrary.simpleMessage( + "Ajoutez vos photos maintenant"), "addedAs": MessageLookupByLibrary.simpleMessage("Ajouté comme"), "addedBy": m1, "addedSuccessfullyTo": m2, @@ -356,6 +368,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Paramètres de la sauvegarde"), "backupVideos": MessageLookupByLibrary.simpleMessage("Sauvegarde des vidéos"), + "blackFridaySale": + MessageLookupByLibrary.simpleMessage("Offre Black Friday"), "blog": MessageLookupByLibrary.simpleMessage("Blog"), "cachedData": MessageLookupByLibrary.simpleMessage("Données mises en cache"), @@ -446,6 +460,8 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Contacter l\'assistance"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), + "contents": MessageLookupByLibrary.simpleMessage("Contenus"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuer"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage( "Poursuivre avec la version d\'essai gratuite"), @@ -510,7 +526,7 @@ class MessageLookup extends MessageLookupByLibrary { "Ceci supprimera tous les albums vides. Ceci est utile lorsque vous voulez réduire l\'encombrement dans votre liste d\'albums."), "deleteAll": MessageLookupByLibrary.simpleMessage("Tout Supprimer"), "deleteConfirmDialogBody": MessageLookupByLibrary.simpleMessage( - "This account is linked to other ente apps, if you use any.\\n\\nYour uploaded data, across all ente apps, will be scheduled for deletion, and your account will be permanently deleted."), + "Ce compte est lié à d\'autres applications ente, si vous en utilisez une.\\n\\nVos données téléchargées, dans toutes les applications ente, seront planifiées pour suppression, et votre compte sera définitivement supprimé."), "deleteEmailRequest": MessageLookupByLibrary.simpleMessage( "Veuillez envoyer un e-mail à account-deletion@ente.io à partir de votre adresse e-mail enregistrée."), "deleteEmptyAlbums": @@ -658,6 +674,7 @@ class MessageLookup extends MessageLookupByLibrary { "exportLogs": MessageLookupByLibrary.simpleMessage("Exporter les logs"), "exportYourData": MessageLookupByLibrary.simpleMessage("Exportez vos données"), + "faces": MessageLookupByLibrary.simpleMessage("Visages"), "failedToApplyCode": MessageLookupByLibrary.simpleMessage( "Impossible d\'appliquer le code"), "failedToCancel": @@ -689,7 +706,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ajouter une description..."), "fileSavedToGallery": MessageLookupByLibrary.simpleMessage( "Fichier enregistré dans la galerie"), - "fileTypes": MessageLookupByLibrary.simpleMessage("File types"), + "fileTypes": MessageLookupByLibrary.simpleMessage("Types de fichiers"), + "fileTypesAndNames": + MessageLookupByLibrary.simpleMessage("Types et noms de fichiers"), "filesBackedUpFromDevice": m19, "filesBackedUpInAlbum": m20, "filesDeleted": @@ -729,6 +748,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Accorder la permission"), "groupNearbyPhotos": MessageLookupByLibrary.simpleMessage( "Grouper les photos à proximité"), + "hearUsExplanation": MessageLookupByLibrary.simpleMessage( + "Nous ne suivons pas les installations d\'applications. Il serait utile que vous nous disiez comment vous nous avez trouvés !"), + "hearUsWhereTitle": MessageLookupByLibrary.simpleMessage( + "Comment avez-vous entendu parler de Ente? (facultatif)"), "hidden": MessageLookupByLibrary.simpleMessage("Masqué"), "hide": MessageLookupByLibrary.simpleMessage("Masquer"), "hiding": MessageLookupByLibrary.simpleMessage("Masquage en cours..."), @@ -810,6 +833,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkHasExpired": MessageLookupByLibrary.simpleMessage("Le lien a expiré"), "linkNeverExpires": MessageLookupByLibrary.simpleMessage("Jamais"), + "livePhotos": MessageLookupByLibrary.simpleMessage("Photos en direct"), "loadMessage1": MessageLookupByLibrary.simpleMessage( "Vous pouvez partager votre abonnement avec votre famille"), "loadMessage2": MessageLookupByLibrary.simpleMessage( @@ -876,7 +900,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Sécurité moyenne"), "modifyYourQueryOrTrySearchingFor": MessageLookupByLibrary.simpleMessage( - "Modify your query, or try searching for"), + "Modifiez votre requête, ou essayez de rechercher"), + "moments": MessageLookupByLibrary.simpleMessage("Souvenirs"), "monthly": MessageLookupByLibrary.simpleMessage("Mensuel"), "moveItem": m30, "moveToAlbum": @@ -966,9 +991,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Supprimer définitivement"), "permanentlyDeleteFromDevice": MessageLookupByLibrary.simpleMessage( "Supprimer définitivement de l\'appareil ?"), + "photoDescriptions": + MessageLookupByLibrary.simpleMessage("Descriptions de la photo"), "photoGridSize": MessageLookupByLibrary.simpleMessage("Taille de la grille photo"), "photoSmallCase": MessageLookupByLibrary.simpleMessage("photo"), + "photos": MessageLookupByLibrary.simpleMessage("Photos"), "photosAddedByYouWillBeRemovedFromTheAlbum": MessageLookupByLibrary.simpleMessage( "Les photos ajoutées par vous seront retirées de l\'album"), @@ -1136,12 +1164,36 @@ class MessageLookup extends MessageLookupByLibrary { "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( "Scannez ce code-barres avec\nvotre application d\'authentification"), + "searchAlbumsEmptySection": + MessageLookupByLibrary.simpleMessage("Albums"), "searchByAlbumNameHint": MessageLookupByLibrary.simpleMessage("Nom de l\'album"), "searchByExamples": MessageLookupByLibrary.simpleMessage( "• Noms d\'albums (par exemple \"Caméra\")\n• Types de fichiers (par exemple \"Vidéos\", \".gif\")\n• Années et mois (par exemple \"2022\", \"Janvier\")\n• Vacances (par exemple \"Noël\")\n• Descriptions de photos (par exemple \"#fun\")"), + "searchCaptionEmptySection": MessageLookupByLibrary.simpleMessage( + "Ajoutez des descriptions comme \"#trip\" dans les infos photo pour les retrouver ici plus rapidement"), + "searchDatesEmptySection": MessageLookupByLibrary.simpleMessage( + "Recherche par date, mois ou année"), + "searchFaceEmptySection": MessageLookupByLibrary.simpleMessage( + "Trouver toutes les photos d\'une personne"), + "searchFileTypesAndNamesEmptySection": + MessageLookupByLibrary.simpleMessage("Types et noms de fichiers"), + "searchHint1": MessageLookupByLibrary.simpleMessage( + "Recherche rapide, sur l\'appareil"), + "searchHint2": MessageLookupByLibrary.simpleMessage( + "Dates des photos, descriptions"), + "searchHint3": MessageLookupByLibrary.simpleMessage( + "Albums, noms de fichiers et types"), + "searchHint4": MessageLookupByLibrary.simpleMessage("Emplacement"), + "searchHint5": MessageLookupByLibrary.simpleMessage( + "Bientôt: Visages & recherche magique ✨"), "searchHintText": MessageLookupByLibrary.simpleMessage( "Albums, mois, jours, années, ..."), + "searchLocationEmptySection": MessageLookupByLibrary.simpleMessage( + "Grouper les photos qui sont prises dans un certain angle d\'une photo"), + "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( + "Invitez des gens, et vous verrez ici toutes les photos qu\'ils partagent"), + "searchResultCount": m65, "security": MessageLookupByLibrary.simpleMessage("Sécurité"), "selectAlbum": MessageLookupByLibrary.simpleMessage("Sélectionner album"), @@ -1400,6 +1452,8 @@ class MessageLookup extends MessageLookupByLibrary { "upgrade": MessageLookupByLibrary.simpleMessage("Améliorer"), "uploadingFilesToAlbum": MessageLookupByLibrary.simpleMessage( "Envoi des fichiers vers l\'album..."), + "upto50OffUntil4thDec": MessageLookupByLibrary.simpleMessage( + "Jusqu\'à 50% de réduction, jusqu\'au 4ème déc."), "usableReferralStorageInfo": MessageLookupByLibrary.simpleMessage( "Le stockage utilisable est limité par votre offre actuelle. Le stockage excédentaire deviendra automatiquement utilisable lorsque vous mettez à niveau votre offre."), "usePublicLinksForPeopleNotOnEnte": MessageLookupByLibrary.simpleMessage( @@ -1409,6 +1463,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage( "Utiliser la photo sélectionnée"), "usedSpace": MessageLookupByLibrary.simpleMessage("Mémoire utilisée"), + "validTill": m66, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "La vérification a échouée, veuillez réessayer"), @@ -1426,8 +1481,11 @@ class MessageLookup extends MessageLookupByLibrary { "verifyingRecoveryKey": MessageLookupByLibrary.simpleMessage( "Vérification de la clé de récupération..."), "videoSmallCase": MessageLookupByLibrary.simpleMessage("vidéo"), + "videos": MessageLookupByLibrary.simpleMessage("Vidéos"), "viewActiveSessions": MessageLookupByLibrary.simpleMessage( "Afficher les sessions actives"), + "viewAddOnButton": MessageLookupByLibrary.simpleMessage( + "Afficher les modules complémentaires"), "viewAll": MessageLookupByLibrary.simpleMessage("Tout afficher"), "viewAllExifData": MessageLookupByLibrary.simpleMessage( "Visualiser toutes les données EXIF"), @@ -1481,7 +1539,7 @@ class MessageLookup extends MessageLookupByLibrary { "youHaveSuccessfullyFreedUp": m63, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Votre compte a été supprimé"), - "yourMap": MessageLookupByLibrary.simpleMessage("Your map"), + "yourMap": MessageLookupByLibrary.simpleMessage("Votre carte"), "yourPlanWasSuccessfullyDowngraded": MessageLookupByLibrary.simpleMessage( "Votre plan a été rétrogradé avec succès"), diff --git a/lib/generated/intl/messages_it.dart b/lib/generated/intl/messages_it.dart index 1659be2cb..eaabb326b 100644 --- a/lib/generated/intl/messages_it.dart +++ b/lib/generated/intl/messages_it.dart @@ -187,7 +187,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m59(count) => "${Intl.plural(count, zero: '', one: '1 giorno', other: '${count} giorni')}"; - static String m65(endDate) => "Valido fino al ${endDate}"; + static String m66(endDate) => "Valido fino al ${endDate}"; static String m60(email) => "Verifica ${email}"; @@ -446,6 +446,7 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Contatta il supporto"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continua"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage("Continua la prova gratuita"), @@ -1390,7 +1391,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("Usa la foto selezionata"), "usedSpace": MessageLookupByLibrary.simpleMessage("Spazio utilizzato"), - "validTill": m65, + "validTill": m66, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Verifica fallita, per favore prova di nuovo"), diff --git a/lib/generated/intl/messages_ko.dart b/lib/generated/intl/messages_ko.dart index 653419bae..7c5259342 100644 --- a/lib/generated/intl/messages_ko.dart +++ b/lib/generated/intl/messages_ko.dart @@ -24,6 +24,7 @@ class MessageLookup extends MessageLookupByLibrary { static Map _notInlinedMessages(_) => { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Add to hidden album"), + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "deleteConfirmDialogBody": MessageLookupByLibrary.simpleMessage( "This account is linked to other ente apps, if you use any.\\n\\nYour uploaded data, across all ente apps, will be scheduled for deletion, and your account will be permanently deleted."), "fileTypes": MessageLookupByLibrary.simpleMessage("File types"), diff --git a/lib/generated/intl/messages_nl.dart b/lib/generated/intl/messages_nl.dart index f2f316213..90ac6a215 100644 --- a/lib/generated/intl/messages_nl.dart +++ b/lib/generated/intl/messages_nl.dart @@ -441,6 +441,7 @@ class MessageLookup extends MessageLookupByLibrary { "contactSupport": MessageLookupByLibrary.simpleMessage("Contacteer klantenservice"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Doorgaan"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage( "Doorgaan met gratis proefversie"), diff --git a/lib/generated/intl/messages_no.dart b/lib/generated/intl/messages_no.dart index 4de30a91b..d162c4550 100644 --- a/lib/generated/intl/messages_no.dart +++ b/lib/generated/intl/messages_no.dart @@ -33,6 +33,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Bekreft sletting av konto"), "confirmDeletePrompt": MessageLookupByLibrary.simpleMessage( "Ja, jeg ønsker å slette denne kontoen og all dataen dens permanent."), + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "deleteAccount": MessageLookupByLibrary.simpleMessage("Slett konto"), "deleteAccountFeedbackPrompt": MessageLookupByLibrary.simpleMessage( "Vi er lei oss for at du forlater oss. Gi oss gjerne en tilbakemelding så vi kan forbedre oss."), diff --git a/lib/generated/intl/messages_pl.dart b/lib/generated/intl/messages_pl.dart index 6fb8aa6f0..7a567715b 100644 --- a/lib/generated/intl/messages_pl.dart +++ b/lib/generated/intl/messages_pl.dart @@ -50,6 +50,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Powtórz hasło"), "contactSupport": MessageLookupByLibrary.simpleMessage( "Skontaktuj się z pomocą techniczną"), + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Kontynuuj"), "createAccount": MessageLookupByLibrary.simpleMessage("Stwórz konto"), "createNewAccount": diff --git a/lib/generated/intl/messages_pt.dart b/lib/generated/intl/messages_pt.dart index a873f19d4..9ddbbd8d9 100644 --- a/lib/generated/intl/messages_pt.dart +++ b/lib/generated/intl/messages_pt.dart @@ -136,6 +136,7 @@ class MessageLookup extends MessageLookupByLibrary { "Confirme sua chave de recuperação"), "contactSupport": MessageLookupByLibrary.simpleMessage("Falar com o suporte"), + "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuar"), "copypasteThisCodentoYourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( diff --git a/lib/generated/intl/messages_zh.dart b/lib/generated/intl/messages_zh.dart index 1e62fea04..b90353d47 100644 --- a/lib/generated/intl/messages_zh.dart +++ b/lib/generated/intl/messages_zh.dart @@ -127,6 +127,9 @@ class MessageLookup extends MessageLookupByLibrary { static String m41(endDate) => "在 ${endDate} 前续费"; + static String m65(count) => + "${Intl.plural(count, other: '已找到 ${count} 个结果')}"; + static String m42(count) => "已选择 ${count} 个"; static String m43(count, yourCount) => "选择了 ${count} 个 (您的 ${yourCount} 个)"; @@ -170,7 +173,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m59(count) => "${Intl.plural(count, zero: '', one: '1天', other: '${count} 天')}"; - static String m65(endDate) => "有效期至 ${endDate}"; + static String m66(endDate) => "有效期至 ${endDate}"; static String m60(email) => "验证 ${email}"; @@ -198,6 +201,7 @@ class MessageLookup extends MessageLookupByLibrary { "addLocation": MessageLookupByLibrary.simpleMessage("添加地点"), "addLocationButton": MessageLookupByLibrary.simpleMessage("添加"), "addMore": MessageLookupByLibrary.simpleMessage("添加更多"), + "addNew": MessageLookupByLibrary.simpleMessage("新建"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("附加组件详情"), "addOns": MessageLookupByLibrary.simpleMessage("附加组件"), "addPhotos": MessageLookupByLibrary.simpleMessage("添加照片"), @@ -206,6 +210,7 @@ class MessageLookup extends MessageLookupByLibrary { "addToEnte": MessageLookupByLibrary.simpleMessage("添加到 ente"), "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("添加到隐藏相册"), "addViewer": MessageLookupByLibrary.simpleMessage("添加查看者"), + "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("立即添加您的照片"), "addedAs": MessageLookupByLibrary.simpleMessage("已添加为"), "addedBy": m1, "addedSuccessfullyTo": m2, @@ -308,6 +313,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("通过移动数据备份"), "backupSettings": MessageLookupByLibrary.simpleMessage("备份设置"), "backupVideos": MessageLookupByLibrary.simpleMessage("备份视频"), + "blackFridaySale": MessageLookupByLibrary.simpleMessage("黑色星期五特惠"), "blog": MessageLookupByLibrary.simpleMessage("博客"), "cachedData": MessageLookupByLibrary.simpleMessage("缓存数据"), "calculating": MessageLookupByLibrary.simpleMessage("正在计算..."), @@ -374,6 +380,8 @@ class MessageLookup extends MessageLookupByLibrary { "contactFamilyAdmin": m9, "contactSupport": MessageLookupByLibrary.simpleMessage("联系支持"), "contactToManageSubscription": m10, + "contacts": MessageLookupByLibrary.simpleMessage("联系人"), + "contents": MessageLookupByLibrary.simpleMessage("内容"), "continueLabel": MessageLookupByLibrary.simpleMessage("继续"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage("继续免费试用"), "convertToAlbum": MessageLookupByLibrary.simpleMessage("转换为相册"), @@ -535,6 +543,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("此链接已过期。请选择新的过期时间或禁用链接过期。"), "exportLogs": MessageLookupByLibrary.simpleMessage("导出日志"), "exportYourData": MessageLookupByLibrary.simpleMessage("导出您的数据"), + "faces": MessageLookupByLibrary.simpleMessage("人脸"), "failedToApplyCode": MessageLookupByLibrary.simpleMessage("无法应用代码"), "failedToCancel": MessageLookupByLibrary.simpleMessage("取消失败"), "failedToDownloadVideo": MessageLookupByLibrary.simpleMessage("视频下载失败"), @@ -558,6 +567,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("无法将文件保存到相册"), "fileInfoAddDescHint": MessageLookupByLibrary.simpleMessage("添加说明..."), "fileSavedToGallery": MessageLookupByLibrary.simpleMessage("文件已保存到相册"), + "fileTypes": MessageLookupByLibrary.simpleMessage("文件类型"), + "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("文件类型和名称"), "filesBackedUpFromDevice": m19, "filesBackedUpInAlbum": m20, "filesDeleted": MessageLookupByLibrary.simpleMessage("文件已删除"), @@ -655,6 +666,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkExpiry": MessageLookupByLibrary.simpleMessage("链接过期"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("链接已过期"), "linkNeverExpires": MessageLookupByLibrary.simpleMessage("永不"), + "livePhotos": MessageLookupByLibrary.simpleMessage("实况照片"), "loadMessage1": MessageLookupByLibrary.simpleMessage("您可以与家庭分享您的订阅"), "loadMessage2": MessageLookupByLibrary.simpleMessage("到目前为止,我们已经保存了1 000多万个回忆"), @@ -710,8 +722,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("移动端, 网页端, 桌面端"), "moderateStrength": MessageLookupByLibrary.simpleMessage("中等"), "modifyYourQueryOrTrySearchingFor": - MessageLookupByLibrary.simpleMessage( - "Modify your query, or try searching for"), + MessageLookupByLibrary.simpleMessage("修改您的查询,或尝试搜索"), + "moments": MessageLookupByLibrary.simpleMessage("瞬间"), "monthly": MessageLookupByLibrary.simpleMessage("每月"), "moveItem": m30, "moveToAlbum": MessageLookupByLibrary.simpleMessage("移动到相册"), @@ -784,8 +796,10 @@ class MessageLookup extends MessageLookupByLibrary { "permanentlyDelete": MessageLookupByLibrary.simpleMessage("永久删除"), "permanentlyDeleteFromDevice": MessageLookupByLibrary.simpleMessage("要从设备中永久删除吗?"), + "photoDescriptions": MessageLookupByLibrary.simpleMessage("照片说明"), "photoGridSize": MessageLookupByLibrary.simpleMessage("照片网格大小"), "photoSmallCase": MessageLookupByLibrary.simpleMessage("照片"), + "photos": MessageLookupByLibrary.simpleMessage("照片"), "photosAddedByYouWillBeRemovedFromTheAlbum": MessageLookupByLibrary.simpleMessage("您添加的照片将从相册中移除"), "pickCenterPoint": MessageLookupByLibrary.simpleMessage("选择中心点"), @@ -908,10 +922,29 @@ class MessageLookup extends MessageLookupByLibrary { "scanCode": MessageLookupByLibrary.simpleMessage("扫描代码"), "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage("用您的身份验证器应用\n扫描此条码"), + "searchAlbumsEmptySection": MessageLookupByLibrary.simpleMessage("相册"), "searchByAlbumNameHint": MessageLookupByLibrary.simpleMessage("相册名称"), "searchByExamples": MessageLookupByLibrary.simpleMessage( "• 相册名称(例如“相机”)\n• 文件类型(例如“视频”、“.gif”)\n• 年份和月份(例如“2022”、“一月”)\n• 假期(例如“圣诞节”)\n• 照片说明(例如“#和女儿独居,好开心啊”)"), + "searchCaptionEmptySection": MessageLookupByLibrary.simpleMessage( + "在照片信息中添加“#旅游”等描述,以便在此处快速找到它们"), + "searchDatesEmptySection": + MessageLookupByLibrary.simpleMessage("按日期搜索,月份或年份"), + "searchFaceEmptySection": + MessageLookupByLibrary.simpleMessage("查找一个人的所有照片"), + "searchFileTypesAndNamesEmptySection": + MessageLookupByLibrary.simpleMessage("文件类型和名称"), + "searchHint1": MessageLookupByLibrary.simpleMessage("在设备上快速搜索"), + "searchHint2": MessageLookupByLibrary.simpleMessage("照片日期、描述"), + "searchHint3": MessageLookupByLibrary.simpleMessage("相册、文件名和类型"), + "searchHint4": MessageLookupByLibrary.simpleMessage("位置"), + "searchHint5": MessageLookupByLibrary.simpleMessage("即将到来:面部和魔法搜索✨"), "searchHintText": MessageLookupByLibrary.simpleMessage("相册,月,日,年,..."), + "searchLocationEmptySection": + MessageLookupByLibrary.simpleMessage("在照片的一定半径内拍摄的几组照片"), + "searchPeopleEmptySection": + MessageLookupByLibrary.simpleMessage("邀请他人,您将在此看到他们分享的所有照片"), + "searchResultCount": m65, "security": MessageLookupByLibrary.simpleMessage("安全"), "selectAlbum": MessageLookupByLibrary.simpleMessage("选择相册"), "selectAll": MessageLookupByLibrary.simpleMessage("全选"), @@ -1113,6 +1146,8 @@ class MessageLookup extends MessageLookupByLibrary { "upgrade": MessageLookupByLibrary.simpleMessage("升级"), "uploadingFilesToAlbum": MessageLookupByLibrary.simpleMessage("正在将文件上传到相册..."), + "upto50OffUntil4thDec": + MessageLookupByLibrary.simpleMessage("最高五折优惠,直至12月4日。"), "usableReferralStorageInfo": MessageLookupByLibrary.simpleMessage( "可用存储空间受您当前计划的限制。 当您升级您的计划时,超出要求的存储空间将自动变为可用。"), "usePublicLinksForPeopleNotOnEnte": @@ -1120,7 +1155,7 @@ class MessageLookup extends MessageLookupByLibrary { "useRecoveryKey": MessageLookupByLibrary.simpleMessage("使用恢复密钥"), "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("使用所选照片"), "usedSpace": MessageLookupByLibrary.simpleMessage("已用空间"), - "validTill": m65, + "validTill": m66, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage("验证失败,请重试"), "verificationId": MessageLookupByLibrary.simpleMessage("验证 ID"), @@ -1133,6 +1168,7 @@ class MessageLookup extends MessageLookupByLibrary { "verifyingRecoveryKey": MessageLookupByLibrary.simpleMessage("正在验证恢复密钥..."), "videoSmallCase": MessageLookupByLibrary.simpleMessage("视频"), + "videos": MessageLookupByLibrary.simpleMessage("视频"), "viewActiveSessions": MessageLookupByLibrary.simpleMessage("查看活动会话"), "viewAddOnButton": MessageLookupByLibrary.simpleMessage("查看附加组件"), "viewAll": MessageLookupByLibrary.simpleMessage("查看全部"), @@ -1178,7 +1214,7 @@ class MessageLookup extends MessageLookupByLibrary { "youHaveSuccessfullyFreedUp": m63, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("您的账户已删除"), - "yourMap": MessageLookupByLibrary.simpleMessage("Your map"), + "yourMap": MessageLookupByLibrary.simpleMessage("您的地图"), "yourPlanWasSuccessfullyDowngraded": MessageLookupByLibrary.simpleMessage("您的计划已成功降级"), "yourPlanWasSuccessfullyUpgraded": diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 523110e70..8e3ae83b7 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -3924,6 +3924,16 @@ class S { ); } + /// `Your {storageAmount} add-on is valid till {endDate}` + String addOnValidTill(Object storageAmount, Object endDate) { + return Intl.message( + 'Your $storageAmount add-on is valid till $endDate', + name: 'addOnValidTill', + desc: '', + args: [storageAmount, endDate], + ); + } + /// `Free trial valid till {endDate}.\nYou can choose a paid plan afterwards.` String playStoreFreeTrialValidTill(Object endDate) { return Intl.message( @@ -7995,10 +8005,10 @@ class S { ); } - /// `Coming soon: Photo contents, faces` + /// `Coming soon: Faces & magic search ✨` String get searchHint5 { return Intl.message( - 'Coming soon: Photo contents, faces', + 'Coming soon: Faces & magic search ✨', name: 'searchHint5', desc: '', args: [], diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index f3fca6a0c..1325d1b2e 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -558,6 +558,7 @@ "renewsOn": "Renews on {endDate}", "freeTrialValidTill": "Free trial valid till {endDate}", "validTill": "Valid till {endDate}", + "addOnValidTill": "Your {storageAmount} add-on is valid till {endDate}", "playStoreFreeTrialValidTill": "Free trial valid till {endDate}.\nYou can choose a paid plan afterwards.", "subWillBeCancelledOn": "Your subscription will be cancelled on {endDate}", "subscription": "Subscription", diff --git a/lib/ui/payment/store_subscription_page.dart b/lib/ui/payment/store_subscription_page.dart index d9a95f684..e544ca702 100644 --- a/lib/ui/payment/store_subscription_page.dart +++ b/lib/ui/payment/store_subscription_page.dart @@ -239,7 +239,7 @@ class _StoreSubscriptionPageState extends State { widgets.add(_showSubscriptionToggle()); } - if (_hasActiveSubscription) { + if (_currentSubscription != null) { widgets.add( ValidityWidget( currentSubscription: _currentSubscription, diff --git a/lib/ui/payment/stripe_subscription_page.dart b/lib/ui/payment/stripe_subscription_page.dart index 54a551b7d..b48e59f75 100644 --- a/lib/ui/payment/stripe_subscription_page.dart +++ b/lib/ui/payment/stripe_subscription_page.dart @@ -210,7 +210,7 @@ class _StripeSubscriptionPageState extends State { widgets.add(_showSubscriptionToggle()); - if (_hasActiveSubscription) { + if (_currentSubscription != null) { widgets.add( ValidityWidget( currentSubscription: _currentSubscription, diff --git a/lib/ui/payment/subscription_common_widgets.dart b/lib/ui/payment/subscription_common_widgets.dart index f2b8fe23f..6efdf56d7 100644 --- a/lib/ui/payment/subscription_common_widgets.dart +++ b/lib/ui/payment/subscription_common_widgets.dart @@ -98,9 +98,14 @@ class ValidityWidget extends StatelessWidget { if (currentSubscription == null) { return const SizedBox.shrink(); } + final List addOnBonus = bonusData?.getAddOnBonuses() ?? []; final bool isFreeTrialSub = currentSubscription!.productID == freeProductID; - if (isFreeTrialSub && (bonusData?.getAddOnBonuses().isNotEmpty ?? false)) { - return const SizedBox.shrink(); + bool hideSubValidityView = false; + if (isFreeTrialSub && addOnBonus.isNotEmpty) { + hideSubValidityView = true; + } + if (!currentSubscription!.isValid()) { + hideSubValidityView = true; } final endDate = DateFormat.yMMMd(Localizations.localeOf(context).languageCode).format( @@ -114,11 +119,45 @@ class ValidityWidget extends StatelessWidget { : S.of(context).freeTrialValidTill(endDate); } else if (currentSubscription!.attributes?.isCancelled ?? false) { message = S.of(context).subWillBeCancelledOn(endDate); + if (addOnBonus.isNotEmpty) { + hideSubValidityView = true; + } } + return Padding( - padding: const EdgeInsets.only(top: 8), + padding: const EdgeInsets.only(top: 0), + child: Column( + children: [ + if (!hideSubValidityView) + Text( + message, + style: Theme.of(context).textTheme.bodySmall, + textAlign: TextAlign.center, + ), + if (addOnBonus.isNotEmpty) + ...addOnBonus.map((bonus) => AddOnBonusValidity(bonus)).toList(), + ], + ), + ); + } +} + +class AddOnBonusValidity extends StatelessWidget { + final Bonus bonus; + + const AddOnBonusValidity(this.bonus, {super.key}); + + @override + Widget build(BuildContext context) { + final endDate = + DateFormat.yMMMd(Localizations.localeOf(context).languageCode).format( + DateTime.fromMicrosecondsSinceEpoch(bonus.validTill), + ); + final String storage = formatBytes(bonus.storage); + return Padding( + padding: const EdgeInsets.only(top: 8, bottom: 8), child: Text( - message, + S.of(context).addOnValidTill(storage, endDate), style: Theme.of(context).textTheme.bodySmall, textAlign: TextAlign.center, ), From 3fbf7be3ab0b8482e7e8917f65b48490d51b93bb Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 20 Nov 2023 19:23:39 +0530 Subject: [PATCH 07/10] Toggle current sub active flag based on add-on Signed-off-by: Neeraj Gupta <254676+ua741@users.noreply.github.com> --- lib/ui/payment/store_subscription_page.dart | 6 +++++- lib/ui/payment/stripe_subscription_page.dart | 12 ++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/ui/payment/store_subscription_page.dart b/lib/ui/payment/store_subscription_page.dart index e544ca702..722d6d5d2 100644 --- a/lib/ui/payment/store_subscription_page.dart +++ b/lib/ui/payment/store_subscription_page.dart @@ -52,6 +52,7 @@ class _StoreSubscriptionPageState extends State { late ProgressDialog _dialog; late UserDetails _userDetails; late bool _hasActiveSubscription; + bool _hideCurrentPlanSelection = false; late FreePlan _freePlan; late List _plans; bool _hasLoadedData = false; @@ -177,7 +178,10 @@ class _StoreSubscriptionPageState extends State { _userService.getUserDetailsV2(memoryCount: false).then((userDetails) async { _userDetails = userDetails; _currentSubscription = userDetails.subscription; + _hasActiveSubscription = _currentSubscription!.isValid(); + _hideCurrentPlanSelection = + _currentSubscription?.attributes?.isCancelled ?? false; showYearlyPlan = _currentSubscription!.isYearlyPlan(); final billingPlans = await _billingService.getBillingPlans(); _isActiveStripeSubscriber = @@ -458,7 +462,7 @@ class _StoreSubscriptionPageState extends State { storage: plan.storage, price: plan.price, period: plan.period, - isActive: isActive, + isActive: isActive && !_hideCurrentPlanSelection, ), ), ), diff --git a/lib/ui/payment/stripe_subscription_page.dart b/lib/ui/payment/stripe_subscription_page.dart index b48e59f75..e205fb062 100644 --- a/lib/ui/payment/stripe_subscription_page.dart +++ b/lib/ui/payment/stripe_subscription_page.dart @@ -53,6 +53,7 @@ class _StripeSubscriptionPageState extends State { // indicates if user's subscription plan is still active late bool _hasActiveSubscription; + bool _hideCurrentPlanSelection = false; late FreePlan _freePlan; List _plans = []; bool _hasLoadedData = false; @@ -73,7 +74,11 @@ class _StripeSubscriptionPageState extends State { .then((userDetails) async { _userDetails = userDetails; _currentSubscription = userDetails.subscription; + _showYearlyPlan = _currentSubscription!.isYearlyPlan(); + _hideCurrentPlanSelection = + (_currentSubscription?.attributes?.isCancelled ?? false) && + userDetails.hasPaidAddon(); _hasActiveSubscription = _currentSubscription!.isValid(); _isStripeSubscriber = _currentSubscription!.paymentProvider == stripe; return _filterStripeForUI().then((value) { @@ -340,6 +345,9 @@ class _StripeSubscriptionPageState extends State { Widget _stripeRenewOrCancelButton() { final bool isRenewCancelled = _currentSubscription!.attributes?.isCancelled ?? false; + if (isRenewCancelled && _userDetails.hasPaidAddon()) { + return const SizedBox.shrink(); + } final String title = isRenewCancelled ? S.of(context).renewSubscription : S.of(context).cancelSubscription; @@ -503,7 +511,7 @@ class _StripeSubscriptionPageState extends State { storage: plan.storage, price: plan.price, period: plan.period, - isActive: isActive, + isActive: isActive && !_hideCurrentPlanSelection, ), ), ), @@ -594,7 +602,7 @@ class _StripeSubscriptionPageState extends State { storage: _currentSubscription!.storage, price: _currentSubscription!.price, period: _currentSubscription!.period, - isActive: true, + isActive: !_hasActiveSubscription, ), ), ), From 7c4b389ef4e1ec99f09574af2a7a515f94199e05 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 20 Nov 2023 19:24:41 +0530 Subject: [PATCH 08/10] Update copy Signed-off-by: Neeraj Gupta <254676+ua741@users.noreply.github.com> --- lib/generated/intl/messages_en.dart | 2 +- lib/generated/l10n.dart | 5 +++-- lib/l10n/intl_en.arb | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 726f34076..f7425cb81 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -138,7 +138,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m40(userEmail) => "${userEmail} will be removed from this shared album\n\nAny photos added by them will also be removed from the album"; - static String m41(endDate) => "Renews on ${endDate}"; + static String m41(endDate) => "Subscription renews on ${endDate}"; static String m65(count) => "${Intl.plural(count, one: '${count} result found', other: '${count} results found')}"; diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 8e3ae83b7..17dea8919 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -1,6 +1,7 @@ // GENERATED CODE - DO NOT MODIFY BY HAND import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; + import 'intl/messages_all.dart'; // ************************************************************************** @@ -3894,10 +3895,10 @@ class S { ); } - /// `Renews on {endDate}` + /// `Subscription renews on {endDate}` String renewsOn(Object endDate) { return Intl.message( - 'Renews on $endDate', + 'Subscription renews on $endDate', name: 'renewsOn', desc: '', args: [endDate], diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 1325d1b2e..bd14aa9c6 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -555,7 +555,7 @@ "type": "text" }, "faqs": "FAQs", - "renewsOn": "Renews on {endDate}", + "renewsOn": "Subscription renews on {endDate}", "freeTrialValidTill": "Free trial valid till {endDate}", "validTill": "Valid till {endDate}", "addOnValidTill": "Your {storageAmount} add-on is valid till {endDate}", From 6b15e214f71a36901129539f8fc3229f07ef5043 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 20 Nov 2023 19:26:00 +0530 Subject: [PATCH 09/10] Switch to different formatter for stroage Signed-off-by: Neeraj Gupta <254676+ua741@users.noreply.github.com> --- lib/ui/payment/subscription_common_widgets.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/payment/subscription_common_widgets.dart b/lib/ui/payment/subscription_common_widgets.dart index 6efdf56d7..c33f26d79 100644 --- a/lib/ui/payment/subscription_common_widgets.dart +++ b/lib/ui/payment/subscription_common_widgets.dart @@ -153,7 +153,7 @@ class AddOnBonusValidity extends StatelessWidget { DateFormat.yMMMd(Localizations.localeOf(context).languageCode).format( DateTime.fromMicrosecondsSinceEpoch(bonus.validTill), ); - final String storage = formatBytes(bonus.storage); + final String storage = convertBytesToReadableFormat(bonus.storage); return Padding( padding: const EdgeInsets.only(top: 8, bottom: 8), child: Text( From e1314c1b9829743e0fb63e82732f99f06124d5a1 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 20 Nov 2023 19:35:43 +0530 Subject: [PATCH 10/10] Bump version: 0.8.1+521 --- lib/generated/intl/messages_fr.dart | 8 ++++---- lib/generated/intl/messages_zh.dart | 11 +++++++---- pubspec.yaml | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/generated/intl/messages_fr.dart b/lib/generated/intl/messages_fr.dart index 79391df74..4a76e7b4e 100644 --- a/lib/generated/intl/messages_fr.dart +++ b/lib/generated/intl/messages_fr.dart @@ -140,7 +140,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m41(endDate) => "Renouvellement le ${endDate}"; - static String m64(count) => + static String m65(count) => "${Intl.plural(count, one: '${count} résultat trouvé', other: '${count} résultats trouvés')}"; static String m42(count) => "${count} sélectionné(s)"; @@ -192,7 +192,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m59(count) => "${Intl.plural(count, zero: '0 jour', one: '1 jour', other: '${count} jours')}"; - static String m65(endDate) => "Valable jusqu\'au ${endDate}"; + static String m66(endDate) => "Valable jusqu\'au ${endDate}"; static String m60(email) => "Vérifier ${email}"; @@ -1193,7 +1193,7 @@ class MessageLookup extends MessageLookupByLibrary { "Grouper les photos qui sont prises dans un certain angle d\'une photo"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Invitez des gens, et vous verrez ici toutes les photos qu\'ils partagent"), - "searchResultCount": m64, + "searchResultCount": m65, "security": MessageLookupByLibrary.simpleMessage("Sécurité"), "selectAlbum": MessageLookupByLibrary.simpleMessage("Sélectionner album"), @@ -1463,7 +1463,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage( "Utiliser la photo sélectionnée"), "usedSpace": MessageLookupByLibrary.simpleMessage("Mémoire utilisée"), - "validTill": m65, + "validTill": m66, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "La vérification a échouée, veuillez réessayer"), diff --git a/lib/generated/intl/messages_zh.dart b/lib/generated/intl/messages_zh.dart index 9370da75e..674da416c 100644 --- a/lib/generated/intl/messages_zh.dart +++ b/lib/generated/intl/messages_zh.dart @@ -127,7 +127,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m41(endDate) => "在 ${endDate} 前续费"; - static String m64(count) => + static String m65(count) => "${Intl.plural(count, other: '已找到 ${count} 个结果')}"; static String m42(count) => "已选择 ${count} 个"; @@ -173,7 +173,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m59(count) => "${Intl.plural(count, zero: '', one: '1天', other: '${count} 天')}"; - static String m65(endDate) => "有效期至 ${endDate}"; + static String m66(endDate) => "有效期至 ${endDate}"; static String m60(email) => "验证 ${email}"; @@ -749,6 +749,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("没有隐藏的照片或视频"), "noImagesWithLocation": MessageLookupByLibrary.simpleMessage("没有带有位置的图像"), + "noInternetConnection": MessageLookupByLibrary.simpleMessage("无互联网连接"), "noPhotosAreBeingBackedUpRightNow": MessageLookupByLibrary.simpleMessage("目前没有照片正在备份"), "noPhotosFoundHere": MessageLookupByLibrary.simpleMessage("这里没有找到照片"), @@ -807,6 +808,8 @@ class MessageLookup extends MessageLookupByLibrary { "playStoreFreeTrialValidTill": m35, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore 订阅"), + "pleaseCheckYourInternetConnectionAndTryAgain": + MessageLookupByLibrary.simpleMessage("请检查您的互联网连接,然后重试。"), "pleaseContactSupportAndWeWillBeHappyToHelp": MessageLookupByLibrary.simpleMessage( "请用英语联系 support@ente.io ,我们将乐意提供帮助!"), @@ -944,7 +947,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("在照片的一定半径内拍摄的几组照片"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage("邀请他人,您将在此看到他们分享的所有照片"), - "searchResultCount": m64, + "searchResultCount": m65, "security": MessageLookupByLibrary.simpleMessage("安全"), "selectAlbum": MessageLookupByLibrary.simpleMessage("选择相册"), "selectAll": MessageLookupByLibrary.simpleMessage("全选"), @@ -1155,7 +1158,7 @@ class MessageLookup extends MessageLookupByLibrary { "useRecoveryKey": MessageLookupByLibrary.simpleMessage("使用恢复密钥"), "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("使用所选照片"), "usedSpace": MessageLookupByLibrary.simpleMessage("已用空间"), - "validTill": m65, + "validTill": m66, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage("验证失败,请重试"), "verificationId": MessageLookupByLibrary.simpleMessage("验证 ID"), diff --git a/pubspec.yaml b/pubspec.yaml index e5ca90dd6..769948d6c 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.8.0+520 +version: 0.8.1+521 environment: sdk: ">=3.0.0 <4.0.0"