diff --git a/src/Android/Android.csproj b/src/Android/Android.csproj index 0d377d020..cc93dcdf0 100644 --- a/src/Android/Android.csproj +++ b/src/Android/Android.csproj @@ -906,5 +906,20 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Android/Resources/Resource.Designer.cs b/src/Android/Resources/Resource.Designer.cs index c937e355e..fa29b1228 100644 --- a/src/Android/Resources/Resource.Designer.cs +++ b/src/Android/Resources/Resource.Designer.cs @@ -4682,26 +4682,26 @@ namespace Bit.Android // aapt resource value: 0x7f02005b public const int avd_hide_password = 2130837595; - // aapt resource value: 0x7f02015a - public const int avd_hide_password_1 = 2130837850; - // aapt resource value: 0x7f02015b - public const int avd_hide_password_2 = 2130837851; + public const int avd_hide_password_1 = 2130837851; // aapt resource value: 0x7f02015c - public const int avd_hide_password_3 = 2130837852; + public const int avd_hide_password_2 = 2130837852; + + // aapt resource value: 0x7f02015d + public const int avd_hide_password_3 = 2130837853; // aapt resource value: 0x7f02005c public const int avd_show_password = 2130837596; - // aapt resource value: 0x7f02015d - public const int avd_show_password_1 = 2130837853; - // aapt resource value: 0x7f02015e - public const int avd_show_password_2 = 2130837854; + public const int avd_show_password_1 = 2130837854; // aapt resource value: 0x7f02015f - public const int avd_show_password_3 = 2130837855; + public const int avd_show_password_2 = 2130837855; + + // aapt resource value: 0x7f020160 + public const int avd_show_password_3 = 2130837856; // aapt resource value: 0x7f02005d public const int bottom_nav_bg = 2130837597; @@ -5405,11 +5405,11 @@ namespace Bit.Android // aapt resource value: 0x7f020146 public const int notification_sm = 2130837830; - // aapt resource value: 0x7f020158 - public const int notification_template_icon_bg = 2130837848; - // aapt resource value: 0x7f020159 - public const int notification_template_icon_low_bg = 2130837849; + public const int notification_template_icon_bg = 2130837849; + + // aapt resource value: 0x7f02015a + public const int notification_template_icon_low_bg = 2130837850; // aapt resource value: 0x7f020147 public const int notification_tile_bg = 2130837831; @@ -5430,37 +5430,40 @@ namespace Bit.Android public const int refresh = 2130837836; // aapt resource value: 0x7f02014d - public const int search = 2130837837; + public const int refresh_alt = 2130837837; // aapt resource value: 0x7f02014e - public const int share = 2130837838; + public const int search = 2130837838; // aapt resource value: 0x7f02014f - public const int share_tools = 2130837839; + public const int share = 2130837839; // aapt resource value: 0x7f020150 - public const int shield = 2130837840; + public const int share_tools = 2130837840; // aapt resource value: 0x7f020151 - public const int slider_thumb = 2130837841; + public const int shield = 2130837841; // aapt resource value: 0x7f020152 - public const int splash_screen = 2130837842; + public const int slider_thumb = 2130837842; // aapt resource value: 0x7f020153 - public const int tools = 2130837843; + public const int splash_screen = 2130837843; // aapt resource value: 0x7f020154 - public const int trash = 2130837844; + public const int tools = 2130837844; // aapt resource value: 0x7f020155 - public const int upload = 2130837845; + public const int trash = 2130837845; // aapt resource value: 0x7f020156 - public const int user = 2130837846; + public const int upload = 2130837846; // aapt resource value: 0x7f020157 - public const int yubikey = 2130837847; + public const int user = 2130837847; + + // aapt resource value: 0x7f020158 + public const int yubikey = 2130837848; static Drawable() { diff --git a/src/Android/Resources/drawable-hdpi/refresh_alt.png b/src/Android/Resources/drawable-hdpi/refresh_alt.png new file mode 100644 index 000000000..6da642bf7 Binary files /dev/null and b/src/Android/Resources/drawable-hdpi/refresh_alt.png differ diff --git a/src/Android/Resources/drawable-xhdpi/refresh_alt.png b/src/Android/Resources/drawable-xhdpi/refresh_alt.png new file mode 100644 index 000000000..decdd33f9 Binary files /dev/null and b/src/Android/Resources/drawable-xhdpi/refresh_alt.png differ diff --git a/src/Android/Resources/drawable-xxhdpi/refresh_alt.png b/src/Android/Resources/drawable-xxhdpi/refresh_alt.png new file mode 100644 index 000000000..5c100820a Binary files /dev/null and b/src/Android/Resources/drawable-xxhdpi/refresh_alt.png differ diff --git a/src/Android/Resources/drawable-xxxhdpi/refresh_alt.png b/src/Android/Resources/drawable-xxxhdpi/refresh_alt.png new file mode 100644 index 000000000..88f56062c Binary files /dev/null and b/src/Android/Resources/drawable-xxxhdpi/refresh_alt.png differ diff --git a/src/Android/Resources/drawable/refresh_alt.png b/src/Android/Resources/drawable/refresh_alt.png new file mode 100644 index 000000000..2c12530c8 Binary files /dev/null and b/src/Android/Resources/drawable/refresh_alt.png differ diff --git a/src/App/Controls/FormEntryCell.cs b/src/App/Controls/FormEntryCell.cs index eecaab319..218c7d673 100644 --- a/src/App/Controls/FormEntryCell.cs +++ b/src/App/Controls/FormEntryCell.cs @@ -11,6 +11,7 @@ namespace Bit.App.Controls { private VisualElement _nextElement; private TapGestureRecognizer _tgr; + private StackLayout _buttonStackLayout = null; public FormEntryCell( string labelText, @@ -20,7 +21,8 @@ namespace Bit.App.Controls bool useLabelAsPlaceholder = false, string imageSource = null, Thickness? containerPadding = null, - bool useButton = false) + string button1 = null, + string button2 = null) { if(!useLabelAsPlaceholder) { @@ -83,8 +85,57 @@ namespace Bit.App.Controls VerticalOptions = LayoutOptions.CenterAndExpand }; + if(!useLabelAsPlaceholder) + { + formStackLayout.Children.Add(Label); + } + + formStackLayout.Children.Add(Entry); + imageStackLayout.Children.Add(formStackLayout); + + if(!string.IsNullOrWhiteSpace(button1) || !string.IsNullOrWhiteSpace(button2)) + { + _buttonStackLayout = new StackLayout + { + Orientation = StackOrientation.Horizontal, + VerticalOptions = LayoutOptions.CenterAndExpand + }; + imageStackLayout.Children.Add(_buttonStackLayout); + + if(!string.IsNullOrWhiteSpace(button1)) + { + Button1 = new ExtendedButton { Image = button1 }; + _buttonStackLayout.Children.Add(Button1); + + if(Device.RuntimePlatform == Device.Android) + { + Button1.Padding = new Thickness(0); + Button1.BackgroundColor = Color.Transparent; + Button1.WidthRequest = 40; + } + } + + if(!string.IsNullOrWhiteSpace(button2)) + { + Button2 = new ExtendedButton { Image = button2 }; + _buttonStackLayout.Children.Add(Button2); + + if(Device.RuntimePlatform == Device.Android) + { + Button2.Padding = new Thickness(0); + Button2.BackgroundColor = Color.Transparent; + Button2.WidthRequest = 40; + } + } + } + if(Device.RuntimePlatform == Device.Android) { + if(_buttonStackLayout != null) + { + _buttonStackLayout.Spacing = 5; + } + var deviceInfo = Resolver.Resolve(); if(useLabelAsPlaceholder) { @@ -107,25 +158,11 @@ namespace Bit.App.Controls imageStackLayout.AdjustPaddingForDevice(); } } - - if(!useLabelAsPlaceholder) + else if(Device.RuntimePlatform == Device.UWP) { - formStackLayout.Children.Add(Label); - } - - formStackLayout.Children.Add(Entry); - imageStackLayout.Children.Add(formStackLayout); - - if(useButton) - { - Button = new ExtendedButton(); - imageStackLayout.Children.Add(Button); - - if(Device.RuntimePlatform == Device.Android) + if(_buttonStackLayout != null) { - Button.Padding = new Thickness(0); - Button.BackgroundColor = Color.Transparent; - Button.WidthRequest = 40; + _buttonStackLayout.Spacing = 0; } } @@ -134,7 +171,8 @@ namespace Bit.App.Controls public Label Label { get; private set; } public ExtendedEntry Entry { get; private set; } - public ExtendedButton Button { get; private set; } + public ExtendedButton Button1 { get; private set; } + public ExtendedButton Button2 { get; private set; } public VisualElement NextElement { get => _nextElement; diff --git a/src/App/Pages/Vault/VaultAddCipherPage.cs b/src/App/Pages/Vault/VaultAddCipherPage.cs index fbec59733..d994340b2 100644 --- a/src/App/Pages/Vault/VaultAddCipherPage.cs +++ b/src/App/Pages/Vault/VaultAddCipherPage.cs @@ -101,7 +101,6 @@ namespace Bit.App.Pages public FormEntryCell LoginPasswordCell { get; private set; } public FormEntryCell LoginUsernameCell { get; private set; } public FormEntryCell LoginTotpCell { get; private set; } - public ExtendedTextCell LoginGenerateCell { get; private set; } // Card public FormEntryCell CardNameCell { get; private set; } @@ -202,11 +201,11 @@ namespace Bit.App.Pages LoginPasswordCell.InitEvents(); LoginUsernameCell.InitEvents(); LoginTotpCell.InitEvents(); - LoginPasswordCell.Button.Clicked += PasswordButton_Clicked; - LoginGenerateCell.Tapped += GenerateCell_Tapped; - if(LoginTotpCell?.Button != null) + LoginPasswordCell.Button1.Clicked += PasswordButton_Clicked; + LoginPasswordCell.Button2.Clicked += PasswordButton2_Clicked; + if(LoginTotpCell?.Button1 != null) { - LoginTotpCell.Button.Clicked += TotpButton_Clicked; + LoginTotpCell.Button1.Clicked += TotpButton_Clicked; } break; case CipherType.Card: @@ -285,11 +284,11 @@ namespace Bit.App.Pages LoginTotpCell.Dispose(); LoginPasswordCell.Dispose(); LoginUsernameCell.Dispose(); - LoginPasswordCell.Button.Clicked -= PasswordButton_Clicked; - LoginGenerateCell.Tapped -= GenerateCell_Tapped; - if(LoginTotpCell?.Button != null) + LoginPasswordCell.Button1.Clicked -= PasswordButton_Clicked; + LoginPasswordCell.Button2.Clicked += PasswordButton2_Clicked; + if(LoginTotpCell?.Button1 != null) { - LoginTotpCell.Button.Clicked -= TotpButton_Clicked; + LoginTotpCell.Button1.Clicked -= TotpButton_Clicked; } break; case CipherType.Card: @@ -342,10 +341,20 @@ namespace Bit.App.Pages private void PasswordButton_Clicked(object sender, EventArgs e) { LoginPasswordCell.Entry.InvokeToggleIsPassword(); - LoginPasswordCell.Button.Image = + LoginPasswordCell.Button1.Image = "eye" + (!LoginPasswordCell.Entry.IsPasswordFromToggled ? "_slash" : string.Empty) + ".png"; } + private async void PasswordButton2_Clicked(object sender, EventArgs e) + { + var page = new ToolsPasswordGeneratorPage((password) => + { + LoginPasswordCell.Entry.Text = password; + _deviceActionService.Toast(AppResources.PasswordGenerated); + }, _fromAutofill); + await Navigation.PushForDeviceAsync(page); + } + private async void TotpButton_Clicked(object sender, EventArgs e) { var scanPage = new ScanPage((key) => @@ -368,16 +377,6 @@ namespace Bit.App.Pages await Navigation.PushModalAsync(new ExtendedNavigationPage(scanPage)); } - private async void GenerateCell_Tapped(object sender, EventArgs e) - { - var page = new ToolsPasswordGeneratorPage((password) => - { - LoginPasswordCell.Entry.Text = password; - _deviceActionService.Toast(AppResources.PasswordGenerated); - }, _fromAutofill); - await Navigation.PushForDeviceAsync(page); - } - private void AlertNoConnection() { DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, @@ -400,19 +399,15 @@ namespace Bit.App.Pages if(_type == CipherType.Login) { - LoginTotpCell = new FormEntryCell(AppResources.AuthenticatorKey, useButton: _deviceInfo.HasCamera); - if(_deviceInfo.HasCamera) - { - LoginTotpCell.Button.Image = "camera.png"; - } + LoginTotpCell = new FormEntryCell(AppResources.AuthenticatorKey, + button1: _deviceInfo.HasCamera ? "camera.png" : null); LoginTotpCell.Entry.DisableAutocapitalize = true; LoginTotpCell.Entry.Autocorrect = false; LoginTotpCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", Windows: "Courier"); LoginPasswordCell = new FormEntryCell(AppResources.Password, isPassword: true, nextElement: LoginTotpCell.Entry, - useButton: true); - LoginPasswordCell.Button.Image = "eye.png"; + button1: "eye.png", button2: "refresh_alt.png"); LoginPasswordCell.Entry.DisableAutocapitalize = true; LoginPasswordCell.Entry.Autocorrect = false; LoginPasswordCell.Entry.FontFamily = @@ -422,12 +417,6 @@ namespace Bit.App.Pages LoginPasswordCell.Entry.Text = _defaultPassword; } - LoginGenerateCell = new ExtendedTextCell - { - Text = AppResources.GeneratePassword, - ShowDisclousure = true - }; - LoginUsernameCell = new FormEntryCell(AppResources.Username, nextElement: LoginPasswordCell.Entry); LoginUsernameCell.Entry.DisableAutocapitalize = true; LoginUsernameCell.Entry.Autocorrect = false; @@ -441,7 +430,6 @@ namespace Bit.App.Pages // Build sections TopSection.Add(LoginUsernameCell); TopSection.Add(LoginPasswordCell); - TopSection.Add(LoginGenerateCell); TopSection.Add(LoginTotpCell); // Uris diff --git a/src/App/Pages/Vault/VaultEditCipherPage.cs b/src/App/Pages/Vault/VaultEditCipherPage.cs index 9aa2c8f93..b39e4d3a8 100644 --- a/src/App/Pages/Vault/VaultEditCipherPage.cs +++ b/src/App/Pages/Vault/VaultEditCipherPage.cs @@ -59,7 +59,6 @@ namespace Bit.App.Pages public FormEntryCell LoginPasswordCell { get; private set; } public FormEntryCell LoginUsernameCell { get; private set; } public FormEntryCell LoginTotpCell { get; private set; } - public ExtendedTextCell LoginGenerateCell { get; private set; } // Card public FormEntryCell CardNameCell { get; private set; } @@ -170,11 +169,8 @@ namespace Bit.App.Pages // Types if(Cipher.Type == CipherType.Login) { - LoginTotpCell = new FormEntryCell(AppResources.AuthenticatorKey, useButton: _deviceInfo.HasCamera); - if(_deviceInfo.HasCamera) - { - LoginTotpCell.Button.Image = "camera.png"; - } + LoginTotpCell = new FormEntryCell(AppResources.AuthenticatorKey, + button1: _deviceInfo.HasCamera ? "camera.png" : null); LoginTotpCell.Entry.Text = Cipher.Login?.Totp?.Decrypt(Cipher.OrganizationId); LoginTotpCell.Entry.DisableAutocapitalize = true; LoginTotpCell.Entry.Autocorrect = false; @@ -182,20 +178,13 @@ namespace Bit.App.Pages Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", Windows: "Courier"); LoginPasswordCell = new FormEntryCell(AppResources.Password, isPassword: true, - nextElement: LoginTotpCell.Entry, useButton: true); + nextElement: LoginTotpCell.Entry, button1: "eye.png", button2: "refresh_alt.png"); LoginPasswordCell.Entry.Text = Cipher.Login?.Password?.Decrypt(Cipher.OrganizationId); - LoginPasswordCell.Button.Image = "eye.png"; LoginPasswordCell.Entry.DisableAutocapitalize = true; LoginPasswordCell.Entry.Autocorrect = false; LoginPasswordCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", Windows: "Courier"); - LoginGenerateCell = new ExtendedTextCell - { - Text = AppResources.GeneratePassword, - ShowDisclousure = true - }; - LoginUsernameCell = new FormEntryCell(AppResources.Username, nextElement: LoginPasswordCell.Entry); LoginUsernameCell.Entry.Text = Cipher.Login?.Username?.Decrypt(Cipher.OrganizationId); LoginUsernameCell.Entry.DisableAutocapitalize = true; @@ -207,7 +196,6 @@ namespace Bit.App.Pages // Build sections TopSection.Add(LoginUsernameCell); TopSection.Add(LoginPasswordCell); - TopSection.Add(LoginGenerateCell); TopSection.Add(LoginTotpCell); // Uris @@ -709,17 +697,17 @@ namespace Bit.App.Pages LoginPasswordCell?.InitEvents(); LoginUsernameCell?.InitEvents(); LoginTotpCell?.InitEvents(); - if(LoginPasswordCell?.Button != null) + if(LoginPasswordCell?.Button1 != null) { - LoginPasswordCell.Button.Clicked += PasswordButton_Clicked; + LoginPasswordCell.Button1.Clicked += PasswordButton_Clicked; } - if(LoginGenerateCell != null) + if(LoginPasswordCell?.Button2 != null) { - LoginGenerateCell.Tapped += GenerateCell_Tapped; + LoginPasswordCell.Button2.Clicked += PasswordButton2_Clicked; } - if(LoginTotpCell?.Button != null) + if(LoginTotpCell?.Button1 != null) { - LoginTotpCell.Button.Clicked += TotpButton_Clicked; + LoginTotpCell.Button1.Clicked += TotpButton_Clicked; } break; case CipherType.Card: @@ -789,17 +777,17 @@ namespace Bit.App.Pages LoginTotpCell?.Dispose(); LoginPasswordCell?.Dispose(); LoginUsernameCell?.Dispose(); - if(LoginPasswordCell?.Button != null) + if(LoginPasswordCell?.Button1 != null) { - LoginPasswordCell.Button.Clicked -= PasswordButton_Clicked; + LoginPasswordCell.Button1.Clicked -= PasswordButton_Clicked; } - if(LoginGenerateCell != null) + if(LoginPasswordCell?.Button2 != null) { - LoginGenerateCell.Tapped -= GenerateCell_Tapped; + LoginPasswordCell.Button2.Clicked -= PasswordButton2_Clicked; } - if(LoginTotpCell?.Button != null) + if(LoginTotpCell?.Button1 != null) { - LoginTotpCell.Button.Clicked -= TotpButton_Clicked; + LoginTotpCell.Button1.Clicked -= TotpButton_Clicked; } break; case CipherType.Card: @@ -841,10 +829,26 @@ namespace Bit.App.Pages private void PasswordButton_Clicked(object sender, EventArgs e) { LoginPasswordCell.Entry.InvokeToggleIsPassword(); - LoginPasswordCell.Button.Image = + LoginPasswordCell.Button1.Image = "eye" + (!LoginPasswordCell.Entry.IsPasswordFromToggled ? "_slash" : string.Empty) + ".png"; } + private async void PasswordButton2_Clicked(object sender, EventArgs e) + { + if(!string.IsNullOrWhiteSpace(LoginPasswordCell.Entry.Text) + && !(await DisplayAlert(null, AppResources.PasswordOverrideAlert, AppResources.Yes, AppResources.No))) + { + return; + } + + var page = new ToolsPasswordGeneratorPage((password) => + { + LoginPasswordCell.Entry.Text = password; + _deviceActionService.Toast(AppResources.PasswordGenerated); + }); + await Navigation.PushForDeviceAsync(page); + } + private async void TotpButton_Clicked(object sender, EventArgs e) { var scanPage = new ScanPage((key) => @@ -867,22 +871,6 @@ namespace Bit.App.Pages await Navigation.PushModalAsync(new ExtendedNavigationPage(scanPage)); } - private async void GenerateCell_Tapped(object sender, EventArgs e) - { - if(!string.IsNullOrWhiteSpace(LoginPasswordCell.Entry.Text) - && !(await DisplayAlert(null, AppResources.PasswordOverrideAlert, AppResources.Yes, AppResources.No))) - { - return; - } - - var page = new ToolsPasswordGeneratorPage((password) => - { - LoginPasswordCell.Entry.Text = password; - _deviceActionService.Toast(AppResources.PasswordGenerated); - }); - await Navigation.PushForDeviceAsync(page); - } - private async void AttachmentsCell_Tapped(object sender, EventArgs e) { var page = new ExtendedNavigationPage(new VaultAttachmentsPage(_cipherId)); diff --git a/src/App/Utilities/Helpers.cs b/src/App/Utilities/Helpers.cs index 67b25a729..a38f0c5be 100644 --- a/src/App/Utilities/Helpers.cs +++ b/src/App/Utilities/Helpers.cs @@ -257,7 +257,8 @@ namespace Bit.App.Utilities case FieldType.Text: case FieldType.Hidden: var hidden = type == FieldType.Hidden; - var textFieldCell = new FormEntryCell(label, isPassword: hidden, useButton: hidden); + var textFieldCell = new FormEntryCell(label, isPassword: hidden, + button1: hidden ? "eye.png" : null); textFieldCell.Entry.Text = value; textFieldCell.Entry.DisableAutocapitalize = true; textFieldCell.Entry.Autocorrect = false; @@ -266,11 +267,10 @@ namespace Bit.App.Utilities { textFieldCell.Entry.FontFamily = Helpers.OnPlatform( iOS: "Menlo-Regular", Android: "monospace", Windows: "Courier"); - textFieldCell.Button.Image = "eye.png"; - textFieldCell.Button.Command = new Command(() => + textFieldCell.Button1.Command = new Command(() => { textFieldCell.Entry.InvokeToggleIsPassword(); - textFieldCell.Button.Image = + textFieldCell.Button1.Image = "eye" + (!textFieldCell.Entry.IsPasswordFromToggled ? "_slash" : string.Empty) + ".png"; }); } diff --git a/src/UWP.Images/UWP.Images.projitems b/src/UWP.Images/UWP.Images.projitems index cadc2367b..8b39eb181 100644 --- a/src/UWP.Images/UWP.Images.projitems +++ b/src/UWP.Images/UWP.Images.projitems @@ -43,6 +43,7 @@ + diff --git a/src/UWP.Images/refresh_alt.png b/src/UWP.Images/refresh_alt.png new file mode 100644 index 000000000..decdd33f9 Binary files /dev/null and b/src/UWP.Images/refresh_alt.png differ diff --git a/src/iOS/Resources/refresh_alt.png b/src/iOS/Resources/refresh_alt.png new file mode 100644 index 000000000..2c12530c8 Binary files /dev/null and b/src/iOS/Resources/refresh_alt.png differ diff --git a/src/iOS/Resources/refresh_alt@2x.png b/src/iOS/Resources/refresh_alt@2x.png new file mode 100644 index 000000000..decdd33f9 Binary files /dev/null and b/src/iOS/Resources/refresh_alt@2x.png differ diff --git a/src/iOS/Resources/refresh_alt@3x.png b/src/iOS/Resources/refresh_alt@3x.png new file mode 100644 index 000000000..5c100820a Binary files /dev/null and b/src/iOS/Resources/refresh_alt@3x.png differ diff --git a/src/iOS/iOS.csproj b/src/iOS/iOS.csproj index 9b60de8f4..a2978a8a5 100644 --- a/src/iOS/iOS.csproj +++ b/src/iOS/iOS.csproj @@ -710,5 +710,14 @@ 2.0.5782 + + + + + + + + + \ No newline at end of file