diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 6b9372efe..05fb5eff3 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -14,6 +14,7 @@
+- [ ] 🖼️ New icon
- [ ] ✨ New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6befa7976..3ceae8071 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -25,7 +25,7 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: "stable"
- flutter-version: "3.10.6"
+ flutter-version: "3.13.4"
# Fetch sub modules
- run: git submodule update --init --recursive
diff --git a/assets/custom-icons/_data/custom-icons.json b/assets/custom-icons/_data/custom-icons.json
index 8e3410842..1341b29e6 100644
--- a/assets/custom-icons/_data/custom-icons.json
+++ b/assets/custom-icons/_data/custom-icons.json
@@ -1,24 +1,175 @@
{
"icons": [
+ {
+ "title": "3Commas"
+ },
+ {
+ "title": "Addy.io",
+ "slug": "addy_io"
+ },
+ {
+ "title": "Anycoin Direct",
+ "slug": "anycoindirect"
+ },
+ {
+ "title": "AscendEX"
+ },
+ {
+ "title": "BitMEX"
+ },
+ {
+ "title": "Bitfinex"
+ },
+ {
+ "title": "Bitvavo",
+ "hex": "0051FF"
+ },
+ {
+ "title": "Bybit"
+ },
+ {
+ "title": "Channel Island Hosting",
+ "slug": "cih",
+ "hex": "D14633"
+ },
+ {
+ "title": "Control D",
+ "hex": "5FD800"
+ },
{
"title": "ente",
"hex": "1DB954"
},
+ {
+ "title": "Filen",
+ "hex": "858585"
+ },
{
"title": "Github",
"hex": "858585"
},
+ {
+ "title": "Google"
+ },
+ {
+ "title": "ING"
+ },
+ {
+ "title": "Jagex",
+ "hex": "D3D800"
+ },
+ {
+ "title": "KPN",
+ "color": "00CC00"
+ },
+ {
+ "title": "Kick",
+ "hex": "53FC19"
+ },
+ {
+ "title": "Kraken",
+ "hex": "5848D5"
+ },
+ {
+ "title": "Kronos"
+ },
+ {
+ "title": "KuCoin",
+ "hex": "01BC8D"
+ },
+ {
+ "title": "ngrok",
+ "hex": "858585"
+ },
+ {
+ "title": "Njalla"
+ },
+ {
+ "title": "Odido"
+ },
+ {
+ "title": "Parsec"
+ },
+ {
+ "title": "Peerberry",
+ "hex": "03E5A5"
+ },
+ {
+ "title": "Plutus",
+ "hex": "DEC685"
+ },
+ {
+ "title": "Poloniex"
+ },
{
"title": "Porkbun",
"hex": "F27777"
},
+ {
+ "title": "PostNL",
+ "color": "EF8300"
+ },
+ {
+ "title": "Privacy Guides"
+ },
+ {
+ "title": "Privacy.com"
+ },
+ {
+ "title": "Revolt",
+ "hex": "858585"
+ },
+ {
+ "title": "SimpleLogin"
+ },
+ {
+ "title": "Standard Notes",
+ "hex": "2173E6"
+ },
+ {
+ "title": "Techlore"
+ },
+ {
+ "title": "Termius",
+ "hex": "858585"
+ },
+ {
+ "title": "Trading 212",
+ "hex": "4BA4DE"
+ },
+ {
+ "title": "TradingView"
+ },
+ {
+ "title": "TransIP"
+ },
+ {
+ "title": "Tresorit"
+ },
+ {
+ "title": "Tweakers"
+ },
+ {
+ "title": "Twingate",
+ "hex": "858585"
+ },
+ {
+ "title": "Ubisoft",
+ "hex": "4285f4"
+ },
+ {
+ "title": "Unity",
+ "hex": "858585"
+ },
+ {
+ "title": "WHMCS"
+ },
{
"title": "Windscribe",
"hex": "858585"
},
{
- "title": "Kick",
- "hex": "53FC19"
+ "title": "Wise"
}
]
}
diff --git a/assets/custom-icons/icons/3commas.svg b/assets/custom-icons/icons/3commas.svg
new file mode 100644
index 000000000..759756347
--- /dev/null
+++ b/assets/custom-icons/icons/3commas.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/addy_io.svg b/assets/custom-icons/icons/addy_io.svg
new file mode 100644
index 000000000..04316d510
--- /dev/null
+++ b/assets/custom-icons/icons/addy_io.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/anycoindirect.svg b/assets/custom-icons/icons/anycoindirect.svg
new file mode 100644
index 000000000..964a5946c
--- /dev/null
+++ b/assets/custom-icons/icons/anycoindirect.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/custom-icons/icons/ascendex.svg b/assets/custom-icons/icons/ascendex.svg
new file mode 100644
index 000000000..5551f5591
--- /dev/null
+++ b/assets/custom-icons/icons/ascendex.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/custom-icons/icons/bitfinex.svg b/assets/custom-icons/icons/bitfinex.svg
new file mode 100644
index 000000000..c93635268
--- /dev/null
+++ b/assets/custom-icons/icons/bitfinex.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/bitmex.svg b/assets/custom-icons/icons/bitmex.svg
new file mode 100644
index 000000000..38821552b
--- /dev/null
+++ b/assets/custom-icons/icons/bitmex.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/bitvavo.svg b/assets/custom-icons/icons/bitvavo.svg
new file mode 100644
index 000000000..224896c0d
--- /dev/null
+++ b/assets/custom-icons/icons/bitvavo.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/bybit.svg b/assets/custom-icons/icons/bybit.svg
new file mode 100644
index 000000000..e5c2c8c11
--- /dev/null
+++ b/assets/custom-icons/icons/bybit.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/custom-icons/icons/cih.svg b/assets/custom-icons/icons/cih.svg
new file mode 100644
index 000000000..53c1b321d
--- /dev/null
+++ b/assets/custom-icons/icons/cih.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/controld.svg b/assets/custom-icons/icons/controld.svg
new file mode 100644
index 000000000..068d73c3e
--- /dev/null
+++ b/assets/custom-icons/icons/controld.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/filen.svg b/assets/custom-icons/icons/filen.svg
new file mode 100644
index 000000000..bc8d69ea8
--- /dev/null
+++ b/assets/custom-icons/icons/filen.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/google.svg b/assets/custom-icons/icons/google.svg
new file mode 100644
index 000000000..986851c02
--- /dev/null
+++ b/assets/custom-icons/icons/google.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/ing.svg b/assets/custom-icons/icons/ing.svg
new file mode 100644
index 000000000..16a75bb89
--- /dev/null
+++ b/assets/custom-icons/icons/ing.svg
@@ -0,0 +1 @@
+
diff --git a/assets/custom-icons/icons/jagex.svg b/assets/custom-icons/icons/jagex.svg
new file mode 100644
index 000000000..d11665084
--- /dev/null
+++ b/assets/custom-icons/icons/jagex.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/kpn.svg b/assets/custom-icons/icons/kpn.svg
new file mode 100644
index 000000000..ba1c9a16e
--- /dev/null
+++ b/assets/custom-icons/icons/kpn.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/kraken.svg b/assets/custom-icons/icons/kraken.svg
new file mode 100644
index 000000000..f38ee454c
--- /dev/null
+++ b/assets/custom-icons/icons/kraken.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/kronos.svg b/assets/custom-icons/icons/kronos.svg
new file mode 100644
index 000000000..c43b42a64
--- /dev/null
+++ b/assets/custom-icons/icons/kronos.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/kucoin.svg b/assets/custom-icons/icons/kucoin.svg
new file mode 100644
index 000000000..076ec5c4f
--- /dev/null
+++ b/assets/custom-icons/icons/kucoin.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/ngrok.svg b/assets/custom-icons/icons/ngrok.svg
new file mode 100644
index 000000000..a708247a2
--- /dev/null
+++ b/assets/custom-icons/icons/ngrok.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/njalla.svg b/assets/custom-icons/icons/njalla.svg
new file mode 100644
index 000000000..02e4551fa
--- /dev/null
+++ b/assets/custom-icons/icons/njalla.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/odido.svg b/assets/custom-icons/icons/odido.svg
new file mode 100644
index 000000000..7fef3d7e9
--- /dev/null
+++ b/assets/custom-icons/icons/odido.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/parsec.svg b/assets/custom-icons/icons/parsec.svg
new file mode 100644
index 000000000..734d0874c
--- /dev/null
+++ b/assets/custom-icons/icons/parsec.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/peerberry.svg b/assets/custom-icons/icons/peerberry.svg
new file mode 100644
index 000000000..72e8b6973
--- /dev/null
+++ b/assets/custom-icons/icons/peerberry.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/plutus.svg b/assets/custom-icons/icons/plutus.svg
new file mode 100644
index 000000000..6a88dc417
--- /dev/null
+++ b/assets/custom-icons/icons/plutus.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/poloniex.svg b/assets/custom-icons/icons/poloniex.svg
new file mode 100644
index 000000000..37ad09e2b
--- /dev/null
+++ b/assets/custom-icons/icons/poloniex.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/postnl.svg b/assets/custom-icons/icons/postnl.svg
new file mode 100644
index 000000000..3aa941518
--- /dev/null
+++ b/assets/custom-icons/icons/postnl.svg
@@ -0,0 +1 @@
+
diff --git a/assets/custom-icons/icons/privacy.svg b/assets/custom-icons/icons/privacy.svg
new file mode 100644
index 000000000..7576204d8
--- /dev/null
+++ b/assets/custom-icons/icons/privacy.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/custom-icons/icons/privacyguides.svg b/assets/custom-icons/icons/privacyguides.svg
new file mode 100644
index 000000000..113fe2d87
--- /dev/null
+++ b/assets/custom-icons/icons/privacyguides.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/revolt.svg b/assets/custom-icons/icons/revolt.svg
new file mode 100644
index 000000000..5628f727e
--- /dev/null
+++ b/assets/custom-icons/icons/revolt.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/simplelogin.svg b/assets/custom-icons/icons/simplelogin.svg
new file mode 100644
index 000000000..1f4e00056
--- /dev/null
+++ b/assets/custom-icons/icons/simplelogin.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/standardnotes.svg b/assets/custom-icons/icons/standardnotes.svg
new file mode 100644
index 000000000..89fb3ed57
--- /dev/null
+++ b/assets/custom-icons/icons/standardnotes.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/techlore.svg b/assets/custom-icons/icons/techlore.svg
new file mode 100644
index 000000000..3def3f488
--- /dev/null
+++ b/assets/custom-icons/icons/techlore.svg
@@ -0,0 +1,44 @@
+
diff --git a/assets/custom-icons/icons/termius.svg b/assets/custom-icons/icons/termius.svg
new file mode 100644
index 000000000..a535507c1
--- /dev/null
+++ b/assets/custom-icons/icons/termius.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/trading212.svg b/assets/custom-icons/icons/trading212.svg
new file mode 100644
index 000000000..bce71b5c8
--- /dev/null
+++ b/assets/custom-icons/icons/trading212.svg
@@ -0,0 +1 @@
+
diff --git a/assets/custom-icons/icons/tradingview.svg b/assets/custom-icons/icons/tradingview.svg
new file mode 100644
index 000000000..998162fb9
--- /dev/null
+++ b/assets/custom-icons/icons/tradingview.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/custom-icons/icons/transip.svg b/assets/custom-icons/icons/transip.svg
new file mode 100644
index 000000000..7f35566e8
--- /dev/null
+++ b/assets/custom-icons/icons/transip.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/tresorit.svg b/assets/custom-icons/icons/tresorit.svg
new file mode 100644
index 000000000..ae7bba0aa
--- /dev/null
+++ b/assets/custom-icons/icons/tresorit.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/tweakers.svg b/assets/custom-icons/icons/tweakers.svg
new file mode 100644
index 000000000..36a948725
--- /dev/null
+++ b/assets/custom-icons/icons/tweakers.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/custom-icons/icons/twingate.svg b/assets/custom-icons/icons/twingate.svg
new file mode 100644
index 000000000..75d36c7f0
--- /dev/null
+++ b/assets/custom-icons/icons/twingate.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/ubisoft.svg b/assets/custom-icons/icons/ubisoft.svg
new file mode 100644
index 000000000..c1c69620c
--- /dev/null
+++ b/assets/custom-icons/icons/ubisoft.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/unity.svg b/assets/custom-icons/icons/unity.svg
new file mode 100644
index 000000000..a373b95af
--- /dev/null
+++ b/assets/custom-icons/icons/unity.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/whmcs.svg b/assets/custom-icons/icons/whmcs.svg
new file mode 100644
index 000000000..6aa398c3f
--- /dev/null
+++ b/assets/custom-icons/icons/whmcs.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/custom-icons/icons/wise.svg b/assets/custom-icons/icons/wise.svg
new file mode 100644
index 000000000..71aadde59
--- /dev/null
+++ b/assets/custom-icons/icons/wise.svg
@@ -0,0 +1,3 @@
+
diff --git a/flutter b/flutter
index f468f3366..367f9ea16 160000
--- a/flutter
+++ b/flutter
@@ -1 +1 @@
-Subproject commit f468f3366c26a5092eb964a230ce7892fda8f2f8
+Subproject commit 367f9ea16bfae1ca451b9cc27c1366870b187ae2
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 12b94099d..219a8441c 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -159,7 +159,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1300;
+ LastUpgradeCheck = 1430;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index c87d15a33..a6b826db2 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
ente to support this project",
+ "supportDevs": "Subscribe to ente to support us",
"supportDiscount": "Use coupon code \"AUTH\" to get 10% off first year",
"changeEmail": "Change email",
"changePassword": "Change password",
@@ -92,6 +92,7 @@
"importCodeDelimiterInfo": "The codes can be separated by a comma or a new line",
"selectFile": "Select file",
"emailVerificationToggle": "Email verification",
+ "emailVerificationEnableWarning": "If you are storing the 2FA to your email with us, turning on email verification could result in a deadlock. If you are locked out of one service, you might not be able to log in to the other.",
"authToChangeEmailVerificationSetting": "Please authenticate to change email verification",
"authToViewYourRecoveryKey": "Please authenticate to view your recovery key",
"authToChangeYourEmail": "Please authenticate to change your email",
@@ -329,5 +330,8 @@
"sigInBackupReminder": "Please export your codes to ensure that you have a backup you can restore from.",
"offlineModeWarning": "You have chosen to proceed without backups. Please take manual backups to make sure your codes are safe.",
"showLargeIcons": "Show large icons",
- "focusOnSearchBar": "Focus search on app start"
+ "shouldHideCode": "Hide codes",
+ "focusOnSearchBar": "Focus search on app start",
+ "confirmUpdatingkey": "Are you sure you want to update the secret key?",
+ "minimizeAppOnCopy": "Minimize app on copy"
}
diff --git a/lib/l10n/arb/app_fr.arb b/lib/l10n/arb/app_fr.arb
index 3652b7310..552dada67 100644
--- a/lib/l10n/arb/app_fr.arb
+++ b/lib/l10n/arb/app_fr.arb
@@ -9,8 +9,12 @@
"onBoardingGetStarted": "Premiers pas",
"setupFirstAccount": "Configurez votre premier compte",
"importScanQrCode": "Scannez un QR Code",
+ "qrCode": "QR Code",
"importEnterSetupKey": "Saisir une clé de configuration",
"importAccountPageTitle": "Saisir les détails du compte",
+ "bothIssuerAndAccountCanNotBeEmpty": "L'émetteur et le compte ne peuvent pas être vides",
+ "incorrectDetails": "Détails incorrects",
+ "pleaseVerifyDetails": "Veuillez vérifier vos informations et réessayez",
"codeIssuerHint": "Émetteur",
"codeSecretKeyHint": "Clé secrète",
"codeAccountHint": "Compte (vous@domaine.fr)",
@@ -53,6 +57,9 @@
}
},
"contactSupport": "Contacter le support",
+ "rateUsOnStore": "Notez-nous sur {storeName}",
+ "blog": "Blog",
+ "merchandise": "Marchandise",
"verifyPassword": "Vérifier le mot de passe",
"pleaseWait": "Veuillez patienter...",
"generatingEncryptionKeysTitle": "Génération des clés de chiffrement...",
@@ -68,13 +75,23 @@
"changePassword": "Modifier le mot de passe",
"data": "Données",
"importCodes": "Importer les codes",
+ "importTypePlainText": "Texte brut",
+ "importTypeEnteEncrypted": "ente Exportation chiffrée",
+ "passwordForDecryptingExport": "Mot de passe pour déchiffrer l'exportation",
+ "passwordEmptyError": "Le mot de passe ne peut pas être vide",
+ "importFromApp": "Importer des codes depuis {appName}",
+ "importGoogleAuthGuide": "Exportez vos comptes depuis Google Authenticator vers un code QR en utilisant l'option \"Transférer des comptes\". Ensuite, en utilisant un autre appareil, scannez le code QR.\n\nAstuce : Vous pouvez utiliser la webcam de votre ordinateur portable pour prendre une photo du code QR.",
"importSelectJsonFile": "Sélectionnez un fichier JSON",
"importEnteEncGuide": "Sélectionnez le fichier JSON chiffré exporté à partir de ente",
+ "importRaivoGuide": "Utilisez l'option \"Exporter les OTPs vers l'archive Zip\" dans les paramètres de Raivo.\n\nExtrayez le fichier zip et importez le fichier JSON.",
+ "importAegisGuide": "Utilisez l'option \"Exporter le coffre-fort\" dans les paramètres d'Aegis.\n\nSi votre coffre-fort est crypté, vous devrez saisir le mot de passe du coffre-fort pour déchiffrer le coffre-fort.",
"exportCodes": "Exporter les codes",
+ "importLabel": "Importer",
"importInstruction": "Veuillez sélectionner un fichier qui contient une liste de vos codes dans le format suivant",
"importCodeDelimiterInfo": "Les codes peuvent être séparés par une virgule ou un retour à la ligne",
"selectFile": "Sélectionner le fichier",
"emailVerificationToggle": "Vérification de l'adresse e-mail",
+ "emailVerificationEnableWarning": "Si vous stockez le 2FA dans votre e-mail avec nous, l'activation de la vérification d'e-mail pourrait entraîner un blocage. Si vous êtes exclu d'un service, il se peut que vous ne puissiez pas vous connecter à l'autre.",
"authToChangeEmailVerificationSetting": "Veuillez vous authentifier pour modifier votre adresse e-mail",
"authToViewYourRecoveryKey": "Veuillez vous authentifier pour afficher votre clé de récupération",
"authToChangeYourEmail": "Veuillez vous authentifier pour modifier votre adresse e-mail",
@@ -85,6 +102,7 @@
"no": "Non",
"email": "E-mail",
"support": "Support",
+ "general": "Général",
"settings": "Paramètres",
"copied": "Copié",
"pleaseTryAgain": "Veuillez réessayer",
@@ -96,12 +114,16 @@
"oops": "Oups",
"suggestFeatures": "Suggérer des fonctionnalités",
"faq": "FAQ",
+ "faq_q_1": "Quelle est la sécurité de ente Auth?",
+ "faq_a_1": "Tous les codes que vous sauvegardez via ente sont stockés de bout en bout. Cela signifie que vous seul pouvez accéder à vos codes. Nos applications sont open source et notre cryptographie a été auditée à l'extérieur.",
"faq_q_2": "Puis-je accéder à mes codes sur mon ordinateur ?",
"faq_a_2": "Vous pouvez accéder à vos codes sur le web via auth.ente.io.",
"faq_q_3": "Comment puis-je supprimer des codes ?",
"faq_a_3": "Vous pouvez supprimer un code en glissant vers la gauche.",
"faq_q_4": "Comment puis-je soutenir le projet?",
"faq_a_4": "Vous pouvez soutenir le développement de ce projet en vous abonnant à notre application Photos, ente.io.",
+ "faq_q_5": "Comment puis-je activer le verrou FaceID en ente Auth",
+ "faq_a_5": "Vous pouvez activer le verrouillage FaceID dans Paramètres → Sécurité → Écran de verrouillage.",
"somethingWentWrongMessage": "Quelque chose s'est mal passé, veuillez recommencer",
"leaveFamily": "Quitter le plan familial",
"leaveFamilyMessage": "Êtes-vous certains de vouloir quitter le plan familial?",
@@ -162,6 +184,7 @@
"enterDetailsManually": "Saisir les détails manuellement",
"edit": "Éditer",
"copiedToClipboard": "Copié dans le presse-papiers",
+ "copiedNextToClipboard": "Copié le code suivant dans le presse-papiers",
"error": "Erreur",
"recoveryKeyCopiedToClipboard": "Clé de récupération copiée dans le presse-papiers",
"recoveryKeyOnForgotPassword": "Si vous oubliez votre mot de passe, la seule façon de récupérer vos données sera grâce à cette clé.",
@@ -232,6 +255,10 @@
"privacy": "Confidentialité",
"terms": "Conditions",
"checkForUpdates": "Vérifier les mises à jour",
+ "downloadUpdate": "Télécharger",
+ "criticalUpdateAvailable": "Mise à jour critique disponible",
+ "updateAvailable": "Une mise à jour est disponible",
+ "update": "Mise à jour",
"checking": "Vérification...",
"youAreOnTheLatestVersion": "Vous êtes sur la dernière version",
"warning": "Attention",
@@ -290,5 +317,18 @@
"incorrectRecoveryKey": "Clé de récupération non valide",
"theRecoveryKeyYouEnteredIsIncorrect": "La clé de récupération que vous avez entrée est incorrecte",
"enterPassword": "Saisissez le mot de passe",
- "export": "Exporter"
+ "selectExportFormat": "Choisir le format d'exportation",
+ "exportDialogDesc": "Les exportations chiffrées seront protégées par un mot de passe de votre choix.",
+ "encrypted": "Chiffré",
+ "plainText": "Texte brut",
+ "passwordToEncryptExport": "Mot de passe pour chiffrer l'export",
+ "export": "Exporter",
+ "useOffline": "Utiliser sans sauvegardes",
+ "signInToBackup": "Connectez-vous pour sauvegarder vos codes",
+ "singIn": "Se connecter",
+ "sigInBackupReminder": "Veuillez exporter vos codes pour vous assurer que vous avez une sauvegarde à partir de laquelle vous pouvez restaurer.",
+ "offlineModeWarning": "Vous avez choisi de procéder sans sauvegarde. Veuillez prendre des sauvegardes manuelles pour vous assurer que vos codes sont sûrs.",
+ "showLargeIcons": "Afficher les grandes icônes",
+ "shouldHideCode": "Cacher les codes",
+ "focusOnSearchBar": "Cibler le champ de recherche au démarrage de l'application"
}
\ No newline at end of file
diff --git a/lib/l10n/arb/app_it.arb b/lib/l10n/arb/app_it.arb
index 72dbf0282..94143da3b 100644
--- a/lib/l10n/arb/app_it.arb
+++ b/lib/l10n/arb/app_it.arb
@@ -92,6 +92,7 @@
"importCodeDelimiterInfo": "I codici possono essere separati da una virgola o da una nuova riga",
"selectFile": "Seleziona file",
"emailVerificationToggle": "Verifica email",
+ "emailVerificationEnableWarning": "Se memorizzate il 2FA per accedere alla vostra email con noi, l'attivazione della verifica dell'email potrebbe provocare dei problemi. Se siete rimasti bloccati fuori da un servizio, potreste non essere in grado di accedere anche all'altro.",
"authToChangeEmailVerificationSetting": "Autenticati per cambiare la verifica email",
"authToViewYourRecoveryKey": "Autenticati per visualizzare la tua chiave di recupero",
"authToChangeYourEmail": "Autenticati per cambiare la tua email",
@@ -329,5 +330,6 @@
"sigInBackupReminder": "Si prega di esportare i codici per assicurarsi di avere un backup da cui è possibile ripristinare.",
"offlineModeWarning": "Hai scelto di procedere senza backup. Si prega di eseguire backup manuali per assicurarsi che i codici siano al sicuro.",
"showLargeIcons": "Mostra icone grandi",
+ "shouldHideCode": "Nascondi i codici",
"focusOnSearchBar": "Apri ricerca all'avvio dell'app"
}
\ No newline at end of file
diff --git a/lib/l10n/arb/app_zh.arb b/lib/l10n/arb/app_zh.arb
index 6bf3ea750..761da4883 100644
--- a/lib/l10n/arb/app_zh.arb
+++ b/lib/l10n/arb/app_zh.arb
@@ -29,7 +29,7 @@
"timeBasedKeyType": "基于时间的 (TOTP)",
"counterBasedKeyType": "基于计数器的(HOTP)",
"saveAction": "保存",
- "nextTotpTitle": "下一步",
+ "nextTotpTitle": "下一个",
"deleteCodeTitle": "要删除代码吗?",
"deleteCodeMessage": "您确定要删除此代码吗?此操作是不可逆的。",
"viewLogsAction": "查看日志",
@@ -92,6 +92,7 @@
"importCodeDelimiterInfo": "代码可以用逗号或新行分隔。",
"selectFile": "选择文件",
"emailVerificationToggle": "电子邮件验证",
+ "emailVerificationEnableWarning": "如果您将 2FA 存储到我们的电子邮件中,则打开电子邮件验证可能会导致僵局。如果您被一项服务锁定,您可能无法登录另一项服务。",
"authToChangeEmailVerificationSetting": "请进行身份验证以更改电子邮件验证",
"authToViewYourRecoveryKey": "请验证以查看您的恢复密钥",
"authToChangeYourEmail": "请验证以更改您的电子邮件",
@@ -329,5 +330,6 @@
"sigInBackupReminder": "请导出您的代码以确保您有可以恢复的备份。",
"offlineModeWarning": "您已选择在不进行备份的情况下继续操作。请手动备份以确保您的代码安全。",
"showLargeIcons": "显示大图标",
+ "shouldHideCode": "隐藏代码",
"focusOnSearchBar": "应用启动后聚焦搜索"
}
\ No newline at end of file
diff --git a/lib/onboarding/view/setup_enter_secret_key_page.dart b/lib/onboarding/view/setup_enter_secret_key_page.dart
index b055c3c08..d7d8c11d2 100644
--- a/lib/onboarding/view/setup_enter_secret_key_page.dart
+++ b/lib/onboarding/view/setup_enter_secret_key_page.dart
@@ -1,5 +1,7 @@
import "package:ente_auth/l10n/l10n.dart";
import 'package:ente_auth/models/code.dart';
+import 'package:ente_auth/ui/components/buttons/button_widget.dart';
+import 'package:ente_auth/ui/components/models/button_result.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/totp_util.dart';
import "package:flutter/material.dart";
@@ -10,7 +12,8 @@ class SetupEnterSecretKeyPage extends StatefulWidget {
SetupEnterSecretKeyPage({this.code, Key? key}) : super(key: key);
@override
- State createState() => _SetupEnterSecretKeyPageState();
+ State createState() =>
+ _SetupEnterSecretKeyPageState();
}
class _SetupEnterSecretKeyPageState extends State {
@@ -25,7 +28,8 @@ class _SetupEnterSecretKeyPageState extends State {
text: widget.code != null ? safeDecode(widget.code!.issuer).trim() : null,
);
_accountController = TextEditingController(
- text: widget.code != null ? safeDecode(widget.code!.account).trim() : null,
+ text:
+ widget.code != null ? safeDecode(widget.code!.account).trim() : null,
);
_secretController = TextEditingController(
text: widget.code != null ? widget.code!.secret : null,
@@ -110,7 +114,7 @@ class _SetupEnterSecretKeyPageState extends State {
SizedBox(
width: 400,
child: OutlinedButton(
- onPressed: () {
+ onPressed: () async {
if ((_accountController.text.trim().isEmpty &&
_issuerController.text.trim().isEmpty) ||
_secretController.text.trim().isEmpty) {
@@ -118,31 +122,45 @@ class _SetupEnterSecretKeyPageState extends State {
if (_secretController.text.trim().isEmpty) {
message = context.l10n.secretCanNotBeEmpty;
} else {
- message = context.l10n.bothIssuerAndAccountCanNotBeEmpty;
+ message =
+ context.l10n.bothIssuerAndAccountCanNotBeEmpty;
}
_showIncorrectDetailsDialog(context, message: message);
return;
}
- try {
- final account = _accountController.text.trim();
- final issuer = _issuerController.text.trim();
- final secret = _secretController.text.trim().replaceAll(' ', '');
- final Code newCode = widget.code == null
- ? Code.fromAccountAndSecret(
- account,
- issuer,
- secret,
- )
- : widget.code!.copyWith(
- account: account,
- issuer: issuer,
- secret: secret,
- );
- // Verify the validity of the code
- getOTP(newCode);
- Navigator.of(context).pop(newCode);
- } catch (e) {
- _showIncorrectDetailsDialog(context);
+ ButtonResult? result = await showChoiceActionSheet(
+ context,
+ title: context.l10n.warning,
+ body: context.l10n.confirmUpdatingkey,
+ firstButtonLabel: context.l10n.yes,
+ secondButtonAction: ButtonAction.cancel,
+ secondButtonLabel: context.l10n.cancel,
+ );
+
+ if (result == null) return;
+ if (result.action == ButtonAction.first) {
+ try {
+ final account = _accountController.text.trim();
+ final issuer = _issuerController.text.trim();
+ final secret =
+ _secretController.text.trim().replaceAll(' ', '');
+ final Code newCode = widget.code == null
+ ? Code.fromAccountAndSecret(
+ account,
+ issuer,
+ secret,
+ )
+ : widget.code!.copyWith(
+ account: account,
+ issuer: issuer,
+ secret: secret,
+ );
+ // Verify the validity of the code
+ getOTP(newCode);
+ Navigator.of(context).pop(newCode);
+ } catch (e) {
+ _showIncorrectDetailsDialog(context);
+ }
}
},
child: Padding(
diff --git a/lib/services/preference_service.dart b/lib/services/preference_service.dart
index 57bfbefc6..66d96c7fd 100644
--- a/lib/services/preference_service.dart
+++ b/lib/services/preference_service.dart
@@ -11,7 +11,9 @@ class PreferenceService {
static const kHasShownCoachMarkKey = "has_shown_coach_mark";
static const kShouldShowLargeIconsKey = "should_show_large_icons";
+ static const kShouldHideCodesKey = "should_hide_codes";
static const kShouldAutoFocusOnSearchBar = "should_auto_focus_on_search_bar";
+ static const kShouldMinimizeOnCopy = "should_minimize_on_copy";
Future init() async {
_prefs = await SharedPreferences.getInstance();
@@ -42,6 +44,15 @@ class PreferenceService {
Bus.instance.fire(IconsChangedEvent());
}
+ bool shouldHideCodes() {
+ return _prefs.getBool(kShouldHideCodesKey) ?? false;
+ }
+
+ Future setHideCodes(bool value) async {
+ await _prefs.setBool(kShouldHideCodesKey, value);
+ Bus.instance.fire(IconsChangedEvent());
+ }
+
bool shouldAutoFocusOnSearchBar() {
if (_prefs.containsKey(kShouldAutoFocusOnSearchBar)) {
return _prefs.getBool(kShouldAutoFocusOnSearchBar)!;
@@ -54,4 +65,16 @@ class PreferenceService {
await _prefs.setBool(kShouldAutoFocusOnSearchBar, value);
Bus.instance.fire(IconsChangedEvent());
}
+
+ bool shouldMinimizeOnCopy() {
+ if (_prefs.containsKey(kShouldMinimizeOnCopy)) {
+ return _prefs.getBool(kShouldMinimizeOnCopy)!;
+ } else {
+ return false;
+ }
+ }
+
+ Future setShouldMinimizeOnCopy(bool value) async {
+ await _prefs.setBool(kShouldMinimizeOnCopy, value);
+ }
}
diff --git a/lib/ui/code_widget.dart b/lib/ui/code_widget.dart
index d2a32ee4e..a26cc20b2 100644
--- a/lib/ui/code_widget.dart
+++ b/lib/ui/code_widget.dart
@@ -1,4 +1,5 @@
import 'dart:async';
+import 'dart:io';
import 'package:clipboard/clipboard.dart';
import 'package:ente_auth/core/configuration.dart';
@@ -17,6 +18,7 @@ import 'package:ente_auth/utils/totp_util.dart';
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:logging/logging.dart';
+import 'package:move_to_background/move_to_background.dart';
class CodeWidget extends StatefulWidget {
final Code code;
@@ -35,11 +37,14 @@ class _CodeWidgetState extends State {
bool _isInitialized = false;
late bool hasConfiguredAccount;
late bool _shouldShowLargeIcon;
+ late bool _hideCode;
+ bool isMaskingEnabled = false;
@override
void initState() {
super.initState();
-
+ isMaskingEnabled = PreferenceService.instance.shouldHideCodes();
+ _hideCode = isMaskingEnabled;
_everySecondTimer =
Timer.periodic(const Duration(milliseconds: 500), (Timer t) {
String newCode = _getCurrentOTP();
@@ -63,6 +68,10 @@ class _CodeWidgetState extends State {
@override
Widget build(BuildContext context) {
+ if (isMaskingEnabled != PreferenceService.instance.shouldHideCodes()) {
+ isMaskingEnabled = PreferenceService.instance.shouldHideCodes();
+ _hideCode = isMaskingEnabled;
+ }
_shouldShowLargeIcon = PreferenceService.instance.shouldShowLargeIcons();
if (!_isInitialized) {
_currentCode.value = _getCurrentOTP();
@@ -134,10 +143,19 @@ class _CodeWidgetState extends State {
borderRadius: BorderRadius.circular(10),
),
onTap: () {
- _copyToClipboard();
+ _copyCurrentOTPToClipboard();
},
+ onDoubleTap: isMaskingEnabled
+ ? () {
+ setState(
+ () {
+ _hideCode = !_hideCode;
+ },
+ );
+ }
+ : null,
onLongPress: () {
- _copyToClipboard();
+ _copyCurrentOTPToClipboard();
},
child: _getCardContents(l10n),
),
@@ -312,17 +330,34 @@ class _CodeWidgetState extends State {
);
}
- void _copyToClipboard() {
- FlutterClipboard.copy(_getCurrentOTP())
- .then((value) => showToast(context, context.l10n.copiedToClipboard));
+ void _copyCurrentOTPToClipboard() async {
+ _copyToClipboard(
+ _getCurrentOTP(),
+ confirmationMessage: context.l10n.copiedToClipboard,
+ );
}
void _copyNextToClipboard() {
- FlutterClipboard.copy(_getNextTotp()).then(
- (value) => showToast(context, context.l10n.copiedNextToClipboard),
+ _copyToClipboard(
+ _getNextTotp(),
+ confirmationMessage: context.l10n.copiedNextToClipboard,
);
}
+ void _copyToClipboard(
+ String content, {
+ required String confirmationMessage,
+ }) async {
+ final shouldMinimizeOnCopy =
+ PreferenceService.instance.shouldMinimizeOnCopy();
+
+ await FlutterClipboard.copy(content);
+ showToast(context, confirmationMessage);
+ if (Platform.isAndroid && shouldMinimizeOnCopy) {
+ MoveToBackground.moveTaskToBack();
+ }
+ }
+
void _onNextHotpTapped() {
if (widget.code.type == Type.hotp) {
CodeStore.instance
@@ -390,6 +425,10 @@ class _CodeWidgetState extends State {
}
String _getFormattedCode(String code) {
+ if (_hideCode) {
+ // replace all digits with •
+ code = code.replaceAll(RegExp(r'\d'), '•');
+ }
if (code.length == 6) {
return code.substring(0, 3) + " " + code.substring(3, 6);
}
diff --git a/lib/ui/lifecycle_event_handler.dart b/lib/ui/lifecycle_event_handler.dart
index da539f074..da5dfb3d9 100644
--- a/lib/ui/lifecycle_event_handler.dart
+++ b/lib/ui/lifecycle_event_handler.dart
@@ -1,5 +1,3 @@
-
-
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
@@ -21,6 +19,7 @@ class LifecycleEventHandler extends WidgetsBindingObserver {
}
break;
case AppLifecycleState.inactive:
+ case AppLifecycleState.hidden:
case AppLifecycleState.paused:
case AppLifecycleState.detached:
if (suspendingCallBack != null) {
diff --git a/lib/ui/scanner_gauth_page.dart b/lib/ui/scanner_gauth_page.dart
index 9c94a26a6..785f1d3d3 100644
--- a/lib/ui/scanner_gauth_page.dart
+++ b/lib/ui/scanner_gauth_page.dart
@@ -46,7 +46,8 @@ class ScannerGoogleAuthPageState extends State {
child: QRView(
key: qrKey,
overlay: QrScannerOverlayShape(
- borderColor: getEnteColorScheme(context).primary700,),
+ borderColor: getEnteColorScheme(context).primary700,
+ ),
onQRViewCreated: _onQRViewCreated,
formatsAllowed: const [BarcodeFormat.qrcode],
),
diff --git a/lib/ui/settings/general_section_widget.dart b/lib/ui/settings/general_section_widget.dart
index 63338e1e9..986ef3a8e 100644
--- a/lib/ui/settings/general_section_widget.dart
+++ b/lib/ui/settings/general_section_widget.dart
@@ -1,3 +1,5 @@
+import 'dart:io';
+
import 'package:ente_auth/app/view/app.dart';
import 'package:ente_auth/core/logging/super_logging.dart';
import 'package:ente_auth/l10n/l10n.dart';
@@ -74,6 +76,21 @@ class _AdvancedSectionWidgetState extends State {
),
),
sectionOptionSpacing,
+ MenuItemWidget(
+ captionedTextWidget: CaptionedTextWidget(
+ title: l10n.shouldHideCode,
+ ),
+ trailingWidget: ToggleSwitchWidget(
+ value: () => PreferenceService.instance.shouldHideCodes(),
+ onChanged: () async {
+ await PreferenceService.instance.setHideCodes(
+ !PreferenceService.instance.shouldHideCodes(),
+ );
+ setState(() {});
+ },
+ ),
+ ),
+ sectionOptionSpacing,
MenuItemWidget(
captionedTextWidget: CaptionedTextWidget(
title: l10n.focusOnSearchBar,
@@ -105,6 +122,23 @@ class _AdvancedSectionWidgetState extends State {
),
),
sectionOptionSpacing,
+ if (Platform.isAndroid) ...[
+ MenuItemWidget(
+ captionedTextWidget: CaptionedTextWidget(
+ title: l10n.minimizeAppOnCopy,
+ ),
+ trailingWidget: ToggleSwitchWidget(
+ value: () => PreferenceService.instance.shouldMinimizeOnCopy(),
+ onChanged: () async {
+ await PreferenceService.instance.setShouldMinimizeOnCopy(
+ !PreferenceService.instance.shouldMinimizeOnCopy(),
+ );
+ setState(() {});
+ },
+ ),
+ ),
+ sectionOptionSpacing,
+ ],
],
);
}
diff --git a/lib/ui/settings/security_section_widget.dart b/lib/ui/settings/security_section_widget.dart
index b228ef512..aa05dd62b 100644
--- a/lib/ui/settings/security_section_widget.dart
+++ b/lib/ui/settings/security_section_widget.dart
@@ -179,7 +179,7 @@ class _SecuritySectionWidgetState extends State {
);
}
- Future updateEmailMFA(bool isEnabled) async {
+ Future updateEmailMFA(bool enableEmailMFA) async {
try {
final UserDetails details =
await UserService.instance.getUserDetailsV2(memoryCount: false);
@@ -195,7 +195,21 @@ class _SecuritySectionWidgetState extends State {
),
);
}
- await UserService.instance.updateEmailMFA(isEnabled);
+ if (enableEmailMFA) {
+ await showChoiceActionSheet(
+ context,
+ title: context.l10n.warning,
+ body: context.l10n.emailVerificationEnableWarning,
+ isCritical: true,
+ firstButtonOnTap: () async {
+ await UserService.instance.updateEmailMFA(enableEmailMFA);
+ },
+ secondButtonLabel: context.l10n.cancel,
+ firstButtonLabel: context.l10n.iUnderStand,
+ );
+ } else {
+ await UserService.instance.updateEmailMFA(enableEmailMFA);
+ }
} catch (e) {
showToast(context, context.l10n.somethingWentWrongMessage);
}
diff --git a/lib/ui/settings/support_dev_widget.dart b/lib/ui/settings/support_dev_widget.dart
index 0025a6e2b..63fa92c27 100644
--- a/lib/ui/settings/support_dev_widget.dart
+++ b/lib/ui/settings/support_dev_widget.dart
@@ -1,3 +1,4 @@
+import 'package:dotted_border/dotted_border.dart';
import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/models/subscription.dart';
@@ -35,36 +36,46 @@ class SupportDevWidget extends StatelessWidget {
}
}
- GestureDetector buildWidget(AppLocalizations l10n, BuildContext context) {
+ Widget buildWidget(AppLocalizations l10n, BuildContext context) {
return GestureDetector(
onTap: () {
launchUrl(Uri.parse("https://ente.io"));
},
- child: Padding(
- padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 6),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- StyledText(
- text: l10n.supportDevs,
- style: getEnteTextTheme(context).large,
- tags: {
- 'bold-green': StyledTextTag(
- style: TextStyle(
- fontWeight: FontWeight.bold,
- color: getEnteColorScheme(context).primaryGreen,
+ child: DottedBorder(
+ borderType: BorderType.RRect,
+ radius: const Radius.circular(12),
+ padding: const EdgeInsets.all(6),
+ dashPattern: const [3, 3],
+ color: getEnteColorScheme(context).primaryGreen,
+ child: ClipRRect(
+ borderRadius: const BorderRadius.all(Radius.circular(12)),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 6),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ StyledText(
+ text: l10n.supportDevs,
+ style: getEnteTextTheme(context).large,
+ tags: {
+ 'bold-green': StyledTextTag(
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ color: getEnteColorScheme(context).primaryGreen,
+ ),
+ ),
+ },
+ ),
+ const Padding(padding: EdgeInsets.all(6)),
+ Text(
+ l10n.supportDiscount,
+ style: const TextStyle(
+ color: Colors.grey,
),
),
- },
+ ],
),
- const Padding(padding: EdgeInsets.all(6)),
- Text(
- l10n.supportDiscount,
- style: const TextStyle(
- color: Colors.grey,
- ),
- ),
- ],
+ ),
),
),
);
diff --git a/lib/ui/utils/icon_utils.dart b/lib/ui/utils/icon_utils.dart
index 1a0ec3edc..a1a924658 100644
--- a/lib/ui/utils/icon_utils.dart
+++ b/lib/ui/utils/icon_utils.dart
@@ -12,7 +12,7 @@ class IconUtils {
// Map of icon-title to the color code in HEX
final Map _simpleIcons = {};
- final Map _customIcons = {};
+ final Map _customIcons = {};
Future init() async {
await _loadJson();
@@ -25,16 +25,16 @@ class IconUtils {
final title = _getProviderTitle(provider);
if (_customIcons.containsKey(title)) {
return _getSVGIcon(
- "assets/custom-icons/icons/$title.svg",
+ "assets/custom-icons/icons/${_customIcons[title]!.slug ?? title}.svg",
title,
- _customIcons[title]!,
+ _customIcons[title]!.color,
width,
);
} else if (_simpleIcons.containsKey(title)) {
return _getSVGIcon(
"assets/simple-icons/icons/$title.svg",
title,
- _simpleIcons[title]!,
+ _simpleIcons[title],
width,
);
} else {
@@ -45,17 +45,19 @@ class IconUtils {
Widget _getSVGIcon(
String path,
String title,
- String color,
+ String? color,
double width,
) {
return SvgPicture.asset(
path,
width: width,
semanticsLabel: title,
- colorFilter: ColorFilter.mode(
- Color(int.parse("0xFF" + color)),
- BlendMode.srcIn,
- ),
+ colorFilter: color != null
+ ? ColorFilter.mode(
+ Color(int.parse("0xFF" + color)),
+ BlendMode.srcIn,
+ )
+ : null,
);
}
@@ -70,7 +72,10 @@ class IconUtils {
.loadString('assets/custom-icons/_data/custom-icons.json');
final customIcons = json.decode(customIconData);
for (final icon in customIcons["icons"]) {
- _customIcons[icon["title"].toString().toLowerCase()] = icon["hex"];
+ _customIcons[icon["title"].toString().toLowerCase()] = CustomIconData(
+ icon["slug"],
+ icon["hex"],
+ );
}
}
@@ -78,3 +83,10 @@ class IconUtils {
return provider.split(RegExp(r'[.(]'))[0].trim().toLowerCase();
}
}
+
+class CustomIconData {
+ final String? slug;
+ final String? color;
+
+ CustomIconData(this.slug, this.color);
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index f39afe0ee..ca5437518 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: ente_auth
description: ente two-factor authenticator
-version: 2.0.4+204
+version: 2.0.6+206
publish_to: none
environment:
diff --git a/screenshots/screenshots.png b/screenshots/screenshots.png
index c587e5a04..f4510c28d 100644
Binary files a/screenshots/screenshots.png and b/screenshots/screenshots.png differ