diff --git a/src/Android/MainActivity.cs b/src/Android/MainActivity.cs index e31860b36..1940b3425 100644 --- a/src/Android/MainActivity.cs +++ b/src/Android/MainActivity.cs @@ -16,6 +16,7 @@ using System.Threading.Tasks; using Bit.App.Models.Page; using Bit.App; using Android.Nfc; +using Android.Views.InputMethods; namespace Bit.Android { @@ -78,6 +79,12 @@ namespace Bit.Android Resolver.Resolve(), Resolver.Resolve())); + MessagingCenter.Subscribe( + Xamarin.Forms.Application.Current, "DismissKeyboard", (sender) => + { + DismissKeyboard(); + }); + MessagingCenter.Subscribe(Xamarin.Forms.Application.Current, "RateApp", (sender) => { RateApp(); @@ -293,5 +300,15 @@ namespace Bit.Android MessagingCenter.Send(Xamarin.Forms.Application.Current, "GotYubiKeyOTP", otp); } } + + private void DismissKeyboard() + { + try + { + var imm = (InputMethodManager)GetSystemService(InputMethodService); + imm.HideSoftInputFromWindow(CurrentFocus.WindowToken, 0); + } + catch { } + } } } diff --git a/src/App/Pages/LoginTwoFactorPage.cs b/src/App/Pages/LoginTwoFactorPage.cs index e6067c260..e378900f7 100644 --- a/src/App/Pages/LoginTwoFactorPage.cs +++ b/src/App/Pages/LoginTwoFactorPage.cs @@ -71,7 +71,7 @@ namespace Bit.App.Pages var anotherMethodButton = new ExtendedButton { - Text = "Use another two-step login method", + Text = AppResources.UseAnotherTwoStepMethod, Style = (Style)Application.Current.Resources["btn-primaryAccent"], Margin = new Thickness(15, 0, 15, 25), Command = new Command(() => AnotherMethodAsync()), @@ -89,13 +89,13 @@ namespace Bit.App.Pages RememberCell = new ExtendedSwitchCell { - Text = "Remember me", + Text = AppResources.RememberMe, On = false }; if(!_providerType.HasValue) { - instruction.Text = "No providers available."; + instruction.Text = AppResources.NoTwoStepAvailable; var layout = new StackLayout { @@ -105,7 +105,7 @@ namespace Bit.App.Pages scrollView.Content = layout; - Title = "Login Unavailable"; + Title = AppResources.LoginUnavailable; Content = scrollView; } else if(_providerType.Value == TwoFactorProviderType.Authenticator || @@ -146,17 +146,17 @@ namespace Bit.App.Pages switch(_providerType.Value) { case TwoFactorProviderType.Authenticator: - instruction.Text = "Enter the 6 digit verification code from your authenticator app."; + instruction.Text = AppResources.EnterVerificationCodeApp; layout.Children.Add(anotherMethodButton); break; case TwoFactorProviderType.Email: var emailParams = _providers[TwoFactorProviderType.Email]; var redactedEmail = emailParams["Email"].ToString(); - instruction.Text = $"Enter the 6 digit verification code that was emailed to {redactedEmail}."; + instruction.Text = string.Format(AppResources.EnterVerificationCodeEmail, redactedEmail); var resendEmailButton = new ExtendedButton { - Text = "Send verification code email again", + Text = AppResources.SendVerificationCodeAgain, Style = (Style)Application.Current.Resources["btn-primaryAccent"], Margin = new Thickness(15, 0, 15, 0), Command = new Command(async () => await SendEmailAsync(true)), @@ -176,6 +176,7 @@ namespace Bit.App.Pages Title = AppResources.VerificationCode; Content = scrollView; + TokenCell.Entry.FocusWithDelay(); } else if(_providerType == TwoFactorProviderType.Duo) { @@ -215,7 +216,7 @@ namespace Bit.App.Pages } else if(_providerType == TwoFactorProviderType.YubiKey) { - instruction.Text = "Hold your YubiKey NEO against the back of the device to continue."; + instruction.Text = AppResources.YubiKeyInstruction; var image = new CachedImage { @@ -241,7 +242,7 @@ namespace Bit.App.Pages scrollView.Content = layout; - Title = "YubiKey"; + Title = AppResources.YubiKeyTitle; Content = scrollView; } } @@ -254,9 +255,12 @@ namespace Bit.App.Pages if(TokenCell != null) { TokenCell.InitEvents(); - TokenCell.Entry.FocusWithDelay(); TokenCell.Entry.Completed += Entry_Completed; } + else if(Device.RuntimePlatform == Device.Android) + { + MessagingCenter.Send(Application.Current, "DismissKeyboard"); + } } protected override void OnDisappearing() @@ -278,7 +282,7 @@ namespace Bit.App.Pages var options = new List(); if(_providers.ContainsKey(TwoFactorProviderType.Authenticator)) { - options.Add("Authenticator App"); + options.Add(AppResources.AuthenticatorAppTitle); } if(_providers.ContainsKey(TwoFactorProviderType.Duo)) @@ -292,19 +296,20 @@ namespace Bit.App.Pages (bool)_providers[TwoFactorProviderType.YubiKey]["Nfc"]; if(_deviceInfoService.NfcEnabled || nfcKey) { - options.Add("YubiKey NFC Security Key"); + options.Add(AppResources.YubiKeyTitle); } } if(_providers.ContainsKey(TwoFactorProviderType.Email)) { - options.Add("Email"); + options.Add(AppResources.Email); } - options.Add("Recovery Code"); + options.Add(AppResources.RecoveryCodeTitle); - var selection = await DisplayActionSheet("Two-step Login Options", AppResources.Cancel, null, options.ToArray()); - if(selection == "Authenticator App") + var selection = await DisplayActionSheet(AppResources.TwoStepLoginOptions, AppResources.Cancel, null, + options.ToArray()); + if(selection == AppResources.AuthenticatorAppTitle) { _providerType = TwoFactorProviderType.Authenticator; } @@ -312,15 +317,15 @@ namespace Bit.App.Pages { _providerType = TwoFactorProviderType.Duo; } - else if(selection == "YubiKey NFC Security Key") + else if(selection == AppResources.YubiKeyTitle) { _providerType = TwoFactorProviderType.YubiKey; } - else if(selection == "Email") + else if(selection == AppResources.Email) { _providerType = TwoFactorProviderType.Email; } - else if(selection == "Recovery Code") + else if(selection == AppResources.RecoveryCodeTitle) { Device.OpenUri(new Uri("https://help.bitwarden.com/article/lost-two-step-device/")); return; @@ -349,11 +354,11 @@ namespace Bit.App.Pages if(response.Succeeded && doToast) { - _userDialogs.Toast("Verification email sent."); + _userDialogs.Toast(AppResources.VerificationEmailSent); } else if(!response.Succeeded) { - _userDialogs.Alert("Could not send verification email. Try again."); + _userDialogs.Alert(AppResources.VerificationEmailNotSent); } } diff --git a/src/App/Resources/AppResources.Designer.cs b/src/App/Resources/AppResources.Designer.cs index 47457fbe6..5017bf29c 100644 --- a/src/App/Resources/AppResources.Designer.cs +++ b/src/App/Resources/AppResources.Designer.cs @@ -142,6 +142,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Authenticator App. + /// + public static string AuthenticatorAppTitle { + get { + return ResourceManager.GetString("AuthenticatorAppTitle", resourceCulture); + } + } + /// /// Looks up a localized string similar to Auto-fill. /// @@ -710,11 +719,20 @@ namespace Bit.App.Resources { } /// - /// Looks up a localized string similar to Enter your two-step verification code.. + /// Looks up a localized string similar to Enter the 6 digit verification code from your authenticator app.. /// - public static string EnterVerificationCode { + public static string EnterVerificationCodeApp { get { - return ResourceManager.GetString("EnterVerificationCode", resourceCulture); + return ResourceManager.GetString("EnterVerificationCodeApp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter the 6 digit verification code that was emailed to {0}.. + /// + public static string EnterVerificationCodeEmail { + get { + return ResourceManager.GetString("EnterVerificationCodeEmail", resourceCulture); } } @@ -1231,6 +1249,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Login Unavailable. + /// + public static string LoginUnavailable { + get { + return ResourceManager.GetString("LoginUnavailable", resourceCulture); + } + } + /// /// Looks up a localized string similar to Login updated.. /// @@ -1474,6 +1501,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to This account has two-step login enabled, however, none of the configured two-step providers are supported on this device. Please use a supported supported device and/or add additional providers that are better supported across devices (such as an authenticator app).. + /// + public static string NoTwoStepAvailable { + get { + return ResourceManager.GetString("NoTwoStepAvailable", resourceCulture); + } + } + /// /// Looks up a localized string similar to This login does not have a username or password configured.. /// @@ -1636,6 +1672,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Recovery Code. + /// + public static string RecoveryCodeTitle { + get { + return ResourceManager.GetString("RecoveryCodeTitle", resourceCulture); + } + } + /// /// Looks up a localized string similar to Regenerate Password. /// @@ -1645,6 +1690,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Remember me. + /// + public static string RememberMe { + get { + return ResourceManager.GetString("RememberMe", resourceCulture); + } + } + /// /// Looks up a localized string similar to Re-type Master Password. /// @@ -1717,6 +1771,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Send verification code email again. + /// + public static string SendVerificationCodeAgain { + get { + return ResourceManager.GetString("SendVerificationCodeAgain", resourceCulture); + } + } + /// /// Looks up a localized string similar to Set PIN. /// @@ -1897,6 +1960,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Two-step Login Options. + /// + public static string TwoStepLoginOptions { + get { + return ResourceManager.GetString("TwoStepLoginOptions", resourceCulture); + } + } + /// /// Looks up a localized string similar to Unlock with {0}. /// @@ -1924,6 +1996,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Use another two-step login method. + /// + public static string UseAnotherTwoStepMethod { + get { + return ResourceManager.GetString("UseAnotherTwoStepMethod", resourceCulture); + } + } + /// /// Looks up a localized string similar to Use Fingerprint to Unlock. /// @@ -1978,6 +2059,24 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Could not send verification email. Try again.. + /// + public static string VerificationEmailNotSent { + get { + return ResourceManager.GetString("VerificationEmailNotSent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Verification email sent.. + /// + public static string VerificationEmailSent { + get { + return ResourceManager.GetString("VerificationEmailSent", resourceCulture); + } + } + /// /// Looks up a localized string similar to Verify Fingerprint. /// @@ -2085,5 +2184,23 @@ namespace Bit.App.Resources { return ResourceManager.GetString("Yes", resourceCulture); } } + + /// + /// Looks up a localized string similar to Hold your YubiKey NEO against the back of the device to continue.. + /// + public static string YubiKeyInstruction { + get { + return ResourceManager.GetString("YubiKeyInstruction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to YubiKey NEO Security Key. + /// + public static string YubiKeyTitle { + get { + return ResourceManager.GetString("YubiKeyTitle", resourceCulture); + } + } } } diff --git a/src/App/Resources/AppResources.resx b/src/App/Resources/AppResources.resx index 81e8cabf3..7ae8b92c2 100644 --- a/src/App/Resources/AppResources.resx +++ b/src/App/Resources/AppResources.resx @@ -479,9 +479,6 @@ Enter your account email address to receive your master password hint. - - Enter your two-step verification code. - Re-enable App Extension @@ -853,4 +850,56 @@ Cannot open the app "{0}". Message shown when trying to launch an app that does not exist on the user's device. + + Authenticator App + For 2FA + + + Enter the 6 digit verification code from your authenticator app. + For 2FA + + + Enter the 6 digit verification code that was emailed to {0}. + For 2FA + + + Login Unavailable + For 2FA whenever there are no available providers on this device. + + + This account has two-step login enabled, however, none of the configured two-step providers are supported on this device. Please use a supported supported device and/or add additional providers that are better supported across devices (such as an authenticator app). + + + Recovery Code + For 2FA + + + Remember me + Remember my two-step login + + + Send verification code email again + For 2FA + + + Two-step Login Options + + + Use another two-step login method + + + Could not send verification email. Try again. + For 2FA + + + Verification email sent. + For 2FA + + + Hold your YubiKey NEO against the back of the device to continue. + + + YubiKey NEO Security Key + "YubiKey NEO" is the product name and should not be translated. + \ No newline at end of file