From f5e7f9249c05d4e4374a5528ceef5e1ca9060409 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Wed, 15 Feb 2017 00:28:05 -0500 Subject: [PATCH] attach and detach event handlers onappearing and ondisappearing to free up views for GC --- src/App/Controls/DismissModalToolBarItem.cs | 15 ++- src/App/Controls/FormEditorCell.cs | 13 ++- src/App/Controls/FormEntryCell.cs | 46 ++++++++-- src/App/Controls/FormPickerCell.cs | 13 ++- src/App/Controls/PinControl.cs | 15 ++- src/App/Controls/StepperCell.cs | 18 +++- src/App/Pages/Lock/LockPasswordPage.cs | 10 +- src/App/Pages/Lock/LockPinPage.cs | 22 +++-- src/App/Pages/LoginPage.cs | 13 ++- src/App/Pages/LoginTwoFactorPage.cs | 10 +- src/App/Pages/PasswordHintPage.cs | 10 +- src/App/Pages/RegisterPage.cs | 15 ++- .../Pages/Settings/SettingsAddFolderPage.cs | 17 +++- .../Pages/Settings/SettingsEditFolderPage.cs | 28 ++++-- src/App/Pages/Settings/SettingsPinPage.cs | 10 +- .../ToolsPasswordGeneratorSettingsPage.cs | 13 ++- src/App/Pages/Vault/VaultAddLoginPage.cs | 78 ++++++++++------ src/App/Pages/Vault/VaultEditLoginPage.cs | 92 ++++++++++++------- 18 files changed, 332 insertions(+), 106 deletions(-) diff --git a/src/App/Controls/DismissModalToolBarItem.cs b/src/App/Controls/DismissModalToolBarItem.cs index 22d050727..739f452ba 100644 --- a/src/App/Controls/DismissModalToolBarItem.cs +++ b/src/App/Controls/DismissModalToolBarItem.cs @@ -4,7 +4,7 @@ using Xamarin.Forms; namespace Bit.App.Controls { - public class DismissModalToolBarItem : ToolbarItem + public class DismissModalToolBarItem : ToolbarItem, IDisposable { private readonly ContentPage _page; private readonly Action _cancelClickedAction; @@ -13,8 +13,9 @@ namespace Bit.App.Controls { _cancelClickedAction = cancelClickedAction; _page = page; + // TODO: init and dispose events from pages + InitEvents(); Text = text ?? AppResources.Close; - Clicked += ClickedItem; Priority = -1; } @@ -23,5 +24,15 @@ namespace Bit.App.Controls _cancelClickedAction?.Invoke(); await _page.Navigation.PopModalAsync(); } + + public void InitEvents() + { + Clicked += ClickedItem; + } + + public void Dispose() + { + Clicked -= ClickedItem; + } } } diff --git a/src/App/Controls/FormEditorCell.cs b/src/App/Controls/FormEditorCell.cs index 2fe9d28bb..b77457c21 100644 --- a/src/App/Controls/FormEditorCell.cs +++ b/src/App/Controls/FormEditorCell.cs @@ -3,7 +3,7 @@ using Xamarin.Forms; namespace Bit.App.Controls { - public class FormEditorCell : ExtendedViewCell + public class FormEditorCell : ExtendedViewCell, IDisposable { public FormEditorCell(Keyboard entryKeyboard = null, double? height = null) { @@ -26,7 +26,6 @@ namespace Bit.App.Controls stackLayout.Children.Add(Editor); - Tapped += FormEditorCell_Tapped; Editor.AdjustMarginsForDevice(); stackLayout.AdjustPaddingForDevice(); @@ -39,5 +38,15 @@ namespace Bit.App.Controls { Editor.Focus(); } + + public void InitEvents() + { + Tapped += FormEditorCell_Tapped; + } + + public void Dispose() + { + Tapped -= FormEditorCell_Tapped; + } } } diff --git a/src/App/Controls/FormEntryCell.cs b/src/App/Controls/FormEntryCell.cs index 099cb185e..368490417 100644 --- a/src/App/Controls/FormEntryCell.cs +++ b/src/App/Controls/FormEntryCell.cs @@ -5,8 +5,11 @@ using XLabs.Ioc; namespace Bit.App.Controls { - public class FormEntryCell : ExtendedViewCell + public class FormEntryCell : ExtendedViewCell, IDisposable { + private VisualElement _nextElement; + private TapGestureRecognizer _tgr; + public FormEntryCell( string labelText, Keyboard entryKeyboard = null, @@ -17,6 +20,8 @@ namespace Bit.App.Controls Thickness? containerPadding = null, bool useButton = false) { + _nextElement = nextElement; + if(!useLabelAsPlaceholder) { Label = new Label @@ -47,7 +52,6 @@ namespace Bit.App.Controls if(nextElement != null) { Entry.ReturnType = Enums.ReturnType.Next; - Entry.Completed += (object sender, EventArgs e) => { nextElement.Focus(); }; } var imageStackLayout = new StackLayout @@ -61,8 +65,7 @@ namespace Bit.App.Controls if(imageSource != null) { - var tgr = new TapGestureRecognizer(); - tgr.Tapped += Tgr_Tapped; + _tgr = new TapGestureRecognizer(); var theImage = new Image { @@ -70,7 +73,7 @@ namespace Bit.App.Controls HorizontalOptions = LayoutOptions.Start, VerticalOptions = LayoutOptions.Center }; - theImage.GestureRecognizers.Add(tgr); + theImage.GestureRecognizers.Add(_tgr); imageStackLayout.Children.Add(theImage); } @@ -126,8 +129,6 @@ namespace Bit.App.Controls } } - Tapped += FormEntryCell_Tapped; - View = imageStackLayout; } @@ -135,6 +136,21 @@ namespace Bit.App.Controls public ExtendedEntry Entry { get; private set; } public ExtendedButton Button { get; private set; } + public void InitEvents() + { + if(_nextElement != null) + { + Entry.Completed += Entry_Completed; + } + + if(_tgr != null) + { + _tgr.Tapped += Tgr_Tapped; + } + + Tapped += FormEntryCell_Tapped; + } + private void Tgr_Tapped(object sender, EventArgs e) { Entry.Focus(); @@ -144,5 +160,21 @@ namespace Bit.App.Controls { Entry.Focus(); } + + private void Entry_Completed(object sender, EventArgs e) + { + _nextElement?.Focus(); + } + + public void Dispose() + { + if(_tgr != null) + { + _tgr.Tapped -= Tgr_Tapped; + } + + Tapped -= FormEntryCell_Tapped; + Entry.Completed -= Entry_Completed; + } } } diff --git a/src/App/Controls/FormPickerCell.cs b/src/App/Controls/FormPickerCell.cs index bd95aba5f..a7f3d7112 100644 --- a/src/App/Controls/FormPickerCell.cs +++ b/src/App/Controls/FormPickerCell.cs @@ -1,5 +1,4 @@ using System; -using Bit.App.Resources; using Xamarin.Forms; namespace Bit.App.Controls @@ -42,8 +41,6 @@ namespace Bit.App.Controls Picker.AdjustMarginsForDevice(); stackLayout.AdjustPaddingForDevice(); - Tapped += FormPickerCell_Tapped; - View = stackLayout; } @@ -54,5 +51,15 @@ namespace Bit.App.Controls { Picker.Focus(); } + + public void InitEvents() + { + Tapped += FormPickerCell_Tapped; + } + + public void Dispose() + { + Tapped -= FormPickerCell_Tapped; + } } } diff --git a/src/App/Controls/PinControl.cs b/src/App/Controls/PinControl.cs index ce3e60d91..68fa54ad0 100644 --- a/src/App/Controls/PinControl.cs +++ b/src/App/Controls/PinControl.cs @@ -22,7 +22,6 @@ namespace Bit.App.Controls MaxLength = 4, Margin = new Thickness(0, int.MaxValue, 0, 0) }; - Entry.TextChanged += Entry_TextChanged; if(Device.OS == TargetPlatform.Android) { @@ -30,6 +29,9 @@ namespace Bit.App.Controls } } + public Label Label { get; set; } + public ExtendedEntry Entry { get; set; } + private void Entry_TextChanged(object sender, TextChangedEventArgs e) { if(e.NewTextValue.Length >= 4) @@ -38,7 +40,14 @@ namespace Bit.App.Controls } } - public Label Label { get; set; } - public ExtendedEntry Entry { get; set; } + public void InitEvents() + { + Entry.TextChanged += Entry_TextChanged; + } + + public void Dispose() + { + Entry.TextChanged -= Entry_TextChanged; + } } } diff --git a/src/App/Controls/StepperCell.cs b/src/App/Controls/StepperCell.cs index ca2e436a0..a23f66674 100644 --- a/src/App/Controls/StepperCell.cs +++ b/src/App/Controls/StepperCell.cs @@ -34,8 +34,6 @@ namespace Bit.App.Controls Value = value }; - Stepper.ValueChanged += Stepper_ValueChanged; - var stackLayout = new StackLayout { Orientation = StackOrientation.Horizontal, @@ -56,13 +54,23 @@ namespace Bit.App.Controls View = stackLayout; } + public Label Label { get; private set; } + public Label StepperValueLabel { get; private set; } + public Stepper Stepper { get; private set; } + private void Stepper_ValueChanged(object sender, ValueChangedEventArgs e) { StepperValueLabel.Text = e.NewValue.ToString(); } - public Label Label { get; private set; } - public Label StepperValueLabel { get; private set; } - public Stepper Stepper { get; private set; } + public void InitEvents() + { + Stepper.ValueChanged += Stepper_ValueChanged; + } + + public void Dispose() + { + Stepper.ValueChanged -= Stepper_ValueChanged; + } } } diff --git a/src/App/Pages/Lock/LockPasswordPage.cs b/src/App/Pages/Lock/LockPasswordPage.cs index 89d0c3016..762710f24 100644 --- a/src/App/Pages/Lock/LockPasswordPage.cs +++ b/src/App/Pages/Lock/LockPasswordPage.cs @@ -38,7 +38,6 @@ namespace Bit.App.Pages useLabelAsPlaceholder: true, imageSource: "lock", containerPadding: padding); PasswordCell.Entry.ReturnType = Enums.ReturnType.Go; - PasswordCell.Entry.Completed += Entry_Completed; var table = new ExtendedTableView { @@ -99,7 +98,16 @@ namespace Bit.App.Pages protected override void OnAppearing() { base.OnAppearing(); + PasswordCell.InitEvents(); PasswordCell.Entry.FocusWithDelay(); + PasswordCell.Entry.Completed += Entry_Completed; + } + + protected override void OnDisappearing() + { + base.OnDisappearing(); + PasswordCell.Dispose(); + PasswordCell.Entry.Completed -= Entry_Completed; } protected async Task CheckPasswordAsync() diff --git a/src/App/Pages/Lock/LockPinPage.cs b/src/App/Pages/Lock/LockPinPage.cs index 6d4f88d9a..53e56303a 100644 --- a/src/App/Pages/Lock/LockPinPage.cs +++ b/src/App/Pages/Lock/LockPinPage.cs @@ -15,6 +15,7 @@ namespace Bit.App.Pages { private readonly IAuthService _authService; private readonly ISettings _settings; + private TapGestureRecognizer _tgr; public LockPinPage() { @@ -39,7 +40,6 @@ namespace Bit.App.Pages }; PinControl = new PinControl(); - PinControl.OnPinEntered += PinEntered; PinControl.Label.SetBinding(Label.TextProperty, s => s.LabelText); PinControl.Entry.SetBinding(Entry.TextProperty, s => s.PIN); @@ -60,14 +60,13 @@ namespace Bit.App.Pages Children = { PinControl.Label, instructionLabel, logoutButton, PinControl.Entry } }; - var tgr = new TapGestureRecognizer(); - tgr.Tapped += Tgr_Tapped; - PinControl.Label.GestureRecognizers.Add(tgr); - instructionLabel.GestureRecognizers.Add(tgr); + _tgr = new TapGestureRecognizer(); + PinControl.Label.GestureRecognizers.Add(_tgr); + instructionLabel.GestureRecognizers.Add(_tgr); Title = AppResources.VerifyPIN; Content = stackLayout; - Content.GestureRecognizers.Add(tgr); + Content.GestureRecognizers.Add(_tgr); BindingContext = Model; } @@ -79,9 +78,20 @@ namespace Bit.App.Pages protected override void OnAppearing() { base.OnAppearing(); + _tgr.Tapped += Tgr_Tapped; + PinControl.OnPinEntered += PinEntered; + PinControl.InitEvents(); PinControl.Entry.FocusWithDelay(); } + protected override void OnDisappearing() + { + base.OnDisappearing(); + _tgr.Tapped -= Tgr_Tapped; + PinControl.OnPinEntered -= PinEntered; + PinControl.Dispose(); + } + protected void PinEntered(object sender, EventArgs args) { if(Model.PIN == _authService.PIN) diff --git a/src/App/Pages/LoginPage.cs b/src/App/Pages/LoginPage.cs index 06ca9b6a4..4fe3c08cf 100644 --- a/src/App/Pages/LoginPage.cs +++ b/src/App/Pages/LoginPage.cs @@ -74,7 +74,6 @@ namespace Bit.App.Pages } PasswordCell.Entry.ReturnType = Enums.ReturnType.Go; - PasswordCell.Entry.Completed += Entry_Completed; var table = new ExtendedTableView { @@ -136,6 +135,10 @@ namespace Bit.App.Pages protected override void OnAppearing() { base.OnAppearing(); + PasswordCell.InitEvents(); + EmailCell.InitEvents(); + + PasswordCell.Entry.Completed += Entry_Completed; MessagingCenter.Send(Application.Current, "ShowStatusBar", true); if(string.IsNullOrWhiteSpace(_email)) @@ -151,6 +154,14 @@ namespace Bit.App.Pages } } + protected override void OnDisappearing() + { + base.OnDisappearing(); + PasswordCell.Dispose(); + EmailCell.Dispose(); + PasswordCell.Entry.Completed -= Entry_Completed; + } + private async void Entry_Completed(object sender, EventArgs e) { await LogIn(); diff --git a/src/App/Pages/LoginTwoFactorPage.cs b/src/App/Pages/LoginTwoFactorPage.cs index 201e08b2b..e39532d07 100644 --- a/src/App/Pages/LoginTwoFactorPage.cs +++ b/src/App/Pages/LoginTwoFactorPage.cs @@ -64,7 +64,6 @@ namespace Bit.App.Pages CodeCell.Entry.Keyboard = Keyboard.Numeric; CodeCell.Entry.ReturnType = Enums.ReturnType.Go; - CodeCell.Entry.Completed += Entry_Completed; var table = new ExtendedTableView { @@ -129,7 +128,16 @@ namespace Bit.App.Pages protected override void OnAppearing() { base.OnAppearing(); + CodeCell.InitEvents(); CodeCell.Entry.FocusWithDelay(); + CodeCell.Entry.Completed += Entry_Completed; + } + + protected override void OnDisappearing() + { + base.OnDisappearing(); + CodeCell.Dispose(); + CodeCell.Entry.Completed -= Entry_Completed; } private void Lost2FAApp() diff --git a/src/App/Pages/PasswordHintPage.cs b/src/App/Pages/PasswordHintPage.cs index 02cce73fc..7c7934e8d 100644 --- a/src/App/Pages/PasswordHintPage.cs +++ b/src/App/Pages/PasswordHintPage.cs @@ -38,7 +38,6 @@ namespace Bit.App.Pages useLabelAsPlaceholder: true, imageSource: "envelope", containerPadding: padding); EmailCell.Entry.ReturnType = Enums.ReturnType.Go; - EmailCell.Entry.Completed += Entry_Completed; var table = new ExtendedTableView { @@ -93,9 +92,18 @@ namespace Bit.App.Pages protected override void OnAppearing() { base.OnAppearing(); + EmailCell.InitEvents(); + EmailCell.Entry.Completed += Entry_Completed; EmailCell.Entry.FocusWithDelay(); } + protected override void OnDisappearing() + { + base.OnDisappearing(); + EmailCell.Dispose(); + EmailCell.Entry.Completed -= Entry_Completed; + } + private async void Entry_Completed(object sender, EventArgs e) { await SubmitAsync(); diff --git a/src/App/Pages/RegisterPage.cs b/src/App/Pages/RegisterPage.cs index d5fb9076d..d4e184c31 100644 --- a/src/App/Pages/RegisterPage.cs +++ b/src/App/Pages/RegisterPage.cs @@ -58,7 +58,6 @@ namespace Bit.App.Pages containerPadding: padding); PasswordHintCell.Entry.ReturnType = Enums.ReturnType.Done; - PasswordHintCell.Entry.Completed += Entry_Completed; var table = new FormTableView { @@ -144,8 +143,22 @@ namespace Bit.App.Pages { base.OnAppearing(); MessagingCenter.Send(Application.Current, "ShowStatusBar", true); + EmailCell.InitEvents(); + PasswordCell.InitEvents(); + PasswordHintCell.InitEvents(); + ConfirmPasswordCell.InitEvents(); + PasswordHintCell.Entry.Completed += Entry_Completed; EmailCell.Entry.FocusWithDelay(); } + protected override void OnDisappearing() + { + base.OnDisappearing(); + EmailCell.Dispose(); + PasswordCell.Dispose(); + PasswordHintCell.Dispose(); + ConfirmPasswordCell.Dispose(); + PasswordHintCell.Entry.Completed -= Entry_Completed; + } private async void Entry_Completed(object sender, EventArgs e) { diff --git a/src/App/Pages/Settings/SettingsAddFolderPage.cs b/src/App/Pages/Settings/SettingsAddFolderPage.cs index 9b42f7053..203a766ce 100644 --- a/src/App/Pages/Settings/SettingsAddFolderPage.cs +++ b/src/App/Pages/Settings/SettingsAddFolderPage.cs @@ -28,9 +28,11 @@ namespace Bit.App.Pages Init(); } + public FormEntryCell NameCell { get; set; } + private void Init() { - var nameCell = new FormEntryCell(AppResources.Name); + NameCell = new FormEntryCell(AppResources.Name); var table = new ExtendedTableView { @@ -41,7 +43,7 @@ namespace Bit.App.Pages { new TableSection() { - nameCell + NameCell } } }; @@ -60,7 +62,7 @@ namespace Bit.App.Pages return; } - if(string.IsNullOrWhiteSpace(nameCell.Entry.Text)) + if(string.IsNullOrWhiteSpace(NameCell.Entry.Text)) { await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.Name), AppResources.Ok); @@ -69,7 +71,7 @@ namespace Bit.App.Pages var folder = new Folder { - Name = nameCell.Entry.Text.Encrypt() + Name = NameCell.Entry.Text.Encrypt() }; _userDialogs.ShowLoading(AppResources.Saving, MaskType.Black); @@ -105,12 +107,19 @@ namespace Bit.App.Pages protected override void OnAppearing() { base.OnAppearing(); + NameCell.InitEvents(); if(!_connectivity.IsConnected) { AlertNoConnection(); } } + protected override void OnDisappearing() + { + base.OnDisappearing(); + NameCell.Dispose(); + } + private void AlertNoConnection() { DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, AppResources.Ok); diff --git a/src/App/Pages/Settings/SettingsEditFolderPage.cs b/src/App/Pages/Settings/SettingsEditFolderPage.cs index a2951369a..286ce7d74 100644 --- a/src/App/Pages/Settings/SettingsEditFolderPage.cs +++ b/src/App/Pages/Settings/SettingsEditFolderPage.cs @@ -29,6 +29,9 @@ namespace Bit.App.Pages Init(); } + public FormEntryCell NameCell { get; set; } + public ExtendedTextCell DeleteCell { get; set; } + private void Init() { var folder = _folderService.GetByIdAsync(_folderId).GetAwaiter().GetResult(); @@ -38,11 +41,10 @@ namespace Bit.App.Pages return; } - var nameCell = new FormEntryCell(AppResources.Name); - nameCell.Entry.Text = folder.Name.Decrypt(); + NameCell = new FormEntryCell(AppResources.Name); + NameCell.Entry.Text = folder.Name.Decrypt(); - var deleteCell = new ExtendedTextCell { Text = AppResources.Delete, TextColor = Color.Red }; - deleteCell.Tapped += DeleteCell_Tapped; + DeleteCell = new ExtendedTextCell { Text = AppResources.Delete, TextColor = Color.Red }; var mainTable = new ExtendedTableView { @@ -54,11 +56,11 @@ namespace Bit.App.Pages { new TableSection { - nameCell + NameCell }, new TableSection { - deleteCell + DeleteCell } } }; @@ -77,14 +79,14 @@ namespace Bit.App.Pages return; } - if(string.IsNullOrWhiteSpace(nameCell.Entry.Text)) + if(string.IsNullOrWhiteSpace(NameCell.Entry.Text)) { await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.Name), AppResources.Ok); return; } - folder.Name = nameCell.Entry.Text.Encrypt(); + folder.Name = NameCell.Entry.Text.Encrypt(); _userDialogs.ShowLoading(AppResources.Saving, MaskType.Black); var saveResult = await _folderService.SaveAsync(folder); @@ -119,12 +121,22 @@ namespace Bit.App.Pages protected override void OnAppearing() { base.OnAppearing(); + NameCell.InitEvents(); + DeleteCell.Tapped += DeleteCell_Tapped; + if(!_connectivity.IsConnected) { AlertNoConnection(); } } + protected override void OnDisappearing() + { + base.OnDisappearing(); + NameCell.Dispose(); + DeleteCell.Tapped -= DeleteCell_Tapped; + } + private async void DeleteCell_Tapped(object sender, EventArgs e) { if(!_connectivity.IsConnected) diff --git a/src/App/Pages/Settings/SettingsPinPage.cs b/src/App/Pages/Settings/SettingsPinPage.cs index cb07571a3..74968ec73 100644 --- a/src/App/Pages/Settings/SettingsPinPage.cs +++ b/src/App/Pages/Settings/SettingsPinPage.cs @@ -40,7 +40,6 @@ namespace Bit.App.Pages }; PinControl = new PinControl(); - PinControl.OnPinEntered += PinEntered; PinControl.Label.SetBinding(Label.TextProperty, s => s.LabelText); PinControl.Entry.SetBinding(Entry.TextProperty, s => s.PIN); @@ -75,9 +74,18 @@ namespace Bit.App.Pages protected override void OnAppearing() { base.OnAppearing(); + PinControl.OnPinEntered += PinEntered; + PinControl.InitEvents(); PinControl.Entry.FocusWithDelay(); } + protected override void OnDisappearing() + { + base.OnDisappearing(); + PinControl.Dispose(); + PinControl.OnPinEntered -= PinEntered; + } + protected void PinEntered(object sender, EventArgs args) { OnPinEntered.Invoke(this, null); diff --git a/src/App/Pages/Tools/ToolsPasswordGeneratorSettingsPage.cs b/src/App/Pages/Tools/ToolsPasswordGeneratorSettingsPage.cs index 392585b32..e70896c46 100644 --- a/src/App/Pages/Tools/ToolsPasswordGeneratorSettingsPage.cs +++ b/src/App/Pages/Tools/ToolsPasswordGeneratorSettingsPage.cs @@ -53,7 +53,6 @@ namespace Bit.App.Pages Text = "!@#$%^&*", On = _settings.GetValueOrDefault(Constants.PasswordGeneratorSpecial, true) }; - SpecialCell.OnChanged += SpecialCell_OnChanged; NumbersCell = new ExtendedSwitchCell { @@ -67,7 +66,6 @@ namespace Bit.App.Pages Text = AppResources.AvoidAmbiguousCharacters, On = !_settings.GetValueOrDefault(Constants.PasswordGeneratorAmbiguous, false) }; - AvoidAmbiguousCell.OnChanged += AvoidAmbiguousCell_OnChanged; ; NumbersMinCell = new StepperCell(AppResources.MinNumbers, _settings.GetValueOrDefault(Constants.PasswordGeneratorMinNumbers, 1), 0, 5, 1); @@ -111,8 +109,19 @@ namespace Bit.App.Pages Content = table; } + protected override void OnAppearing() + { + base.OnAppearing(); + SpecialCell.OnChanged += SpecialCell_OnChanged; + AvoidAmbiguousCell.OnChanged += AvoidAmbiguousCell_OnChanged; + } + protected override void OnDisappearing() { + base.OnDisappearing(); + SpecialCell.OnChanged -= SpecialCell_OnChanged; + AvoidAmbiguousCell.OnChanged -= AvoidAmbiguousCell_OnChanged; + _settings.AddOrUpdateValue(Constants.PasswordGeneratorMinNumbers, Convert.ToInt32(NumbersMinCell.Stepper.Value)); diff --git a/src/App/Pages/Vault/VaultAddLoginPage.cs b/src/App/Pages/Vault/VaultAddLoginPage.cs index 5a64c5f59..8bba60987 100644 --- a/src/App/Pages/Vault/VaultAddLoginPage.cs +++ b/src/App/Pages/Vault/VaultAddLoginPage.cs @@ -46,32 +46,37 @@ namespace Bit.App.Pages } public FormEntryCell PasswordCell { get; private set; } + public FormEntryCell UsernameCell { get; private set; } + public FormEntryCell UriCell { get; private set; } + public FormEntryCell NameCell { get; private set; } + public FormEditorCell NotesCell { get; private set; } + public FormPickerCell FolderCell { get; private set; } + public ExtendedTextCell GenerateCell { get; private set; } private void Init() { - var notesCell = new FormEditorCell(height: 90); - PasswordCell = new FormEntryCell(AppResources.Password, isPassword: true, nextElement: notesCell.Editor, + NotesCell = new FormEditorCell(height: 90); + PasswordCell = new FormEntryCell(AppResources.Password, isPassword: true, nextElement: NotesCell.Editor, useButton: true); PasswordCell.Button.Image = "eye"; - PasswordCell.Button.Clicked += PasswordButton_Clicked; PasswordCell.Entry.DisableAutocapitalize = true; PasswordCell.Entry.Autocorrect = false; PasswordCell.Entry.FontFamily = Device.OnPlatform(iOS: "Courier", Android: "monospace", WinPhone: "Courier"); - var usernameCell = new FormEntryCell(AppResources.Username, nextElement: PasswordCell.Entry); - usernameCell.Entry.DisableAutocapitalize = true; - usernameCell.Entry.Autocorrect = false; + UsernameCell = new FormEntryCell(AppResources.Username, nextElement: PasswordCell.Entry); + UsernameCell.Entry.DisableAutocapitalize = true; + UsernameCell.Entry.Autocorrect = false; - var uriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: usernameCell.Entry); + UriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: UsernameCell.Entry); if(!string.IsNullOrWhiteSpace(_defaultUri)) { - uriCell.Entry.Text = _defaultUri; + UriCell.Entry.Text = _defaultUri; } - var nameCell = new FormEntryCell(AppResources.Name, nextElement: uriCell.Entry); + NameCell = new FormEntryCell(AppResources.Name, nextElement: UriCell.Entry); if(!string.IsNullOrWhiteSpace(_defaultName)) { - nameCell.Entry.Text = _defaultName; + NameCell.Entry.Text = _defaultName; } var folderOptions = new List { AppResources.FolderNone }; @@ -81,14 +86,13 @@ namespace Bit.App.Pages { folderOptions.Add(folder.Name.Decrypt()); } - var folderCell = new FormPickerCell(AppResources.Folder, folderOptions.ToArray()); + FolderCell = new FormPickerCell(AppResources.Folder, folderOptions.ToArray()); - var generateCell = new ExtendedTextCell + GenerateCell = new ExtendedTextCell { Text = AppResources.GeneratePassword, ShowDisclousure = true }; - generateCell.Tapped += GenerateCell_Tapped; ; var favoriteCell = new ExtendedSwitchCell { Text = AppResources.Favorite }; @@ -101,20 +105,20 @@ namespace Bit.App.Pages { new TableSection(AppResources.LoginInformation) { - nameCell, - uriCell, - usernameCell, + NameCell, + UriCell, + UsernameCell, PasswordCell, - generateCell + GenerateCell }, new TableSection { - folderCell, + FolderCell, favoriteCell }, new TableSection(AppResources.Notes) { - notesCell + NotesCell } } }; @@ -137,7 +141,7 @@ namespace Bit.App.Pages return; } - if(string.IsNullOrWhiteSpace(nameCell.Entry.Text)) + if(string.IsNullOrWhiteSpace(NameCell.Entry.Text)) { await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.Name), AppResources.Ok); @@ -146,17 +150,17 @@ namespace Bit.App.Pages var login = new Login { - Uri = uriCell.Entry.Text?.Encrypt(), - Name = nameCell.Entry.Text?.Encrypt(), - Username = usernameCell.Entry.Text?.Encrypt(), + Uri = UriCell.Entry.Text?.Encrypt(), + Name = NameCell.Entry.Text?.Encrypt(), + Username = UsernameCell.Entry.Text?.Encrypt(), Password = PasswordCell.Entry.Text?.Encrypt(), - Notes = notesCell.Editor.Text?.Encrypt(), + Notes = NotesCell.Editor.Text?.Encrypt(), Favorite = favoriteCell.On }; - if(folderCell.Picker.SelectedIndex > 0) + if(FolderCell.Picker.SelectedIndex > 0) { - login.FolderId = folders.ElementAt(folderCell.Picker.SelectedIndex - 1).Id; + login.FolderId = folders.ElementAt(FolderCell.Picker.SelectedIndex - 1).Id; } _userDialogs.ShowLoading(AppResources.Saving, MaskType.Black); @@ -203,6 +207,15 @@ namespace Bit.App.Pages AlertNoConnection(); } + PasswordCell.InitEvents(); + UsernameCell.InitEvents(); + UriCell.InitEvents(); + NameCell.InitEvents(); + NotesCell.InitEvents(); + FolderCell.InitEvents(); + PasswordCell.Button.Clicked += PasswordButton_Clicked; + GenerateCell.Tapped += GenerateCell_Tapped; + if(!_fromAutofill && !_settings.GetValueOrDefault(AddedLoginAlertKey, false)) { _settings.AddOrUpdateValue(AddedLoginAlertKey, true); @@ -219,6 +232,19 @@ namespace Bit.App.Pages } } + protected override void OnDisappearing() + { + base.OnDisappearing(); + PasswordCell.Dispose(); + UsernameCell.Dispose(); + UriCell.Dispose(); + NameCell.Dispose(); + NotesCell.Dispose(); + FolderCell.Dispose(); + PasswordCell.Button.Clicked -= PasswordButton_Clicked; + GenerateCell.Tapped -= GenerateCell_Tapped; + } + private void PasswordButton_Clicked(object sender, EventArgs e) { PasswordCell.Entry.InvokeToggleIsPassword(); diff --git a/src/App/Pages/Vault/VaultEditLoginPage.cs b/src/App/Pages/Vault/VaultEditLoginPage.cs index a3c0f862d..42b97432a 100644 --- a/src/App/Pages/Vault/VaultEditLoginPage.cs +++ b/src/App/Pages/Vault/VaultEditLoginPage.cs @@ -33,6 +33,13 @@ namespace Bit.App.Pages } public FormEntryCell PasswordCell { get; private set; } + public FormEntryCell UsernameCell { get; private set; } + public FormEntryCell UriCell { get; private set; } + public FormEntryCell NameCell { get; private set; } + public FormEditorCell NotesCell { get; private set; } + public FormPickerCell FolderCell { get; private set; } + public ExtendedTextCell GenerateCell { get; private set; } + public ExtendedTextCell DeleteCell { get; private set; } private void Init() { @@ -43,34 +50,32 @@ namespace Bit.App.Pages return; } - var notesCell = new FormEditorCell(height: 90); - notesCell.Editor.Text = login.Notes?.Decrypt(); + NotesCell = new FormEditorCell(height: 90); + NotesCell.Editor.Text = login.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 = login.Password?.Decrypt(); PasswordCell.Button.Image = "eye"; - PasswordCell.Button.Clicked += PasswordButton_Clicked; PasswordCell.Entry.DisableAutocapitalize = true; PasswordCell.Entry.Autocorrect = false; PasswordCell.Entry.FontFamily = Device.OnPlatform(iOS: "Courier", Android: "monospace", WinPhone: "Courier"); - var usernameCell = new FormEntryCell(AppResources.Username, nextElement: PasswordCell.Entry); - usernameCell.Entry.Text = login.Username?.Decrypt(); - usernameCell.Entry.DisableAutocapitalize = true; - usernameCell.Entry.Autocorrect = false; + UsernameCell = new FormEntryCell(AppResources.Username, nextElement: PasswordCell.Entry); + UsernameCell.Entry.Text = login.Username?.Decrypt(); + UsernameCell.Entry.DisableAutocapitalize = true; + UsernameCell.Entry.Autocorrect = false; - var uriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: usernameCell.Entry); - uriCell.Entry.Text = login.Uri?.Decrypt(); - var nameCell = new FormEntryCell(AppResources.Name, nextElement: uriCell.Entry); - nameCell.Entry.Text = login.Name?.Decrypt(); + UriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: UsernameCell.Entry); + UriCell.Entry.Text = login.Uri?.Decrypt(); + NameCell = new FormEntryCell(AppResources.Name, nextElement: UriCell.Entry); + NameCell.Entry.Text = login.Name?.Decrypt(); - var generateCell = new ExtendedTextCell + GenerateCell = new ExtendedTextCell { Text = AppResources.GeneratePassword, ShowDisclousure = true }; - generateCell.Tapped += GenerateCell_Tapped; ; var folderOptions = new List { AppResources.FolderNone }; var folders = _folderService.GetAllAsync().GetAwaiter().GetResult() @@ -87,8 +92,8 @@ namespace Bit.App.Pages folderOptions.Add(folder.Name.Decrypt()); } - var folderCell = new FormPickerCell(AppResources.Folder, folderOptions.ToArray()); - folderCell.Picker.SelectedIndex = selectedIndex; + FolderCell = new FormPickerCell(AppResources.Folder, folderOptions.ToArray()); + FolderCell.Picker.SelectedIndex = selectedIndex; var favoriteCell = new ExtendedSwitchCell { @@ -96,8 +101,7 @@ namespace Bit.App.Pages On = login.Favorite }; - var deleteCell = new ExtendedTextCell { Text = AppResources.Delete, TextColor = Color.Red }; - deleteCell.Tapped += DeleteCell_Tapped; + DeleteCell = new ExtendedTextCell { Text = AppResources.Delete, TextColor = Color.Red }; var table = new ExtendedTableView { @@ -108,24 +112,24 @@ namespace Bit.App.Pages { new TableSection(AppResources.LoginInformation) { - nameCell, - uriCell, - usernameCell, + NameCell, + UriCell, + UsernameCell, PasswordCell, - generateCell + GenerateCell }, new TableSection { - folderCell, + FolderCell, favoriteCell }, new TableSection(AppResources.Notes) { - notesCell + NotesCell }, new TableSection { - deleteCell + DeleteCell } } }; @@ -148,23 +152,23 @@ namespace Bit.App.Pages return; } - if(string.IsNullOrWhiteSpace(nameCell.Entry.Text)) + if(string.IsNullOrWhiteSpace(NameCell.Entry.Text)) { await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.Name), AppResources.Ok); return; } - login.Uri = uriCell.Entry.Text?.Encrypt(); - login.Name = nameCell.Entry.Text?.Encrypt(); - login.Username = usernameCell.Entry.Text?.Encrypt(); + login.Uri = UriCell.Entry.Text?.Encrypt(); + login.Name = NameCell.Entry.Text?.Encrypt(); + login.Username = UsernameCell.Entry.Text?.Encrypt(); login.Password = PasswordCell.Entry.Text?.Encrypt(); - login.Notes = notesCell.Editor.Text?.Encrypt(); + login.Notes = NotesCell.Editor.Text?.Encrypt(); login.Favorite = favoriteCell.On; - if(folderCell.Picker.SelectedIndex > 0) + if(FolderCell.Picker.SelectedIndex > 0) { - login.FolderId = folders.ElementAt(folderCell.Picker.SelectedIndex - 1).Id; + login.FolderId = folders.ElementAt(FolderCell.Picker.SelectedIndex - 1).Id; } else { @@ -208,6 +212,30 @@ namespace Bit.App.Pages { AlertNoConnection(); } + + PasswordCell.InitEvents(); + UsernameCell.InitEvents(); + UriCell.InitEvents(); + NameCell.InitEvents(); + NotesCell.InitEvents(); + FolderCell.InitEvents(); + PasswordCell.Button.Clicked += PasswordButton_Clicked; + GenerateCell.Tapped += GenerateCell_Tapped; + DeleteCell.Tapped += DeleteCell_Tapped; + } + + protected override void OnDisappearing() + { + base.OnDisappearing(); + PasswordCell.Dispose(); + UsernameCell.Dispose(); + UriCell.Dispose(); + NameCell.Dispose(); + NotesCell.Dispose(); + FolderCell.Dispose(); + PasswordCell.Button.Clicked -= PasswordButton_Clicked; + GenerateCell.Tapped -= GenerateCell_Tapped; + DeleteCell.Tapped -= DeleteCell_Tapped; } private void PasswordButton_Clicked(object sender, EventArgs e)