Merge branch 'main' into offline_mode

This commit is contained in:
vishnukvmd 2023-08-20 21:50:38 +05:30
commit d965a0239f
30 changed files with 644 additions and 122 deletions

View file

@ -25,7 +25,7 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: "3.7.3"
flutter-version: "3.10.6"
# Fetch sub modules
- run: git submodule update --init --recursive

3
.gitmodules vendored
View file

@ -6,3 +6,6 @@
path = flutter
url = https://github.com/flutter/flutter.git
branch = stable
[submodule "assets/simple-icons"]
path = assets/simple-icons
url = https://github.com/simple-icons/simple-icons.git

View file

@ -101,6 +101,15 @@ For maintainers, there is [additional documentation](RELEASES.md) on
automatically publishing the main branch to App store, Play store and GitHub
releases.
## 🙂 Icons
ente Auth supports the icon pack provided by
[simple-icons](https://github.com/simple-icons/simple-icons).
If you would like to add your own custom icon, please open a pull-request
with the relevant SVG and color
code ([example PR](https://github.com/ente-io/auth/pull/213/files)).
## 🙋‍♂️ Support
If you need help, please reach out to support@ente.io, and a human will get in

View file

@ -0,0 +1 @@
f23611a675a8c9bc71eb16e8a1108cf8

View file

@ -0,0 +1,12 @@
{
"icons": [
{
"title": "ente",
"hex": "1DB954"
},
{
"title": "Github",
"hex": "858585"
}
]
}

View file

@ -0,0 +1,3 @@
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.06803 7.096C3.33203 7.096 2.68403 6.952 2.12403 6.664C1.57203 6.376 1.14403 5.984 0.840033 5.488C0.536033 4.984 0.384033 4.412 0.384033 3.772C0.384033 3.124 0.532033 2.552 0.828033 2.056C1.13203 1.552 1.54403 1.16 2.06403 0.879997C2.58403 0.591998 3.17203 0.447998 3.82803 0.447998C4.46003 0.447998 5.02803 0.583998 5.53203 0.855998C6.04403 1.12 6.44803 1.504 6.74403 2.008C7.04003 2.504 7.18803 3.1 7.18803 3.796C7.18803 3.868 7.18403 3.952 7.17603 4.048C7.16803 4.136 7.16003 4.22 7.15203 4.3H1.90803V3.208H6.16803L5.44803 3.532C5.44803 3.196 5.38003 2.904 5.24403 2.656C5.10803 2.408 4.92003 2.216 4.68003 2.08C4.44003 1.936 4.16003 1.864 3.84003 1.864C3.52003 1.864 3.23603 1.936 2.98803 2.08C2.74803 2.216 2.56003 2.412 2.42403 2.668C2.28803 2.916 2.22003 3.212 2.22003 3.556V3.844C2.22003 4.196 2.29603 4.508 2.44803 4.78C2.60803 5.044 2.82803 5.248 3.10803 5.392C3.39603 5.528 3.73203 5.596 4.11603 5.596C4.46003 5.596 4.76003 5.544 5.01603 5.44C5.28003 5.336 5.52003 5.18 5.73603 4.972L6.73203 6.052C6.43603 6.388 6.06403 6.648 5.61603 6.832C5.16803 7.008 4.65203 7.096 4.06803 7.096Z" fill="black" style="fill:black;fill:black;fill-opacity:1;"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>

After

Width:  |  Height:  |  Size: 822 B

1
assets/simple-icons Submodule

@ -0,0 +1 @@
Subproject commit 7e1ad4517598f36ba625741a4dfbc33610d105d8

@ -1 +1 @@
Subproject commit b06b8b2710955028a6b562f5aa6fe62941d6febf
Subproject commit f468f3366c26a5092eb964a230ce7892fda8f2f8

View file

@ -81,14 +81,16 @@ PODS:
- Flutter
- MTBBarcodeScanner
- Reachability (3.2)
- SDWebImage (5.15.0):
- SDWebImage/Core (= 5.15.0)
- SDWebImage/Core (5.15.0)
- Sentry/HybridSDK (7.31.5)
- SDWebImage (5.17.0):
- SDWebImage/Core (= 5.17.0)
- SDWebImage/Core (5.17.0)
- Sentry/HybridSDK (8.9.1):
- SentryPrivate (= 8.9.1)
- sentry_flutter (0.0.1):
- Flutter
- FlutterMacOS
- Sentry/HybridSDK (= 7.31.5)
- Sentry/HybridSDK (= 8.9.1)
- SentryPrivate (8.9.1)
- share_plus (0.0.1):
- Flutter
- shared_preferences_foundation (0.0.1):
@ -121,11 +123,11 @@ DEPENDENCIES:
- move_to_background (from `.symlinks/plugins/move_to_background/ios`)
- open_filex (from `.symlinks/plugins/open_filex/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`)
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- uni_links (from `.symlinks/plugins/uni_links/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
@ -140,6 +142,7 @@ SPEC REPOS:
- Reachability
- SDWebImage
- Sentry
- SentryPrivate
- SwiftyGif
- Toast
@ -177,7 +180,7 @@ EXTERNAL SOURCES:
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
:path: ".symlinks/plugins/path_provider_foundation/darwin"
qr_code_scanner:
:path: ".symlinks/plugins/qr_code_scanner/ios"
sentry_flutter:
@ -185,7 +188,7 @@ EXTERNAL SOURCES:
share_plus:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
uni_links:
@ -214,13 +217,14 @@ SPEC CHECKSUMS:
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
open_filex: 6e26e659846ec990262224a12ef1c528bb4edbe4
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
SDWebImage: 9bec4c5cdd9579e1f57104735ee0c37df274d593
Sentry: 4c9babff9034785067c896fd580b1f7de44da020
sentry_flutter: 1346a880b24c0240807b53b10cf50ddad40f504e
SDWebImage: 750adf017a315a280c60fde706ab1e552a3ae4e9
Sentry: e3203780941722a1fcfee99e351de14244c7f806
sentry_flutter: 8f0ffd53088e6a4d50c095852c5cad9e4405025c
SentryPrivate: 5e3683390f66611fc7c6215e27645873adb55d13
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a

View file

@ -204,7 +204,7 @@ class SuperLogging {
static void setUserID(String userID) async {
if (config.sentryDsn != null) {
Sentry.configureScope((scope) => scope.user = SentryUser(id: userID));
Sentry.configureScope((scope) => scope.setUser(SentryUser(id: userID)));
$.info("setting sentry user ID to: $userID");
}
}

View file

@ -22,11 +22,11 @@ class TunneledTransport implements Transport {
: _dsn = _options.dsn != null ? Dsn.parse(_options.dsn!) : null,
_headers = _buildHeaders(
_options.platformChecker.isWeb,
_options.sdk.identifier,
_options.sentryClientName,
) {
_credentialBuilder = _CredentialBuilder(
_dsn,
_options.sdk.identifier,
_options.sentryClientName,
_options.clock,
);
}

View file

@ -15,7 +15,6 @@ final lightThemeData = ThemeData(
primary: Colors.black,
secondary: Color.fromARGB(255, 163, 163, 163),
),
accentColor: const Color.fromRGBO(0, 0, 0, 0.6),
outlinedButtonTheme: buildOutlinedButtonThemeData(
bgDisabled: const Color.fromRGBO(158, 158, 158, 1),
bgEnabled: const Color.fromRGBO(0, 0, 0, 1),
@ -91,7 +90,6 @@ final darkThemeData = ThemeData(
const IconThemeData(color: Colors.red, opacity: 1.0, size: 50.0),
hintColor: const Color.fromRGBO(158, 158, 158, 1),
colorScheme: const ColorScheme.dark(primary: Colors.white),
accentColor: const Color.fromRGBO(45, 194, 98, 0.2),
buttonTheme: const ButtonThemeData().copyWith(
buttonColor: const Color.fromRGBO(45, 194, 98, 1.0),
),

View file

@ -85,6 +85,7 @@
"importSelectJsonFile": "Select JSON file",
"importEnteEncGuide": "Select the encrypted JSON file exported from ente",
"importRaivoGuide": "Use the \"Export OTPs to Zip archive\" option in Raivo's Settings.\n\nExtract the zip file and import the JSON file.",
"importAegisGuide": "Use the \"Export the vault\" option in Aegis's Settings.\n\nIf your vault is encrypted, you will need to enter vault password to decrypt the vault.",
"exportCodes": "Export codes",
"importLabel": "Import",
"importInstruction": "Please select a file that contains a list of your codes in the following format",

View file

@ -68,10 +68,14 @@
"changePassword": "Modifier le mot de passe",
"data": "Données",
"importCodes": "Importer les codes",
"importSelectJsonFile": "Sélectionnez un fichier JSON",
"importEnteEncGuide": "Sélectionnez le fichier JSON chiffré exporté à partir de ente",
"exportCodes": "Exporter les codes",
"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",
"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",
"authToChangeYourPassword": "Veuillez vous authentifier pour modifier votre mot de passe",
@ -90,6 +94,14 @@
"enterYourPasswordHint": "Saisir votre mot de passe",
"forgotPassword": "Mot de passe oublié",
"oops": "Oups",
"suggestFeatures": "Suggérer des fonctionnalités",
"faq": "FAQ",
"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.",
"somethingWentWrongMessage": "Quelque chose s'est mal passé, veuillez recommencer",
"leaveFamily": "Quitter le plan familial",
"leaveFamilyMessage": "Êtes-vous certains de vouloir quitter le plan familial?",
@ -156,6 +168,7 @@
"recoveryKeySaveDescription": "Nous ne stockons pas cette clé, veuillez enregistrer cette clé de 24 mots dans un endroit sûr.",
"doThisLater": "Plus tard",
"saveKey": "Enregistrer la clé",
"back": "Retour",
"createAccount": "Créer un compte",
"passwordStrength": "Force du mot de passe : {passwordStrengthValue}",
"@passwordStrength": {
@ -186,6 +199,7 @@
"continueLabel": "Continuer",
"insecureDevice": "Appareil non sécurisé",
"sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Désolé, nous n'avons pas pu générer de clés sécurisées sur cet appareil.\n\nVeuillez vous inscrire depuis un autre appareil.",
"howItWorks": "Comment ça fonctionne",
"ackPasswordLostWarning": "Je comprends que si je perds mon mot de passe, je risque de perdre mes données puisque celles-ci sont <underline>chiffrées de bout en bout</underline>.",
"loginTerms": "En cliquant sur \"Connexion\", j'accepte les <u-terms>conditions d'utilisation</u-terms> et la <u-policy>politique de confidentialité</u-policy>",
"logInLabel": "Connexion",
@ -262,5 +276,19 @@
"thisWillLogYouOutOfTheFollowingDevice": "Cela vous déconnectera de l'appareil suivant :",
"terminateSession": "Quitter la session ?",
"terminate": "Quitter",
"thisDevice": "Cet appareil"
"thisDevice": "Cet appareil",
"toResetVerifyEmail": "Pour réinitialiser votre mot de passe, veuillez d'abord vérifier votre e-mail.",
"thisEmailIsAlreadyInUse": "Cette adresse mail est déjà utilisé",
"verificationFailedPleaseTryAgain": "La vérification a échouée, veuillez réessayer",
"yourVerificationCodeHasExpired": "Votre code de vérification a expiré",
"incorrectCode": "Code non valide",
"sorryTheCodeYouveEnteredIsIncorrect": "Le code que vous avez saisi est incorrect",
"emailChangedTo": "L'e-mail a été changé en {newEmail}",
"authenticationFailedPleaseTryAgain": "L'authentification a échouée, veuillez réessayer",
"authenticationSuccessful": "Authentification réussie!",
"twofactorAuthenticationSuccessfullyReset": "L'authentification à deux facteurs a été réinitialisée avec succès ",
"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"
}

View file

@ -85,6 +85,7 @@
"importSelectJsonFile": "Seleziona file JSON",
"importEnteEncGuide": "Seleziona il file JSON criptato esportato da ente",
"importRaivoGuide": "Utilizza l'opzione \"Esporta i codici OTP in archivio Zip\" nelle impostazioni di Raivo.\n\nEstrai il file zip e importa il file JSON.",
"importAegisGuide": "Usa l'opzione \"Esporta la cassaforte\" nelle impostazioni di Aegis.\n\nSe la tua cassaforte è criptata, dovrai inserire la password della cassaforte per decriptarla.",
"exportCodes": "Esporta codici",
"importLabel": "Importa",
"importInstruction": "Per favore seleziona un file contenente una lista dei tuoi codici nel seguente formato",

View file

@ -117,6 +117,11 @@
"faq_q_2": "Kan ik toegang krijgen tot mijn codes op desktop?",
"faq_a_2": "U heeft toegang tot uw codes op het web @ auth.ente.io.",
"faq_q_3": "Hoe kan ik codes verwijderen?",
"faq_a_3": "Je kunt een code verwijderen door naar links te vegen op dat item.",
"faq_q_4": "Hoe kan ik dit project steunen?",
"faq_a_4": "U kunt de ontwikkeling van dit project steunen door u te abonneren op onze Photos app @ ente.io.",
"faq_q_5": "Hoe kan ik FaceID lock inschakelen in ente Auth",
"faq_a_5": "Je kunt FaceID vergrendelen onder Instellingen → Beveiliging → Lockscreen.",
"somethingWentWrongMessage": "Er is iets fout gegaan, probeer het opnieuw",
"leaveFamily": "Familie verlaten",
"leaveFamilyMessage": "Weet je zeker dat je het familie-plan wil verlaten?",
@ -183,6 +188,7 @@
"recoveryKeySaveDescription": "We slaan deze code niet op, bewaar deze code met 24 woorden op een veilige plaats.",
"doThisLater": "Doe dit later",
"saveKey": "Sleutel opslaan",
"back": "Terug",
"createAccount": "Account aanmaken",
"passwordStrength": "Wachtwoord sterkte: {passwordStrengthValue}",
"@passwordStrength": {
@ -290,5 +296,24 @@
"thisWillLogYouOutOfTheFollowingDevice": "Dit zal je uitloggen van het volgende apparaat:",
"terminateSession": "Sessie beëindigen?",
"terminate": "Beëindigen",
"thisDevice": "Dit apparaat"
"thisDevice": "Dit apparaat",
"toResetVerifyEmail": "Verifieer eerst je e-mailadres om je wachtwoord opnieuw in te stellen.",
"thisEmailIsAlreadyInUse": "Dit e-mailadres is al in gebruik",
"verificationFailedPleaseTryAgain": "Verificatie mislukt, probeer het opnieuw",
"yourVerificationCodeHasExpired": "Uw verificatiecode is verlopen",
"incorrectCode": "Onjuiste code",
"sorryTheCodeYouveEnteredIsIncorrect": "Sorry, de ingevoerde code is onjuist",
"emailChangedTo": "E-mailadres gewijzigd naar {newEmail}",
"authenticationFailedPleaseTryAgain": "Verificatie mislukt, probeer het opnieuw",
"authenticationSuccessful": "Verificatie geslaagd!",
"twofactorAuthenticationSuccessfullyReset": "Tweestapsverificatie succesvol gereset",
"incorrectRecoveryKey": "Onjuiste herstelsleutel",
"theRecoveryKeyYouEnteredIsIncorrect": "De ingevoerde herstelsleutel is onjuist",
"enterPassword": "Voer wachtwoord in",
"selectExportFormat": "Selecteer export formaat",
"exportDialogDesc": "Versleutelde exports worden beschermd door een wachtwoord van uw keuze.",
"encrypted": "Versleuteld",
"plainText": "Kale tekst",
"passwordToEncryptExport": "Wachtwoord voor het versleutelen van export",
"export": "Exporteren"
}

View file

@ -9,7 +9,8 @@
"onBoardingGetStarted": "Начать",
"setupFirstAccount": "Настройте свой первый аккаунт",
"importScanQrCode": "Сканировать QR-код",
"importEnterSetupKey": "Введите ключ установки",
"qrCode": "QR-код",
"importEnterSetupKey": "Ввести ключ настройки",
"importAccountPageTitle": "Введите данные аккаунта",
"secretCanNotBeEmpty": "Секретный код не может быть пустым",
"bothIssuerAndAccountCanNotBeEmpty": "И эмитент, и аккаунт не могут быть пустыми",
@ -57,6 +58,9 @@
}
},
"contactSupport": "Связаться с поддержкой",
"rateUsOnStore": "Оценить нас на {storeName}",
"blog": "Блог",
"merchandise": "Товары",
"verifyPassword": "Подтверждение пароля",
"pleaseWait": "Пожалуйста, подождите...",
"generatingEncryptionKeysTitle": "Генерируем ключи шифрования...",
@ -68,14 +72,26 @@
"madeWithLoveAtPrefix": "сделана с ❤️ в ",
"supportDevs": "Подпишитесь на <bold-green>ente</bold-green> для поддержки этого проекта.",
"supportDiscount": "Используйте код скидки \"AUTH\", чтобы получить скидку 10% в первый год",
"changeEmail": "изменить почту",
"changeEmail": "Изменить почту",
"changePassword": "Изменить пароль",
"data": "Данные",
"importCodes": "Импортировать коды",
"importTypePlainText": "Обычный текст",
"importTypeEnteEncrypted": "ente Зашифрованный экспорт",
"passwordForDecryptingExport": "Пароль для расшифровки экспорта",
"passwordEmptyError": "Пароль не может быть пустым",
"importFromApp": "Импорт кодов из {appName}",
"importGoogleAuthGuide": "Экспортируйте учетные записи из Google Authenticator в QR-код, используя опцию «Перенести учетные записи». Затем с помощью другого устройства отсканируйте QR-код.\n\nСовет: Чтобы сфотографировать QR-код, можно воспользоваться веб-камерой ноутбука.",
"importSelectJsonFile": "Выбрать JSON-файл",
"importEnteEncGuide": "Выберите зашифрованный JSON-файл, экспортированный из ente",
"importRaivoGuide": "Используйте опцию «Export OTPs to Zip archive» в настройках Raivo.\n\nРаспакуйте zip-архив и импортируйте JSON-файл.",
"exportCodes": "Экспортировать коды",
"importLabel": "Импорт",
"importInstruction": "Пожалуйста, выберите файл, содержащий список ваших кодов в следующем формате",
"importCodeDelimiterInfo": "Коды могут быть разделены запятой или новой строкой",
"selectFile": "Выберите файл",
"selectFile": "Выбрать файл",
"emailVerificationToggle": "Подтверждение электронной почты",
"authToChangeEmailVerificationSetting": "Авторизуйтесь, чтобы изменить подтверждение электронной почты",
"authToViewYourRecoveryKey": "Пожалуйста, авторизуйтесь для просмотра вашего ключа восстановления",
"authToChangeYourEmail": "Пожалуйста, авторизуйтесь, чтобы изменить адрес электронной почты",
"authToChangeYourPassword": "Пожалуйста, авторизуйтесь, чтобы изменить пароль",
@ -94,6 +110,18 @@
"enterYourPasswordHint": "Введите пароль",
"forgotPassword": "Забыл пароль",
"oops": "Ой",
"suggestFeatures": "Предложить улучшения",
"faq": "FAQ",
"faq_q_1": "Насколько безопасен ente Auth?",
"faq_a_1": "Все коды, которые вы резервируете с помощью ente, хранятся в зашифрованном виде. Это означает, что только вы можете получить доступ к своим кодам. Наши приложения имеют открытый исходный код, а наша криптография прошла внешний аудит.",
"faq_q_2": "Могу ли я получить доступ к моим кодам на компьютере?",
"faq_a_2": "Вы можете получить доступ к своим кодам на сайте @ auth.ente.io.",
"faq_q_3": "Как я могу удалить коды?",
"faq_a_3": "Вы можете удалить код, проведя пальцем влево по этому элементу.",
"faq_q_4": "Как я могу поддержать этот проект?",
"faq_a_4": "Вы можете поддержать развитие этого проекта, подписавшись на наше приложение Photos @ ente.io.",
"faq_q_5": "Как мне включить блокировку FaceID в ente Auth?",
"faq_a_5": "Вы можете включить блокировку FaceID в Настройки → Безопасность → Экран блокировки.",
"somethingWentWrongMessage": "Что-то пошло не так. Попробуйте еще раз",
"leaveFamily": "Покинуть семью",
"leaveFamilyMessage": "Вы уверены, что хотите отказаться от семейного плана?",
@ -160,6 +188,7 @@
"recoveryKeySaveDescription": "Мы не храним этот ключ, пожалуйста, сохраните этот ключ в безопасном месте.",
"doThisLater": "Сделать позже",
"saveKey": "Сохранить ключ",
"back": "Вернуться",
"createAccount": "Создать аккаунт",
"passwordStrength": "Мощность пароля: {passwordStrengthValue}",
"@passwordStrength": {
@ -267,5 +296,24 @@
"thisWillLogYouOutOfTheFollowingDevice": "Вы выйдете из списка следующих устройств:",
"terminateSession": "Завершить сеанс?",
"terminate": "Завершить",
"thisDevice": "Это устройство"
"thisDevice": "Это устройство",
"toResetVerifyEmail": "Чтобы сбросить пароль, сначала подтвердите свой адрес электронной почты.",
"thisEmailIsAlreadyInUse": "Этот адрес электронной почты уже используется",
"verificationFailedPleaseTryAgain": "Проверка не удалась, попробуйте еще раз",
"yourVerificationCodeHasExpired": "Срок действия вашего проверочного кода истек",
"incorrectCode": "Неверный код",
"sorryTheCodeYouveEnteredIsIncorrect": "Извините, введенный вами код неверный",
"emailChangedTo": "Адрес электронной почты изменен на {newEmail}",
"authenticationFailedPleaseTryAgain": "Аутентификация не удалась, попробуйте еще раз",
"authenticationSuccessful": "Аутентификация прошла успешно!",
"twofactorAuthenticationSuccessfullyReset": "Двухфакторная аутентификация успешно сброшена",
"incorrectRecoveryKey": "Неправильный ключ восстановления",
"theRecoveryKeyYouEnteredIsIncorrect": "Введен неправильный ключ восстановления",
"enterPassword": "Введите пароль",
"selectExportFormat": "Выбрать формат экспорта",
"exportDialogDesc": "Зашифрованные экспортированные данные будут защищены паролем, который вы выберете.",
"encrypted": "Зашифрованный",
"plainText": "Обычный текст",
"passwordToEncryptExport": "Пароль для шифрования экспорта",
"export": "Экспорт"
}

View file

@ -9,8 +9,11 @@
"onBoardingGetStarted": "Başlayın",
"setupFirstAccount": "İlk hesabınızı ekleyin",
"importScanQrCode": "Karekodu tara",
"qrCode": "QR Kodu",
"importEnterSetupKey": "Kurulum anahtarını giriniz",
"importAccountPageTitle": "Hesap bilgilerinizi girin",
"incorrectDetails": "Bilgiler yanlış",
"pleaseVerifyDetails": "Lütfen bilgileri doğrulayın ve tekrar deneyin",
"codeIssuerHint": "Yayınlayan",
"codeSecretKeyHint": "Gizli Anahtar",
"codeAccountHint": "Hesap (örnek@domain.com)",
@ -24,7 +27,7 @@
"timeBasedKeyType": "Zaman tabanlı (TOTP)",
"counterBasedKeyType": "Sayaç tabanlı (HOTP)",
"saveAction": "Kaydet",
"nextTotpTitle": "ileri",
"nextTotpTitle": "sonraki",
"deleteCodeTitle": "Kodu silmek istiyor musunuz?",
"deleteCodeMessage": "Bu kodu silmek istediğinize emin misiniz? Bu geri alınamaz bir işlemdir.",
"viewLogsAction": "Günlüğü görüntüle",
@ -53,6 +56,9 @@
}
},
"contactSupport": "Destek ekibiyle iletişime geçin",
"rateUsOnStore": "Bizi {storeName} üzerinden değerlendirin",
"blog": "Blog",
"merchandise": "Ürünler",
"verifyPassword": "Şifreyi doğrulayın",
"pleaseWait": "Lütfen bekleyin...",
"generatingEncryptionKeysTitle": "Şifreleme anahtarları üretiliyor...",
@ -67,11 +73,24 @@
"changeEmail": "E-postayı değiştir",
"changePassword": "Şifreyi değiştir",
"data": "Veriler",
"importCodes": "Kodu İçe Aktar",
"importCodes": "Kodu içe aktar",
"importTypePlainText": "Düz metin",
"importTypeEnteEncrypted": "ente Şifreli dışa aktarma",
"passwordForDecryptingExport": "Dışa aktarımın şifresini çözmek için parola",
"passwordEmptyError": "Şifre boş olamaz",
"importFromApp": "Kodları {appName} uygulamasından içe aktarın",
"importGoogleAuthGuide": "\"Hesapları Aktar\" seçeneğini kullanarak hesaplarınızı Google Authenticator'dan bir QR koduna aktarın. Ardından başka bir cihaz kullanarak QR kodunu tarayın.\n\nİpucu: QR kodunun fotoğrafını çekmek için dizüstü bilgisayarınızın kamerasını kullanabilirsiniz.",
"importSelectJsonFile": "JSON dosyasını seçin",
"importEnteEncGuide": "Ente'den dışa aktarılan şifrelenmiş JSON dosyasını seçin",
"importRaivoGuide": "Raivo'nun ayarlarında \"OTP'leri Zip arşivine aktar\" seçeneğini kullanın.\n\nZip dosyasını çıkarın ve JSON dosyasını içe aktarın.",
"importAegisGuide": "Aegis'in Ayarlarında \"Kasayı dışa aktar\" seçeneğini kullanın.\n\nKasanız şifrelenmişse, kasanın şifresini çözmek için kasa parolasını girmeniz gerekecektir.",
"exportCodes": "Kodu dışa aktar",
"importLabel": "İçe aktar",
"importInstruction": "Lütfen aşağıdaki şekilde kodlarınızın listesini içeren dosyayı seçiniz",
"importCodeDelimiterInfo": "Kodlar, virgülle ya da yeni bir satırla ayrılabilir",
"selectFile": "Dosya seç",
"emailVerificationToggle": "E-posta doğrulama",
"authToChangeEmailVerificationSetting": "E-posta doğrulamasını değiştirmek için lütfen kimlik doğrulaması yapın",
"authToViewYourRecoveryKey": "Kurtarma anahtarınızı görmek için lütfen kimliğinizi doğrulayın",
"authToChangeYourEmail": "Epostanızı değiştirmek için lütfen kimliğinizi doğrulayın",
"authToChangeYourPassword": "Şifrenizi değiştirmek için lütfen kimliğinizi doğrulayın",
@ -90,6 +109,18 @@
"enterYourPasswordHint": "Parolanızı girin",
"forgotPassword": "Şifremi unuttum",
"oops": "Hay aksi",
"suggestFeatures": "Özellik önerin",
"faq": "SSS",
"faq_q_1": "Ente Auth ne kadar güvenli?",
"faq_a_1": "Ente aracılığıyla yedeklediğiniz tüm kodlar uçtan uca şifrelenmiş olarak saklanır. Bu, kodlarınıza yalnızca sizin erişebileceğiniz anlamına gelir. Uygulamalarımız açık kaynaklıdır ve kriptografimiz harici olarak denetlenmiştir.",
"faq_q_2": "Kodlarıma masaüstünden erişebilir miyim?",
"faq_a_2": "Kodlarınıza internet üzerinden @ auth.ente.io adresinden erişebilirsiniz.",
"faq_q_3": "Kodları nasıl silebilirim?",
"faq_a_3": "Bir kodu, o öğenin üzerinde sola kaydırarak silebilirsiniz.",
"faq_q_4": "Bu projeye nasıl destek olabilirim?",
"faq_a_4": "Fotoğraflar uygulamamıza @ ente.io abone olarak bu projenin geliştirilmesine destek olabilirsiniz.",
"faq_q_5": "FaceID kilidini ente Auth'ta nasıl etkinleştirebilirim",
"faq_a_5": "FaceID kilidini Ayarlar → Güvenlik → Kilit Ekranı altında etkinleştirebilirsiniz.",
"somethingWentWrongMessage": "Bir şeyler ters gitti, lütfen tekrar deneyin",
"leaveFamily": "Aile planından ayrıl",
"leaveFamilyMessage": "Aile planından ayrılmak istediğinize emin misiniz?",
@ -156,6 +187,7 @@
"recoveryKeySaveDescription": "Biz bu anahtarı saklamıyoruz, lütfen. bu 24 kelimelik anahtarı güvenli bir yerde saklayın.",
"doThisLater": "Bunu daha sonra yap",
"saveKey": "Anahtarı kaydet",
"back": "Geri",
"createAccount": "Hesap oluştur",
"passwordStrength": "Şifre gücü: {passwordStrengthValue}",
"@passwordStrength": {
@ -214,6 +246,7 @@
"enterYourRecoveryKey": "Kurtarma anahtarınızı girin",
"tempErrorContactSupportIfPersists": "Bir şeyler ters gitmiş gibi görünüyor. Lütfen bir süre sonra tekrar deneyin. Hata devam ederse, lütfen destek ekibimizle iletişime geçin.",
"itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Bir şeyler ters gitmiş gibi görünüyor. Lütfen bir süre sonra tekrar deneyin. Hata devam ederse, lütfen destek ekibimizle iletişime geçin.",
"about": "Hakkında",
"weAreOpenSource": "Biz açık kaynağız!",
"privacy": "Gizlilik",
"terms": "Şartlar",
@ -238,6 +271,7 @@
}
}
},
"sorry": "Üzgünüz",
"importFailureDesc": "Seçilen dosya ayrıştırılamadı.\nYardıma ihtiyacınız varsa lütfen support@ente.io adresine yazın!",
"pendingSyncs": "Uyarı",
"pendingSyncsWarningBody": "Kodlarınızdan bazıları yedeklenmemiş.\n\nLütfen oturumu kapatmadan önce bu kodların yedeğini aldığınızdan emin olun.",
@ -257,7 +291,28 @@
},
"activeSessions": "Aktif oturumlar",
"somethingWentWrongPleaseTryAgain": "Bir şeyler ters gitti, lütfen tekrar deneyin",
"thisWillLogYouOutOfThisDevice": "Bu sizin bu cihazdaki oturumunuzu kapatacaktır!",
"thisWillLogYouOutOfTheFollowingDevice": "Bu, aşağıdaki cihazdan çıkış yapmanızı sağlayacaktır:",
"terminateSession": "Oturumu sonlandır?",
"terminate": "Sonlandır",
"thisDevice": "Bu cihaz"
"thisDevice": "Bu cihaz",
"toResetVerifyEmail": "Şifrenizi sıfırlamak için lütfen önce e-postanızı doğrulayın.",
"thisEmailIsAlreadyInUse": "Bu e-posta zaten kullanılıyor",
"verificationFailedPleaseTryAgain": "Doğrulama başarısız oldu, lütfen tekrar deneyin",
"yourVerificationCodeHasExpired": "Doğrulama kodunuzun süresi doldu",
"incorrectCode": "Yanlış kod",
"sorryTheCodeYouveEnteredIsIncorrect": "Üzgünüz, girdiğiniz kod yanlış",
"emailChangedTo": "E-posta {newEmail} olarak değiştirildi",
"authenticationFailedPleaseTryAgain": "Kimlik doğrulama başarısız oldu, lütfen tekrar deneyin",
"authenticationSuccessful": "Kimlik doğrulama başarılı!",
"twofactorAuthenticationSuccessfullyReset": "İki faktörlü kimlik doğrulama başarıyla sıfırlandı",
"incorrectRecoveryKey": "Yanlış kurtarma kodu",
"theRecoveryKeyYouEnteredIsIncorrect": "Girdiğiniz kurtarma kodu yanlış",
"enterPassword": "Şifreyi girin",
"selectExportFormat": "Dışa aktarma formatını seç",
"exportDialogDesc": "Şifrelenmiş dışa aktarımlar seçtiğiniz bir parola ile korunacaktır.",
"encrypted": "Şifreli",
"plainText": "Düz metin",
"passwordToEncryptExport": "Dışa aktarımı şifrelemek için parola",
"export": "Dışa aktar"
}

View file

@ -17,6 +17,7 @@ import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/store/code_store.dart';
import 'package:ente_auth/ui/tools/app_lock.dart';
import 'package:ente_auth/ui/tools/lock_screen.dart';
import 'package:ente_auth/ui/utils/icon_utils.dart';
import 'package:ente_auth/utils/crypto_util.dart';
import 'package:flutter/foundation.dart';
import "package:flutter/material.dart";
@ -85,4 +86,5 @@ Future<void> _init(bool bool, {String? via}) async {
await BillingService.instance.init();
await NotificationService.instance.init();
await UpdateService.instance.init();
await IconUtils.instance.init();
}

View file

@ -8,6 +8,7 @@ import 'package:ente_auth/onboarding/view/setup_enter_secret_key_page.dart';
import 'package:ente_auth/onboarding/view/view_qr_page.dart';
import 'package:ente_auth/store/code_store.dart';
import 'package:ente_auth/ui/code_timer_progress.dart';
import 'package:ente_auth/ui/utils/icon_utils.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:ente_auth/utils/toast_util.dart';
import 'package:ente_auth/utils/totp_util.dart';
@ -81,7 +82,7 @@ class _CodeWidgetState extends State<CodeWidget> {
backgroundColor: Colors.grey.withOpacity(0.1),
borderRadius: const BorderRadius.all(Radius.circular(12.0)),
foregroundColor:
Theme.of(context).colorScheme.inverseBackgroundColor,
Theme.of(context).colorScheme.inverseBackgroundColor,
icon: Icons.qr_code_2_outlined,
label: "QR",
padding: const EdgeInsets.only(left: 4, right: 0),
@ -90,7 +91,6 @@ class _CodeWidgetState extends State<CodeWidget> {
const SizedBox(
width: 4,
),
SlidableAction(
onPressed: _onEditPressed,
backgroundColor: Colors.grey.withOpacity(0.1),
@ -171,14 +171,23 @@ class _CodeWidgetState extends State<CodeWidget> {
),
],
),
widget.code.hasSynced != null &&
widget.code.hasSynced!
? Container()
: const Icon(
Icons.sync_disabled,
size: 20,
color: Colors.amber,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
widget.code.hasSynced != null &&
widget.code.hasSynced!
? Container()
: const Icon(
Icons.sync_disabled,
size: 20,
color: Colors.amber,
),
const SizedBox(width: 12),
IconUtils.instance.getIcon(
safeDecode(widget.code.issuer).trim(),
),
],
),
],
),
),
@ -231,7 +240,7 @@ class _CodeWidgetState extends State<CodeWidget> {
style:
Theme.of(context).textTheme.caption,
),
InkWell(
InkWell(
onTap: _onNextHotpTapped,
child: const Icon(
Icons.forward_outlined,
@ -264,8 +273,13 @@ class _CodeWidgetState extends State<CodeWidget> {
}
void _onNextHotpTapped() {
if(widget.code.type == Type.hotp) {
CodeStore.instance.addCode(widget.code.copyWith(counter: widget.code.counter + 1), shouldSync: true).ignore();
if (widget.code.type == Type.hotp) {
CodeStore.instance
.addCode(
widget.code.copyWith(counter: widget.code.counter + 1),
shouldSync: true,
)
.ignore();
}
}
@ -306,7 +320,6 @@ class _CodeWidgetState extends State<CodeWidget> {
);
}
String _getCurrentOTP() {
try {
return getOTP(widget.code);

View file

@ -0,0 +1,236 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:convert/convert.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/models/code.dart';
import 'package:ente_auth/services/authenticator_service.dart';
import 'package:ente_auth/store/code_store.dart';
import 'package:ente_auth/ui/common/progress_dialog.dart';
import 'package:ente_auth/ui/components/buttons/button_widget.dart';
import 'package:ente_auth/ui/components/dialog_widget.dart';
import 'package:ente_auth/ui/components/models/button_type.dart';
import 'package:ente_auth/ui/settings/data/import/import_success.dart';
import 'package:ente_auth/utils/dialog_util.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:pointycastle/block/aes.dart';
import 'package:pointycastle/block/modes/gcm.dart';
import 'package:pointycastle/key_derivators/scrypt.dart';
import 'package:pointycastle/pointycastle.dart';
Future<void> showAegisImportInstruction(BuildContext context) async {
final l10n = context.l10n;
final result = await showDialogWidget(
context: context,
title: l10n.importFromApp("Aegis Authenticator"),
body: l10n.importAegisGuide,
buttons: [
ButtonWidget(
buttonType: ButtonType.primary,
labelText: l10n.importSelectJsonFile,
isInAlert: true,
buttonSize: ButtonSize.large,
buttonAction: ButtonAction.first,
),
ButtonWidget(
buttonType: ButtonType.secondary,
labelText: context.l10n.cancel,
buttonSize: ButtonSize.large,
isInAlert: true,
buttonAction: ButtonAction.second,
),
],
);
if (result?.action != null && result!.action != ButtonAction.cancel) {
if (result.action == ButtonAction.first) {
await _pickAegisJsonFile(context);
} else {}
}
}
Future<void> _pickAegisJsonFile(BuildContext context) async {
final l10n = context.l10n;
FilePickerResult? result = await FilePicker.platform
.pickFiles(dialogTitle: l10n.importSelectJsonFile);
if (result == null) {
return;
}
final ProgressDialog progressDialog =
createProgressDialog(context, l10n.pleaseWait);
await progressDialog.show();
try {
String path = result.files.single.path!;
int? count = await _processAegisExportFile(context, path, progressDialog);
await progressDialog.hide();
if (count != null) {
await importSuccessDialog(context, count);
}
} catch (e, s) {
Logger('AegisImport').severe('exception while processing for aegis', e, s);
await progressDialog.hide();
await showErrorDialog(
context,
context.l10n.sorry,
context.l10n.importFailureDesc,
);
}
}
Future<int?> _processAegisExportFile(
BuildContext context,
String path,
final ProgressDialog dialog,
) async {
File file = File(path);
final jsonString = await file.readAsString();
final decodedJson = jsonDecode(jsonString);
final isEncrypted = decodedJson['header']['slots'] != null;
var aegisDB;
if (isEncrypted) {
String? password;
try {
await showTextInputDialog(
context,
title: "Enter password to aegis vault",
submitButtonLabel: "Submit",
isPasswordInput: true,
onSubmit: (value) async {
password = value;
},
);
if (password == null) {
await dialog.hide();
return null;
}
final content = decryptAegisVault(decodedJson, password: password!);
aegisDB = jsonDecode(content);
} catch (e, s) {
Logger("AegisImport")
.warning("exception while decrypting aegis vault", e, s);
await dialog.hide();
if (password != null) {
await showErrorDialog(
context,
"Failed to decrypt aegis vault",
"Please check your password and try again.",
);
}
return null;
}
} else {
aegisDB = decodedJson['db'];
}
final parsedCodes = [];
for (var item in aegisDB['entries']) {
var kind = item['type'];
var account = item['name'];
var issuer = item['issuer'];
var algorithm = item['info']['algo'];
var secret = item['info']['secret'];
var timer = item['info']['period'];
var digits = item['info']['digits'];
var counter = item['info']['counter'];
// Build the OTP URL
String otpUrl;
if (kind.toLowerCase() == 'totp') {
otpUrl =
'otpauth://$kind/$issuer:$account?secret=$secret&issuer=$issuer&algorithm=$algorithm&digits=$digits&period=$timer';
} else if (kind.toLowerCase() == 'hotp') {
otpUrl =
'otpauth://$kind/$issuer:$account?secret=$secret&issuer=$issuer&algorithm=$algorithm&digits=$digits&counter=$counter';
} else {
throw Exception('Invalid OTP type');
}
parsedCodes.add(Code.fromRawData(otpUrl));
}
for (final code in parsedCodes) {
await CodeStore.instance.addCode(code, shouldSync: false);
}
unawaited(AuthenticatorService.instance.sync());
int count = parsedCodes.length;
return count;
}
String decryptAegisVault(dynamic data, {required String password}) {
final header = data["header"];
final slots =
(header["slots"] as List).where((slot) => slot["type"] == 1).toList();
Uint8List? masterKey;
for (final slot in slots) {
final salt = Uint8List.fromList(hex.decode(slot["salt"]));
final int iterations = slot["n"];
final int r = slot["r"];
final int p = slot["p"];
const int derivedKeyLength = 32;
final script = Scrypt()
..init(
ScryptParameters(
iterations,
r,
p,
derivedKeyLength,
salt,
),
);
final key = script.process(Uint8List.fromList(utf8.encode(password)));
final params = slot["key_params"];
final nonce = Uint8List.fromList(hex.decode(params["nonce"]));
final encryptedKeyWithTag =
Uint8List.fromList(hex.decode(slot["key"]) + hex.decode(params["tag"]));
final cipher = GCMBlockCipher(AESEngine())
..init(
false,
AEADParameters(
KeyParameter(key),
128,
nonce,
Uint8List.fromList(<int>[]),
),
);
try {
masterKey = cipher.process(encryptedKeyWithTag);
break;
} catch (e) {
// Ignore decryption failure and continue to next slot
}
}
if (masterKey == null) {
throw Exception("Unable to decrypt the master key with the given password");
}
final content = base64.decode(data["db"]);
final params = header["params"];
final nonce = Uint8List.fromList(hex.decode(params["nonce"]));
final tag = Uint8List.fromList(hex.decode(params["tag"]));
final cipherTextWithTag = Uint8List.fromList(content + tag);
final cipher = GCMBlockCipher(AESEngine())
..init(
false,
AEADParameters(
KeyParameter(masterKey),
128,
nonce,
Uint8List.fromList(<int>[]),
),
);
final dbBytes = cipher.process(cipherTextWithTag);
return utf8.decode(dbBytes);
}

View file

@ -66,7 +66,6 @@ List<Code> parseGoogleAuth(String qrCodeData) {
try {
List<Code> codes = <Code>[];
final String payload = qrCodeData.substring(kGoogleAuthExportPrefix.length);
debugPrint("GoogleAuthImport: payload: $payload");
final Uint8List base64Decoded = base64Decode(Uri.decodeComponent(payload));
final MigrationPayload mPayload =
MigrationPayload.fromBuffer(base64Decoded);

View file

@ -1,3 +1,4 @@
import 'package:ente_auth/ui/settings/data/import/aegis_import.dart';
import 'package:ente_auth/ui/settings/data/import/encrypted_ente_import.dart';
import 'package:ente_auth/ui/settings/data/import/google_auth_import.dart';
import 'package:ente_auth/ui/settings/data/import/plain_text_import.dart';
@ -25,9 +26,11 @@ class ImportService {
break;
case ImportType.googleAuthenticator:
showGoogleAuthInstruction(context);
// showToast(context, 'coming soon');
break;
case ImportType.aegis:
showAegisImportInstruction(context);
break;
}
}
}

View file

@ -15,6 +15,7 @@ enum ImportType {
encrypted,
ravio,
googleAuthenticator,
aegis,
}
class ImportCodePage extends StatelessWidget {
@ -22,6 +23,7 @@ class ImportCodePage extends StatelessWidget {
ImportType.plainText,
ImportType.encrypted,
ImportType.ravio,
ImportType.aegis,
ImportType.googleAuthenticator,
];
@ -37,6 +39,8 @@ class ImportCodePage extends StatelessWidget {
return 'Raivo OTP';
case ImportType.googleAuthenticator:
return 'Google Authenticator';
case ImportType.aegis:
return 'Aegis Authenticator';
}
}

View file

@ -0,0 +1,70 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_svg/svg.dart';
class IconUtils {
IconUtils._privateConstructor();
static final IconUtils instance = IconUtils._privateConstructor();
// Map of icon-title to the color code in HEX
final Map<String, String> _simpleIcons = {};
final Map<String, String> _customIcons = {};
Future<void> init() async {
await _loadJson();
}
Widget getIcon(String provider) {
final title = _getProviderTitle(provider);
if (_customIcons.containsKey(title)) {
return _getSVGIcon(
"assets/custom-icons/icons/$title.svg",
title,
_customIcons[title]!,
);
} else if (_simpleIcons.containsKey(title)) {
return _getSVGIcon(
"assets/simple-icons/icons/$title.svg",
title,
_simpleIcons[title]!,
);
} else {
return const SizedBox.shrink();
}
}
Widget _getSVGIcon(String path, String title, String color) {
return SvgPicture.asset(
path,
width: 24,
semanticsLabel: title,
colorFilter: ColorFilter.mode(
Color(int.parse("0xFF" + color)),
BlendMode.srcIn,
),
);
}
Future<void> _loadJson() async {
final simpleIconData = await rootBundle
.loadString('assets/simple-icons/_data/simple-icons.json');
final simpleIcons = json.decode(simpleIconData);
for (final icon in simpleIcons["icons"]) {
_simpleIcons[icon["title"].toString().toLowerCase()] = icon["hex"];
}
final customIconData = await rootBundle
.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"];
}
}
String _getProviderTitle(String provider) {
return provider.split(".")[0].toLowerCase();
}
}

View file

@ -9,7 +9,7 @@ import connectivity_macos
import device_info_plus
import flutter_local_notifications
import flutter_secure_storage_macos
import package_info_plus_macos
import package_info_plus
import path_provider_foundation
import sentry_flutter
import share_plus_macos

View file

@ -45,10 +45,10 @@ packages:
dependency: transitive
description:
name: async
sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.dev"
source: hosted
version: "2.10.0"
version: "2.11.0"
base32:
dependency: "direct main"
description:
@ -157,10 +157,10 @@ packages:
dependency: transitive
description:
name: characters
sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
version: "1.3.0"
checked_yaml:
dependency: transitive
description:
@ -197,10 +197,10 @@ packages:
dependency: "direct main"
description:
name: collection
sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
url: "https://pub.dev"
source: hosted
version: "1.17.0"
version: "1.17.1"
computer:
dependency: "direct main"
description:
@ -382,10 +382,10 @@ packages:
dependency: "direct main"
description:
name: expansion_tile_card
sha256: "0812d52e4a2effa4957286b9037c81394e1881ac49bcd8f006f631f2ea5ef6eb"
sha256: "27ce4cb518f00e21d0f2309aaa6462b26b148e93cee2029a73088cecf42b1eb0"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
version: "3.0.0"
fake_async:
dependency: transitive
description:
@ -414,10 +414,10 @@ packages:
dependency: "direct main"
description:
name: file_picker
sha256: b85eb92b175767fdaa0c543bf3b0d1f610fe966412ea72845fe5ba7801e763ff
sha256: "9d6e95ec73abbd31ec54d0e0df8a961017e165aba1395e462e5b31ea0c165daf"
url: "https://pub.dev"
source: hosted
version: "5.2.10"
version: "5.3.1"
fixnum:
dependency: transitive
description:
@ -589,6 +589,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.2.0"
flutter_svg:
dependency: "direct main"
description:
name: flutter_svg
sha256: f991fdb1533c3caeee0cdc14b04f50f0c3916f0dbcbc05237ccbe4e3c6b93f3f
url: "https://pub.dev"
source: hosted
version: "2.0.5"
flutter_test:
dependency: "direct dev"
description: flutter
@ -691,10 +699,10 @@ packages:
dependency: "direct main"
description:
name: intl
sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6
url: "https://pub.dev"
source: hosted
version: "0.17.0"
version: "0.18.0"
io:
dependency: transitive
description:
@ -707,10 +715,10 @@ packages:
dependency: transitive
description:
name: js
sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7"
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.5"
version: "0.6.7"
json_annotation:
dependency: "direct main"
description:
@ -787,10 +795,10 @@ packages:
dependency: transitive
description:
name: matcher
sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72"
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
url: "https://pub.dev"
source: hosted
version: "0.12.13"
version: "0.12.15"
material_color_utilities:
dependency: transitive
description:
@ -803,10 +811,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42"
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
url: "https://pub.dev"
source: hosted
version: "1.8.0"
version: "1.9.1"
mime:
dependency: transitive
description:
@ -883,50 +891,18 @@ packages:
dependency: "direct main"
description:
name: package_info_plus
sha256: f62d7253edc197fe3c88d7c2ddab82d68f555e778d55390ccc3537eca8e8d637
sha256: "6ff267fcd9d48cb61c8df74a82680e8b82e940231bb5f68356672fde0397334a"
url: "https://pub.dev"
source: hosted
version: "1.4.3+1"
package_info_plus_linux:
dependency: transitive
description:
name: package_info_plus_linux
sha256: "04b575f44233d30edbb80a94e57cad9107aada334fc02aabb42b6becd13c43fc"
url: "https://pub.dev"
source: hosted
version: "1.0.5"
package_info_plus_macos:
dependency: transitive
description:
name: package_info_plus_macos
sha256: a2ad8b4acf4cd479d4a0afa5a74ea3f5b1c7563b77e52cc32b3ee6956d5482a6
url: "https://pub.dev"
source: hosted
version: "1.3.0"
version: "4.1.0"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: f7a0c8f1e7e981bc65f8b64137a53fd3c195b18d429fba960babc59a5a1c7ae8
sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
package_info_plus_web:
dependency: transitive
description:
name: package_info_plus_web
sha256: f0829327eb534789e0a16ccac8936a80beed4e2401c4d3a74f3f39094a822d3b
url: "https://pub.dev"
source: hosted
version: "1.0.6"
package_info_plus_windows:
dependency: transitive
description:
name: package_info_plus_windows
sha256: "79524f11c42dd9078b96d797b3cf79c0a2883a50c4920dc43da8562c115089bc"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
version: "2.0.1"
password_strength:
dependency: "direct main"
description:
@ -939,10 +915,10 @@ packages:
dependency: transitive
description:
name: path
sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev"
source: hosted
version: "1.8.2"
version: "1.8.3"
path_drawing:
dependency: transitive
description:
@ -1123,18 +1099,18 @@ packages:
dependency: "direct main"
description:
name: sentry
sha256: a1529c545fcbc899e5dcc7c94ff1c6ad0c334dfc99a3cda366b1da98af7c5678
sha256: "39c23342fc96105da449914f7774139a17a0ca8a4e70d9ad5200171f7e47d6ba"
url: "https://pub.dev"
source: hosted
version: "6.22.0"
version: "7.9.0"
sentry_flutter:
dependency: "direct main"
description:
name: sentry_flutter
sha256: cab07e99a8f27af94f399cabceaff6968011660505b30a0e2286728a81bc476c
sha256: ff68ab31918690da004a42e20204242a3ad9ad57da7e2712da8487060ac9767f
url: "https://pub.dev"
source: hosted
version: "6.22.0"
version: "7.9.0"
share_plus:
dependency: "direct main"
description:
@ -1400,26 +1376,26 @@ packages:
dependency: transitive
description:
name: test
sha256: a5fcd2d25eeadbb6589e80198a47d6a464ba3e2049da473943b8af9797900c2d
sha256: "3dac9aecf2c3991d09b9cdde4f98ded7b30804a88a0d7e4e7e1678e78d6b97f4"
url: "https://pub.dev"
source: hosted
version: "1.22.0"
version: "1.24.1"
test_api:
dependency: transitive
description:
name: test_api
sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
url: "https://pub.dev"
source: hosted
version: "0.4.16"
version: "0.5.1"
test_core:
dependency: transitive
description:
name: test_core
sha256: "0ef9755ec6d746951ba0aabe62f874b707690b5ede0fecc818b138fcc9b14888"
sha256: "5138dbffb77b2289ecb12b81c11ba46036590b72a64a7a90d6ffb880f1a29e93"
url: "https://pub.dev"
source: hosted
version: "0.4.20"
version: "0.5.1"
timezone:
dependency: transitive
description:
@ -1556,6 +1532,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.7"
vector_graphics:
dependency: transitive
description:
name: vector_graphics
sha256: ea8d3fc7b2e0f35de38a7465063ecfcf03d8217f7962aa2a6717132cb5d43a79
url: "https://pub.dev"
source: hosted
version: "1.1.5"
vector_graphics_codec:
dependency: transitive
description:
name: vector_graphics_codec
sha256: a5eaa5d19e123ad4f61c3718ca1ed921c4e6254238d9145f82aa214955d9aced
url: "https://pub.dev"
source: hosted
version: "1.1.5"
vector_graphics_compiler:
dependency: transitive
description:
name: vector_graphics_compiler
sha256: "15edc42f7eaa478ce854eaf1fbb9062a899c0e4e56e775dd73b7f4709c97c4ca"
url: "https://pub.dev"
source: hosted
version: "1.1.5"
vector_math:
dependency: transitive
description:
@ -1600,10 +1600,10 @@ packages:
dependency: transitive
description:
name: win32
sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4
sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c"
url: "https://pub.dev"
source: hosted
version: "3.1.4"
version: "4.1.4"
xdg_directories:
dependency: transitive
description:
@ -1637,5 +1637,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
dart: ">=2.19.0 <3.0.0"
dart: ">=3.0.0 <4.0.0"
flutter: ">=3.7.0"

View file

@ -1,10 +1,10 @@
name: ente_auth
description: ente two-factor authenticator
version: 1.0.54+54
version: 1.0.55+55
publish_to: none
environment:
sdk: ">=2.17.0 <3.0.0"
sdk: ">=3.0.0 <4.0.0"
dependencies:
adaptive_theme: ^3.1.0 # done
@ -25,7 +25,7 @@ dependencies:
email_validator: ^2.0.1
event_bus: ^2.0.0
expandable: ^5.0.1
expansion_tile_card: ^2.0.0
expansion_tile_card: ^3.0.0
file_picker: ^5.2.4
fk_user_agent: ^2.1.0
flutter:
@ -44,10 +44,11 @@ dependencies:
git:
url: https://github.com/ente-io/flutter_sodium.git
flutter_speed_dial: ^6.2.0
flutter_svg: ^2.0.5
fluttertoast: ^8.1.1
google_nav_bar: ^5.0.5 #supported
http: ^0.13.4
intl: ^0.17.0
intl: ^0.18.0
json_annotation: ^4.5.0
local_auth: ^2.1.3
logging: ^1.0.1
@ -55,7 +56,7 @@ dependencies:
move_to_background: ^1.0.2
open_filex: ^4.3.2
otp: ^3.1.1
package_info_plus: ^1.0.1
package_info_plus: ^4.1.0
password_strength: ^0.2.0
path_provider: ^2.0.11
pinput: ^1.2.2
@ -63,8 +64,8 @@ dependencies:
protobuf: ^3.0.0
qr_code_scanner: ^1.0.1
qr_flutter: 4.0.0
sentry: ^6.12.1
sentry_flutter: ^6.12.1
sentry: ^7.9.0
sentry_flutter: ^7.9.0
share_plus: ^4.4.0
shared_preferences: ^2.0.5
sqflite: ^2.1.0
@ -92,6 +93,10 @@ flutter:
# https://docs:flutter:dev/development/ui/assets-and-images:
assets:
- assets/
- assets/simple-icons/icons/
- assets/simple-icons/_data/
- assets/custom-icons/icons/
- assets/custom-icons/_data/
fonts:
- family: Inter

Binary file not shown.

Before

Width:  |  Height:  |  Size: 363 KiB

After

Width:  |  Height:  |  Size: 269 KiB