From db6ceea711df4d8dc51d948d56df7ccd1a460dcd Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Mon, 7 Nov 2016 22:07:33 -0500 Subject: [PATCH] Added button to toggle password field visibility on site edit --- src/Android/Controls/ExtendedEntryRenderer.cs | 48 ++++++++++++++++++- src/App/Controls/ExtendedEntry.cs | 17 +++++++ src/App/Controls/FormEntryCell.cs | 10 +++- src/App/Pages/Vault/VaultEditSitePage.cs | 18 +++++-- 4 files changed, 88 insertions(+), 5 deletions(-) diff --git a/src/Android/Controls/ExtendedEntryRenderer.cs b/src/Android/Controls/ExtendedEntryRenderer.cs index dd8441018..db447f370 100644 --- a/src/Android/Controls/ExtendedEntryRenderer.cs +++ b/src/Android/Controls/ExtendedEntryRenderer.cs @@ -16,11 +16,16 @@ namespace Bit.Android.Controls { public class ExtendedEntryRenderer : EntryRenderer { + private bool _isPassword; + private bool _toggledPassword; + protected override void OnElementChanged(ElementChangedEventArgs e) { base.OnElementChanged(e); var view = (ExtendedEntry)Element; + _isPassword = view.IsPassword; + if(Control != null) { Control.SetIncludeFontPadding(false); @@ -56,8 +61,44 @@ namespace Bit.Android.Controls { Control.SetRawInputType(Control.InputType |= InputTypes.TextFlagNoSuggestions); } - } + view.ToggleIsPassword += (object sender, EventArgs args) => + { + var cursorStart = Control.SelectionStart; + var cursorEnd = Control.SelectionEnd; + + Control.TransformationMethod = _isPassword ? null : new PasswordTransformationMethod(); + + // set focus + Control.RequestFocus(); + + if(_toggledPassword) + { + // restore cursor position + Control.SetSelection(cursorStart, cursorEnd); + } + else + { + // set cursor to end + Control.SetSelection(Control.Text.Length); + } + + // show keyboard + var app = XLabs.Ioc.Resolver.Resolve(); + var inputMethodManager = + app.GetSystemService(global::Android.Content.Context.InputMethodService) as InputMethodManager; + inputMethodManager.ShowSoftInput(Control, ShowFlags.Forced); + inputMethodManager.ToggleSoftInput(ShowFlags.Forced, HideSoftInputFlags.ImplicitOnly); + + _isPassword = view.IsPasswordFromToggled = !_isPassword; + _toggledPassword = true; + }; + + if(view.FontFamily == "monospace") + { + Control.Typeface = Typeface.Monospace; + } + } protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { var view = (ExtendedEntry)Element; @@ -76,6 +117,11 @@ namespace Bit.Android.Controls Control.SetBackgroundColor(view.BackgroundColor.ToAndroid()); } } + + if(view.FontFamily == "monospace") + { + Control.Typeface = Typeface.Monospace; + } } private void SetReturnType(ExtendedEntry view) diff --git a/src/App/Controls/ExtendedEntry.cs b/src/App/Controls/ExtendedEntry.cs index bc93961d5..201bb9152 100644 --- a/src/App/Controls/ExtendedEntry.cs +++ b/src/App/Controls/ExtendedEntry.cs @@ -12,6 +12,8 @@ namespace Bit.App.Controls { PlaceholderColor = Color.FromHex("c7c7cd"); } + + IsPasswordFromToggled = IsPassword; } public static readonly BindableProperty HasBorderProperty = @@ -62,5 +64,20 @@ namespace Bit.App.Controls { Completed?.Invoke(this, null); } + + public virtual void InvokeToggleIsPassword() + { + if(ToggleIsPassword == null) + { + IsPassword = IsPasswordFromToggled = !IsPassword; + } + else + { + ToggleIsPassword.Invoke(this, null); + } + } + + public event EventHandler ToggleIsPassword; + public bool IsPasswordFromToggled { get; set; } = false; } } diff --git a/src/App/Controls/FormEntryCell.cs b/src/App/Controls/FormEntryCell.cs index 8e98ee013..0ab4027c5 100644 --- a/src/App/Controls/FormEntryCell.cs +++ b/src/App/Controls/FormEntryCell.cs @@ -14,7 +14,8 @@ namespace Bit.App.Controls VisualElement nextElement = null, bool useLabelAsPlaceholder = false, string imageSource = null, - Thickness? containerPadding = null) + Thickness? containerPadding = null, + bool useButton = false) { if(!useLabelAsPlaceholder) { @@ -112,6 +113,12 @@ namespace Bit.App.Controls formStackLayout.Children.Add(Entry); imageStackLayout.Children.Add(formStackLayout); + if(useButton) + { + Button = new ExtendedButton(); + imageStackLayout.Children.Add(Button); + } + Tapped += FormEntryCell_Tapped; View = imageStackLayout; @@ -119,6 +126,7 @@ namespace Bit.App.Controls public Label Label { get; private set; } public ExtendedEntry Entry { get; private set; } + public ExtendedButton Button { get; private set; } private void Tgr_Tapped(object sender, EventArgs e) { diff --git a/src/App/Pages/Vault/VaultEditSitePage.cs b/src/App/Pages/Vault/VaultEditSitePage.cs index 17cf62084..0e1dd75f6 100644 --- a/src/App/Pages/Vault/VaultEditSitePage.cs +++ b/src/App/Pages/Vault/VaultEditSitePage.cs @@ -45,15 +45,21 @@ namespace Bit.App.Pages var notesCell = new FormEditorCell(height: 90); notesCell.Editor.Text = site.Notes?.Decrypt(); - PasswordCell = new FormEntryCell(AppResources.Password, IsPassword: true, nextElement: notesCell.Editor); + + PasswordCell = new FormEntryCell(AppResources.Password, IsPassword: true, nextElement: notesCell.Editor, + useButton: true); PasswordCell.Entry.Text = site.Password?.Decrypt(); + PasswordCell.Button.Image = "eye"; + PasswordCell.Button.Clicked += PasswordButton_Clicked; + var usernameCell = new FormEntryCell(AppResources.Username, nextElement: PasswordCell.Entry); usernameCell.Entry.Text = site.Username?.Decrypt(); usernameCell.Entry.DisableAutocapitalize = true; usernameCell.Entry.Autocorrect = false; - usernameCell.Entry.FontFamily = PasswordCell.Entry.FontFamily = Device.OnPlatform( - iOS: "Courier", Android: "monospace", WinPhone: "Courier"); + + usernameCell.Entry.FontFamily = PasswordCell.Entry.FontFamily = + Device.OnPlatform(iOS: "Courier", Android: "monospace", WinPhone: "Courier"); var uriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: usernameCell.Entry); uriCell.Entry.Text = site.Uri?.Decrypt(); @@ -192,6 +198,12 @@ namespace Bit.App.Pages } } + private void PasswordButton_Clicked(object sender, EventArgs e) + { + PasswordCell.Entry.InvokeToggleIsPassword(); + PasswordCell.Button.Image = "eye" + (!PasswordCell.Entry.IsPasswordFromToggled ? "_slash" : string.Empty); + } + protected override void OnAppearing() { base.OnAppearing();