diff --git a/Authenticator.xcodeproj/project.pbxproj b/Authenticator.xcodeproj/project.pbxproj index f2f05573..2e526a7e 100644 --- a/Authenticator.xcodeproj/project.pbxproj +++ b/Authenticator.xcodeproj/project.pbxproj @@ -34,7 +34,7 @@ 5156D05B265D0538007A94F8 /* TKTokenAlgorithm+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5156D05A265D0538007A94F8 /* TKTokenAlgorithm+Extensions.swift */; }; 5156D05D265D2602007A94F8 /* TokenRequestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5156D05C265D2602007A94F8 /* TokenRequestViewController.swift */; }; 5156D05F265D3CEF007A94F8 /* TokenRequestViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5156D05E265D3CEF007A94F8 /* TokenRequestViewModel.swift */; }; - 5180974326DE185100A122C1 /* ResetOATHViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5180974226DE185100A122C1 /* ResetOATHViewModel.swift */; }; + 5180974326DE185100A122C1 /* OATHResetViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5180974226DE185100A122C1 /* OATHResetViewModel.swift */; }; 51AFD4D62716FCDB008F2630 /* ApplicationSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51AFD4D52716FCDB008F2630 /* ApplicationSettingsViewModel.swift */; }; 51AFD4D827196AB6008F2630 /* VersionHistory.plist in Resources */ = {isa = PBXBuildFile; fileRef = 51AFD4D727196AB6008F2630 /* VersionHistory.plist */; }; 51AFD4DA271D4278008F2630 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51AFD4D9271D4277008F2630 /* QuartzCore.framework */; }; @@ -185,7 +185,7 @@ 5156D05A265D0538007A94F8 /* TKTokenAlgorithm+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TKTokenAlgorithm+Extensions.swift"; sourceTree = ""; }; 5156D05C265D2602007A94F8 /* TokenRequestViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenRequestViewController.swift; sourceTree = ""; }; 5156D05E265D3CEF007A94F8 /* TokenRequestViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenRequestViewModel.swift; sourceTree = ""; }; - 5180974226DE185100A122C1 /* ResetOATHViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetOATHViewModel.swift; sourceTree = ""; }; + 5180974226DE185100A122C1 /* OATHResetViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OATHResetViewModel.swift; sourceTree = ""; }; 51AFD4D32716FC78008F2630 /* NFCSettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NFCSettingsController.swift; sourceTree = ""; }; 51AFD4D52716FCDB008F2630 /* ApplicationSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationSettingsViewModel.swift; sourceTree = ""; }; 51AFD4D727196AB6008F2630 /* VersionHistory.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = VersionHistory.plist; sourceTree = ""; }; @@ -539,7 +539,7 @@ B4696F402CB6CF2500604F6F /* ConfigurationViewModel.swift */, B4FE90D12A4431AB00B59170 /* NotificationsViewModel.swift */, B40D61A12AE7F89500467AE9 /* DisableOTPModel.swift */, - 5180974226DE185100A122C1 /* ResetOATHViewModel.swift */, + 5180974226DE185100A122C1 /* OATHResetViewModel.swift */, B44E5EB22C777F22007ABB79 /* OATHPasswordViewModel.swift */, B4BB02DD2C80BC8500B72904 /* OATHSavedPasswordsViewModel.swift */, B4BB02E12C81A82300B72904 /* FIDOPINViewModel.swift */, @@ -828,7 +828,7 @@ B4C93E65299FC67800C2A8B8 /* View+Extensions.swift in Sources */, 816C685023440D2200209342 /* SecureStoreError.swift in Sources */, 515542602649BDDB00B19C59 /* PasswordStatusViewModel.swift in Sources */, - 5180974326DE185100A122C1 /* ResetOATHViewModel.swift in Sources */, + 5180974326DE185100A122C1 /* OATHResetViewModel.swift in Sources */, B4BB02E02C80BEBD00B72904 /* OATHSavedPasswordsView.swift in Sources */, 81FA3C39231AF4F0009C22AB /* UIViewControllerAdditions.swift in Sources */, 816C684623430E0700209342 /* SecureStore.swift in Sources */, diff --git a/Authenticator/Localizable.xcstrings b/Authenticator/Localizable.xcstrings index 8a38928b..6819448e 100644 --- a/Authenticator/Localizable.xcstrings +++ b/Authenticator/Localizable.xcstrings @@ -214,14 +214,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "A PIN must be at least %llu characters long and may contain letters, numbers and special characters." + "state" : "translated", + "value" : "Saisissez votre nouveau PIN. Un PIN doit avoir au moins %llu caractères et peut inclure des lettres, chiffres et caractères spéciaux." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "A PIN must be at least %llu characters long and may contain letters, numbers and special characters." + "state" : "translated", + "value" : "新しいPINを入力してください。PINは%llu文字以上にする必要があり、文字、数字、特殊文字を含めることができます。" } }, "sk" : { @@ -242,14 +242,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "A PIN must be at least %llu characters long, contain at least 2 unique characters, and not be a commonly used PIN, like \"123456\". It may contain letters, numbers and special characters." + "state" : "translated", + "value" : "Le code PIN doit être composé d'au moins %llu caractères, contenir au moins 2 caractères uniques et ne pas être un code PIN couramment utilisé, comme \"123456\". Il peut contenir des lettres, des chiffres et des caractères spéciaux." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "A PIN must be at least %llu characters long, contain at least 2 unique characters, and not be a commonly used PIN, like \"123456\". It may contain letters, numbers and special characters." + "state" : "translated", + "value" : "PINは少なくとも %llu 文字以上で、少なくとも2つのユニークな文字を含み、\"123456 \"のような一般的に使用されているPINであってはなりません。文字、数字、特殊文字を含むことができます。" } }, "sk" : { @@ -411,7 +411,7 @@ "de" : { "stringUnit" : { "state" : "translated", - "value" : "Konten" + "value" : "OATH Konten" } }, "fr" : { @@ -736,14 +736,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "Certificates on this YubiKey can be used to authenticate and sign requests from other applications if added to this %@." + "state" : "translated", + "value" : "Les certificats de cette YubiKey peuvent être utilisés pour authentifier et signer les demandes d'autres applications si elles sont ajoutées à ce site %@." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "Certificates on this YubiKey can be used to authenticate and sign requests from other applications if added to this %@." + "state" : "translated", + "value" : "この YubiKey の証明書は、 %@に追加すれば、他のアプリケーションからのリクエストの認証や署名に使用できる。" } }, "sk" : { @@ -1135,8 +1135,8 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "Configuration read" + "state" : "translated", + "value" : "Lecture de la configuration" } }, "ja" : { @@ -2363,14 +2363,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "Get a shared secret from any service you wish to secure, store it on the YubiKey and use it to generate your security codes.\n\nYou will need a YubiKey 5Ci or a compatible YubiKey with NFC to get started." + "state" : "translated", + "value" : "Obtenez un secret partagé de tout service que vous souhaitez sécuriser, stockez-le sur la YubiKey et utilisez-le pour générer vos codes de sécurité.\n\nVous aurez besoin d'une YubiKey 5Ci ou d'une YubiKey compatible avec NFC pour commencer." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "Get a shared secret from any service you wish to secure, store it on the YubiKey and use it to generate your security codes.\n\nYou will need a YubiKey 5Ci or a compatible YubiKey with NFC to get started." + "state" : "translated", + "value" : "セキュリティを確保したいサービスから共有シークレットを取得し、YubiKeyに保存してセキュリティコードの生成に使用します。\n\n利用開始にはYubiKey 5CiまたはNFC搭載の互換性のあるYubiKeyが必要です。" } }, "sk" : { @@ -2419,14 +2419,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "How it works" + "state" : "translated", + "value" : "Comment cela fonctionne-t-il" } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "How it works" + "state" : "translated", + "value" : "仕組み" } }, "sk" : { @@ -2436,6 +2436,12 @@ } } } + }, + "If enabled, scanning the YubiKey will display a notification. Tapping the notification will reveal the One-Time Password." : { + + }, + "If enabled, the YubiKey will output a One-Time Password when touched. Since the YubiKey is detected as a keyboard the built in keyboard in iOS will be disabled." : { + }, "If you have a YubiKey 5Ci, plug it in.\n\nTouch the contacts on the sides when prompted." : { "localizations" : { @@ -2447,14 +2453,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "If you have a YubiKey 5Ci, plug it in.\n\nTouch the contacts on the sides when prompted." + "state" : "translated", + "value" : "Si vous avez une YubiKey 5Ci, branchez-la.\n\nTouchez les contacts sur les côtés lorsque vous y êtes invité." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "If you have a YubiKey 5Ci, plug it in.\n\nTouch the contacts on the sides when prompted." + "state" : "translated", + "value" : "YubiKey 5Ciをお持ちの場合は、接続してください。\n\nプロンプトが表示されたら、側面の接点をタッチします。" } }, "sk" : { @@ -2470,19 +2476,19 @@ "de" : { "stringUnit" : { "state" : "translated", - "value" : "Falls Du einen YubiKey mit NFC Funktionalität hast, ziehe bitte in der Hauptansicht der App nach unten um das NFC Scanning zu aktivieren.\n\nHalte den YubiKey horizontal und neige Dein iPhone in Richtung des YubiKey.\n\nBerühre die Mitte Deines YubiKeys (goldene Kontaktfläche) während Du ihn an weiterhin an den Rand Deines iPhones hälst." + "value" : "Falls Du einen YubiKey mit NFC Funktionalität besitzt, ziehe bitte in der Hauptansicht der App nach unten um das NFC Scanning zu aktivieren.\n\nHalte den YubiKey an den NFC Leser Deine iPhones.\n\nBerühre die Mitte Deines YubiKeys (goldene Kontaktfläche) während Du ihn an weiterhin an den Rand Deines iPhones hälst." } }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "If you have a YubiKey with NFC, pull down the main view to activate NFC.\n\nHold the key horizontally and tilt the iPhone towards the key.\n\nTouch the center of the key to the edge of the phone." + "state" : "translated", + "value" : "Si vous disposez d'une clé YubiKey avec NFC, abaissez la vue principale pour activer la NFC.\n\nTenez la clé horizontalement et inclinez l'iPhone vers la clé.\n\nTouchez le centre de la clé au bord du téléphone." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "If you have a YubiKey with NFC, pull down the main view to activate NFC.\n\nHold the key horizontally and tilt the iPhone towards the key.\n\nTouch the center of the key to the edge of the phone." + "state" : "translated", + "value" : "NFC搭載のYubiKeyをお持ちの場合は、メインビューを引き下げてNFCを有効にします。\n\nキーを水平に持ち、iPhoneをキーの方に傾けます。\n\nキーの中央をiPhoneの端にタッチします。" } }, "sk" : { @@ -2617,14 +2623,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "Invalid session state." + "state" : "translated", + "value" : "État de la session non valide." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "Invalid session state." + "state" : "translated", + "value" : "無効なセッション状態です。" } }, "sk" : { @@ -4448,14 +4454,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "Public key certificates on %@" + "state" : "translated", + "value" : "Certificats de clé publique sur %@" } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "Public key certificates on %@" + "state" : "translated", + "value" : "%@における公開鍵証明書" } }, "sk" : { @@ -4471,19 +4477,19 @@ "de" : { "stringUnit" : { "state" : "translated", - "value" : "Du erhälst QR Codes direkt bei den Diensten die Du absichern möchtest.\n\nScanne einfach den QR-Code um das shared Secret/Seed Deinem YubiKey hinzuzufügen und Sicherheitscodes zu generieren." + "value" : "Du erhälst QR Codes direkt bei den Diensten die Du absichern möchtest.\n\nScanne einfach den QR-Code um das shared Secret/Seed Deinem YubiKey hinzuzufügen und OTP Codes zu generieren." } }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "QR codes are available from the services you wish to secure.\n\nSimply scan the QR code when you add your YubiKey and generate your own security codes." + "state" : "translated", + "value" : "Les codes QR sont disponibles auprès des services que vous souhaitez sécuriser.\n\nIl vous suffit de scanner le code QR lorsque vous ajoutez votre YubiKey et de générer vos propres codes de sécurité." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "QR codes are available from the services you wish to secure.\n\nSimply scan the QR code when you add your YubiKey and generate your own security codes." + "state" : "translated", + "value" : "QRコードは、セキュリティを確保したいサービスから入手できます。\n\nYubiKeyを追加する際にQRコードを読み取るだけで、独自のセキュリティコードを生成できます。" } }, "sk" : { @@ -4814,7 +4820,7 @@ "de" : { "stringUnit" : { "state" : "translated", - "value" : "Lösche alle auf Deinem YubiKey gespeicherten Konten zurück. Stelle bitte unbedingt sicher, dass Du sie nirgendwo verwendest bevor Du fortfährst." + "value" : "Lösche alle auf Deinem YubiKey gespeicherten Konten. Stelle bitte unbedingt sicher, dass Du sie nirgendwo verwendest bevor Du fortfährst." } }, "fr" : { @@ -5700,7 +5706,7 @@ "de" : { "stringUnit" : { "state" : "translated", - "value" : "Bedingungen für die Nutzung" + "value" : "Nutzungsbedingungen" } }, "fr" : { @@ -5791,14 +5797,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "The key is busy performing another operation." + "state" : "translated", + "value" : "La clé est occupée à effectuer une autre opération." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "The key is busy performing another operation." + "state" : "translated", + "value" : "キーは別の操作で忙しい。" } }, "sk" : { @@ -5902,19 +5908,19 @@ "de" : { "stringUnit" : { "state" : "translated", - "value" : "Die gewünschte Funktion ist in diesem YubiKey entweder nicht verfügbar oder deaktiviert." + "value" : "Die gewünschte Funktion ist auf diesem YubiKey entweder nicht verfügbar oder deaktiviert." } }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "The requested functionality is missing or disabled in this YubiKey." + "state" : "translated", + "value" : "La fonctionnalité demandée est absente ou désactivée dans ce YubiKey." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "The requested functionality is missing or disabled in this YubiKey." + "state" : "translated", + "value" : "この YubiKey には、要求された機能がないか、無効になっています。" } }, "sk" : { @@ -5959,7 +5965,7 @@ "de" : { "stringUnit" : { "state" : "translated", - "value" : "Der YubiKey hat keinen Speicherplatz mehr für OATH-Konten." + "value" : "Der YubiKey hat keinen weiteren Speicherplatz mehr zusätzliche OATH-Konten." } }, "fr" : { @@ -5992,14 +5998,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "The YubiKey is not connected." + "state" : "translated", + "value" : "Le YubiKey n'est pas connecté." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "The YubiKey is not connected." + "state" : "translated", + "value" : "YubiKeyが接続されていません。" } }, "sk" : { @@ -6075,19 +6081,19 @@ "de" : { "stringUnit" : { "state" : "translated", - "value" : "Diese Zertifikate wurden zu diesem %@ hinzugefügt und können von anderen Applikationen verwendet werden." + "value" : "Diese Zertifikate wurden zu Deinem %@ hinzugefügt und können von anderen Applikationen verwendet werden." } }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "These certificates have been added to this %@ and can be used by other applications." + "state" : "translated", + "value" : "Ces certificats ont été ajoutés à ce site %@ et peuvent être utilisés par d'autres applications." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "These certificates have been added to this %@ and can be used by other applications." + "state" : "translated", + "value" : "これらの証明書はこの %@ に追加され、他のアプリケーションで使用できる。" } }, "sk" : { @@ -6155,6 +6161,34 @@ } } }, + "This setting is not supported on your YubiKey." : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Diese Einstellung wird von Deinem YubiKey nicht unterstützt." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ce paramètre n'est pas pris en charge par votre YubiKey." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "この設定はYubiKeyではサポートされていません。" + } + }, + "sk" : { + "stringUnit" : { + "state" : "new", + "value" : "This setting is not supported on your YubiKey." + } + } + } + }, "This translation is a community effort, please visit [crowdin.com](https://crowdin.com/project/yubico-authenticator-ios) to contribute." : { "localizations" : { "de" : { @@ -6476,14 +6510,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "Touch key time out." + "state" : "translated", + "value" : "Temps d'attente de la touche tactile." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "Touch key time out." + "state" : "translated", + "value" : "タッチキータイムアウト。" } }, "sk" : { @@ -6523,6 +6557,64 @@ } } }, + "Turn on/off opening Safari to copy your OTP when scanning the NFC YubiKey." : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Falls aktiviert erscheint bei Berührung der Kontaktfläche Deines YubiKeys eine Benachrichtigung. Beim Druck auf die Benachrichtigung wird der Yubico OTP Code in der App angezeigt." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activez/désactivez l'ouverture de Safari pour copier votre OTP lorsque vous scannez la YubiKey NFC." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "NFC YubiKeyをスキャンする際、Safariを開いてワンタイムパスワードをコピーするかどうかを設定します。" + } + }, + "sk" : { + "stringUnit" : { + "state" : "new", + "value" : "Turn on/off opening Safari to copy your OTP when scanning the NFC YubiKey." + } + } + } + }, + "Turn on/off output of OTP codes when touching the YubiKey." : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Falls aktiviert, wird bei Berührung der Kontaktfläche Deines YubiKeys ein Yubico OTP ausgegeben." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer/désactiver la sortie des codes OTP lorsque l'on touche la YubiKey." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "YubiKeyタッチ時のOTPコード出力ON/OFF。" + } + }, + "sk" : { + "stringUnit" : { + "state" : "new", + "value" : "Turn on/off output of OTP codes when touching the YubiKey." + } + } + } + }, "Type" : { "comment" : "Add account select type", "localizations" : { @@ -6608,6 +6700,34 @@ } } }, + "Unknown error." : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unbekannter Fehler." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erreur inconnue." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "不明なエラー。" + } + }, + "sk" : { + "stringUnit" : { + "state" : "new", + "value" : "Unknown error." + } + } + } + }, "Unlock YubiKey" : { "comment" : "Password entry unlock message", "localizations" : { @@ -6936,14 +7056,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "Where to get QR codes" + "state" : "translated", + "value" : "Où obtenir des codes QR" } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "Where to get QR codes" + "state" : "translated", + "value" : "QRコードの入手先" } }, "sk" : { @@ -7278,14 +7398,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "YubiKey 5 Series NFC authentication" + "state" : "translated", + "value" : "Authentification NFC YubiKey 5 Series" } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "YubiKey 5 Series NFC authentication" + "state" : "translated", + "value" : "YubiKey 5シリーズ NFC認証" } }, "sk" : { @@ -7306,14 +7426,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "YubiKey 5Ci authentication" + "state" : "translated", + "value" : "Authentification YubiKey 5Ci" } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "YubiKey 5Ci authentication" + "state" : "translated", + "value" : "YubiKey 5Ci認証" } }, "sk" : { @@ -7334,14 +7454,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "YubiKey connection is not found." + "state" : "translated", + "value" : "La connexion YubiKey est introuvable." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "YubiKey connection is not found." + "state" : "translated", + "value" : "YubiKey 接続が見つかりません。" } }, "sk" : { @@ -7362,14 +7482,14 @@ }, "fr" : { "stringUnit" : { - "state" : "new", - "value" : "YubiKey connection lost." + "state" : "translated", + "value" : "Connexion YubiKey perdue." } }, "ja" : { "stringUnit" : { - "state" : "new", - "value" : "YubiKey connection lost." + "state" : "translated", + "value" : "YubiKeyの接続が切れた。" } }, "sk" : { diff --git a/Authenticator/Model/FIDOPINViewModel.swift b/Authenticator/Model/FIDOPINViewModel.swift index 2d407590..2121c37b 100644 --- a/Authenticator/Model/FIDOPINViewModel.swift +++ b/Authenticator/Model/FIDOPINViewModel.swift @@ -112,17 +112,19 @@ class FIDOPINViewModel: ObservableObject { } connection.managementSession { session, error in guard let session else { - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription) + let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error + YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription) DispatchQueue.main.async { - self.state = .error(error!) + self.state = .error(error) } return } session.getDeviceInfo { deviceInfo, error in guard let deviceInfo else { - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription) + let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error + YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription) DispatchQueue.main.async { - self.state = .error(error!) + self.state = .error(error) } return } @@ -131,16 +133,18 @@ class FIDOPINViewModel: ObservableObject { } connection.fido2Session { session, error in guard let session else { - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription) + let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error + YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription) DispatchQueue.main.async { - self.state = .error(error!) + self.state = .error(error) } return } session.getInfoWithCompletion { response, error in guard let response else { DispatchQueue.main.async { - self.state = .error(error!) + let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error + self.state = .error(error) } return } @@ -162,7 +166,7 @@ class FIDOPINViewModel: ObservableObject { session.getPinRetries { retries, error in if let error { DispatchQueue.main.async { - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription) + YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription) self.state = .error(error) } return @@ -200,7 +204,8 @@ class FIDOPINViewModel: ObservableObject { guard let session else { DispatchQueue.main.async { self.isProcessing = false - self.state = .error(error!) // If there is no error and no session crashing is the best thing. + let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error + self.state = .error(error) } YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription) return @@ -209,7 +214,7 @@ class FIDOPINViewModel: ObservableObject { DispatchQueue.main.async { if let error { self.state = .error(error) - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription) + YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription) } else { self.state = .didSet YubiKitManager.shared.stopNFCConnection(withMessage: String(localized: "PIN has been set")) @@ -229,7 +234,8 @@ class FIDOPINViewModel: ObservableObject { guard let session else { DispatchQueue.main.async { self.isProcessing = false - self.state = .error(error!) // If there is no error and no session crashing is the best thing. + let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error + self.state = .error(error) } YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription) return @@ -238,7 +244,7 @@ class FIDOPINViewModel: ObservableObject { DispatchQueue.main.async { if let error { self.state = .error(error) - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription) + YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription) } else { self.state = .didChange YubiKitManager.shared.stopNFCConnection(withMessage: String(localized: "PIN has been changed")) diff --git a/Authenticator/Model/FIDOResetViewModel.swift b/Authenticator/Model/FIDOResetViewModel.swift index 64a0a6ba..c7217e04 100644 --- a/Authenticator/Model/FIDOResetViewModel.swift +++ b/Authenticator/Model/FIDOResetViewModel.swift @@ -93,17 +93,20 @@ extension FIDOResetViewModel { func resetNFC(connection: YKFNFCConnection) { connection.fido2Session { session, error in guard let session = session else { - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription) + guard let error else { return } + let localizedError = LocalizedErrorWrapper(error: error) + YubiKitManager.shared.stopNFCConnection(withErrorMessage: localizedError.localizedDescription) DispatchQueue.main.async { - self.state = .error(error!) + self.state = .error(localizedError) } return } session.reset { error in DispatchQueue.main.async { - if let error = error { - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription) - self.state = .error(error) + if let error { + let localizedError = LocalizedErrorWrapper(error: error) + YubiKitManager.shared.stopNFCConnection(withErrorMessage: localizedError.localizedDescription) + self.state = .error(localizedError) } else { let message = String(localized: "Reset FIDO application", comment: "FIDO reset NFC confirmation message") YubiKitManager.shared.stopNFCConnection(withMessage: message) diff --git a/Authenticator/Model/OATHPasswordViewModel.swift b/Authenticator/Model/OATHPasswordViewModel.swift index cd889e1e..1243c36b 100644 --- a/Authenticator/Model/OATHPasswordViewModel.swift +++ b/Authenticator/Model/OATHPasswordViewModel.swift @@ -92,9 +92,10 @@ class OATHPasswordViewModel: ObservableObject { connection.startConnection { [weak self] connection in connection.oathSession { session, error in guard let session else { - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription) + let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error + YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription) DispatchQueue.main.async { - self?.state = .error(error!) + self?.state = .error(error) } return } @@ -108,7 +109,7 @@ class OATHPasswordViewModel: ObservableObject { if let oathError = error as? YKFOATHError, oathError.code == YKFOATHErrorCode.authenticationRequired.rawValue { self?.state = .set } else { - self?.state = .error(error) + self?.state = .error(error) // If we got this far the error is pretty exotic so bailing out like this is ok. } } } @@ -138,18 +139,19 @@ class OATHPasswordViewModel: ObservableObject { connection.startConnection { connection in connection.oathSession { session, error in guard let session else { + guard let error else { return } DispatchQueue.main.async { self.isProcessing = false - self.state = .error(error!) // If there is no error and no session crashing is the best thing. + self.state = .error(error) // If there is no error and no session crashing is the best thing. } - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription) + YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription) return } session.setPassword(newPassword) { error in DispatchQueue.main.async { if let error { self.state = .error(error) - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription) + YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription) } else { self.state = .didSet YubiKitManager.shared.stopNFCConnection(withMessage: String(localized: "Password has been set")) diff --git a/Authenticator/Model/ResetOATHViewModel.swift b/Authenticator/Model/OATHResetViewModel.swift similarity index 69% rename from Authenticator/Model/ResetOATHViewModel.swift rename to Authenticator/Model/OATHResetViewModel.swift index 8f402300..b7155dca 100644 --- a/Authenticator/Model/ResetOATHViewModel.swift +++ b/Authenticator/Model/OATHResetViewModel.swift @@ -17,12 +17,25 @@ import Foundation import OSLog -class ResetOATHViewModel: ObservableObject { +class OATHResetViewModel: ObservableObject { @Published var state: ResetState = .ready enum ResetState: Equatable { - case ready, success, error(String) + case ready, success, error(Error) + + static func == (lhs: OATHResetViewModel.ResetState, rhs: OATHResetViewModel.ResetState) -> Bool { + switch (lhs, rhs) { + case (.ready, .ready): + return true + case (.success, .success): + return true + case (.error(_), .error(_)): + return true + default: + return false + } + } } private let connection = Connection() @@ -35,18 +48,18 @@ class ResetOATHViewModel: ObservableObject { connection.startConnection { connection in connection.oathSession { session, error in guard let session = session else { - let errorMessage = error?.localizedDescription ?? String(localized: "Unknown error") - YubiKitManager.shared.stopNFCConnection(withErrorMessage: errorMessage) + let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error + YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription) DispatchQueue.main.async { - self.state = .error(errorMessage) + self.state = .error(error) } return } session.reset { error in DispatchQueue.main.async { if let error = error { - YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription) - self.state = .error(error.localizedDescription) + YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription) + self.state = .error(error) } else { let message = String(localized: "OATH accounts deleted and OATH application reset to factory defaults.", comment: "OATH reset confirmation message") YubiKitManager.shared.stopNFCConnection(withMessage: message) diff --git a/Authenticator/UI/Base.lproj/Main.storyboard b/Authenticator/UI/Base.lproj/Main.storyboard index ac23acef..990f3256 100644 --- a/Authenticator/UI/Base.lproj/Main.storyboard +++ b/Authenticator/UI/Base.lproj/Main.storyboard @@ -18,7 +18,7 @@ - +