diff --git a/src/App/Controls/StepperCell.cs b/src/App/Controls/StepperCell.cs index d8e7182b3..f4007df8c 100644 --- a/src/App/Controls/StepperCell.cs +++ b/src/App/Controls/StepperCell.cs @@ -1,12 +1,17 @@ using Bit.App.Utilities; +using System; using Xamarin.Forms; namespace Bit.App.Controls { public class StepperCell : ExtendedViewCell { - public StepperCell(string labelText, double value, double min, double max, double increment) + private Action _changedAction; + + public StepperCell(string labelText, double value, double min, double max, double increment, Action changed = null) { + _changedAction = changed; + Label = new Label { Text = labelText, @@ -62,6 +67,7 @@ namespace Bit.App.Controls private void Stepper_ValueChanged(object sender, ValueChangedEventArgs e) { StepperValueLabel.Text = e.NewValue.ToString(); + _changedAction?.Invoke(); } public void InitEvents() diff --git a/src/App/Pages/Tools/ToolsPasswordGeneratorPage.cs b/src/App/Pages/Tools/ToolsPasswordGeneratorPage.cs index bb384481a..a7c66373a 100644 --- a/src/App/Pages/Tools/ToolsPasswordGeneratorPage.cs +++ b/src/App/Pages/Tools/ToolsPasswordGeneratorPage.cs @@ -38,9 +38,15 @@ namespace Bit.App.Pages public Label Password { get; private set; } public SliderViewCell SliderCell { get; private set; } public TapGestureRecognizer Tgr { get; set; } - public ExtendedTextCell SettingsCell { get; set; } public ExtendedTextCell RegenerateCell { get; set; } public ExtendedTextCell CopyCell { get; set; } + public ExtendedSwitchCell UppercaseCell { get; set; } + public ExtendedSwitchCell LowercaseCell { get; set; } + public ExtendedSwitchCell SpecialCell { get; set; } + public ExtendedSwitchCell NumbersCell { get; set; } + public ExtendedSwitchCell AvoidAmbiguousCell { get; set; } + public StepperCell SpecialMinCell { get; set; } + public StepperCell NumbersMinCell { get; set; } public void Init() { @@ -59,12 +65,57 @@ namespace Bit.App.Pages Password.SetBinding(Label.TextProperty, nameof(PasswordGeneratorPageModel.Password)); SliderCell = new SliderViewCell(this, _passwordGenerationService, _settings); - SettingsCell = new ExtendedTextCell { Text = AppResources.MoreSettings, ShowDisclousure = true }; var buttonColor = Color.FromHex("3c8dbc"); RegenerateCell = new ExtendedTextCell { Text = AppResources.RegeneratePassword, TextColor = buttonColor }; CopyCell = new ExtendedTextCell { Text = AppResources.CopyPassword, TextColor = buttonColor }; + UppercaseCell = new ExtendedSwitchCell + { + Text = "A-Z", + On = _settings.GetValueOrDefault(Constants.PasswordGeneratorUppercase, true) + }; + + LowercaseCell = new ExtendedSwitchCell + { + Text = "a-z", + On = _settings.GetValueOrDefault(Constants.PasswordGeneratorLowercase, true) + }; + + SpecialCell = new ExtendedSwitchCell + { + Text = "!@#$%^&*", + On = _settings.GetValueOrDefault(Constants.PasswordGeneratorSpecial, true) + }; + + NumbersCell = new ExtendedSwitchCell + { + Text = "0-9", + On = _settings.GetValueOrDefault(Constants.PasswordGeneratorNumbers, true) + }; + + AvoidAmbiguousCell = new ExtendedSwitchCell + { + Text = AppResources.AvoidAmbiguousCharacters, + On = !_settings.GetValueOrDefault(Constants.PasswordGeneratorAmbiguous, false) + }; + + NumbersMinCell = new StepperCell(AppResources.MinNumbers, + _settings.GetValueOrDefault(Constants.PasswordGeneratorMinNumbers, 1), 0, 5, 1, () => + { + _settings.AddOrUpdateValue(Constants.PasswordGeneratorMinNumbers, + Convert.ToInt32(NumbersMinCell.Stepper.Value)); + Model.Password = _passwordGenerationService.GeneratePassword(); + }); + + SpecialMinCell = new StepperCell(AppResources.MinSpecial, + _settings.GetValueOrDefault(Constants.PasswordGeneratorMinSpecial, 1), 0, 5, 1, () => + { + _settings.AddOrUpdateValue(Constants.PasswordGeneratorMinSpecial, + Convert.ToInt32(SpecialMinCell.Stepper.Value)); + Model.Password = _passwordGenerationService.GeneratePassword(); + }); + var table = new ExtendedTableView { VerticalOptions = LayoutOptions.Start, @@ -82,7 +133,19 @@ namespace Bit.App.Pages new TableSection(AppResources.Options) { SliderCell, - SettingsCell + UppercaseCell, + LowercaseCell, + NumbersCell, + SpecialCell + }, + new TableSection(Helpers.GetEmptyTableSectionTitle()) + { + NumbersMinCell, + SpecialMinCell + }, + new TableSection(Helpers.GetEmptyTableSectionTitle()) + { + AvoidAmbiguousCell } } }; @@ -145,9 +208,15 @@ namespace Bit.App.Pages base.OnAppearing(); Tgr.Tapped += Tgr_Tapped; RegenerateCell.Tapped += RegenerateCell_Tapped; - SettingsCell.Tapped += SettingsCell_Tapped; CopyCell.Tapped += CopyCell_Tapped; SliderCell.InitEvents(); + SpecialCell.OnChanged += SpecialCell_OnChanged; + AvoidAmbiguousCell.OnChanged += AvoidAmbiguousCell_OnChanged; + UppercaseCell.OnChanged += UppercaseCell_OnChanged; + LowercaseCell.OnChanged += LowercaseCell_OnChanged; + NumbersCell.OnChanged += NumbersCell_OnChanged; + NumbersMinCell.InitEvents(); + SpecialMinCell.InitEvents(); if(_fromAutofill) { @@ -166,7 +235,13 @@ namespace Bit.App.Pages base.OnDisappearing(); Tgr.Tapped -= Tgr_Tapped; RegenerateCell.Tapped -= RegenerateCell_Tapped; - SettingsCell.Tapped -= SettingsCell_Tapped; + SpecialCell.OnChanged -= SpecialCell_OnChanged; + AvoidAmbiguousCell.OnChanged -= AvoidAmbiguousCell_OnChanged; + UppercaseCell.OnChanged -= UppercaseCell_OnChanged; + LowercaseCell.OnChanged -= LowercaseCell_OnChanged; + NumbersCell.OnChanged -= NumbersCell_OnChanged; + NumbersMinCell.Dispose(); + SpecialMinCell.Dispose(); CopyCell.Tapped -= CopyCell_Tapped; SliderCell.Dispose(); } @@ -189,11 +264,6 @@ namespace Bit.App.Pages CopyPassword(); } - private void SettingsCell_Tapped(object sender, EventArgs e) - { - Navigation.PushAsync(new ToolsPasswordGeneratorSettingsPage()); - } - private void CopyPassword() { if(_fromAutofill) @@ -208,6 +278,70 @@ namespace Bit.App.Pages _userDialogs.Toast(string.Format(AppResources.ValueHasBeenCopied, AppResources.Password)); } + private void AvoidAmbiguousCell_OnChanged(object sender, ToggledEventArgs e) + { + _settings.AddOrUpdateValue(Constants.PasswordGeneratorAmbiguous, !AvoidAmbiguousCell.On); + Model.Password = _passwordGenerationService.GeneratePassword(); + } + + private void NumbersCell_OnChanged(object sender, ToggledEventArgs e) + { + _settings.AddOrUpdateValue(Constants.PasswordGeneratorNumbers, NumbersCell.On); + + if(InvalidState()) + { + _settings.AddOrUpdateValue(Constants.PasswordGeneratorLowercase, true); + LowercaseCell.On = true; + } + + Model.Password = _passwordGenerationService.GeneratePassword(); + } + + private void SpecialCell_OnChanged(object sender, ToggledEventArgs e) + { + _settings.AddOrUpdateValue(Constants.PasswordGeneratorSpecial, SpecialCell.On); + + if(InvalidState()) + { + _settings.AddOrUpdateValue(Constants.PasswordGeneratorLowercase, true); + LowercaseCell.On = true; + } + + Model.Password = _passwordGenerationService.GeneratePassword(); + } + + private void LowercaseCell_OnChanged(object sender, ToggledEventArgs e) + { + _settings.AddOrUpdateValue(Constants.PasswordGeneratorLowercase, LowercaseCell.On); + + if(InvalidState()) + { + _settings.AddOrUpdateValue(Constants.PasswordGeneratorUppercase, true); + UppercaseCell.On = true; + } + + Model.Password = _passwordGenerationService.GeneratePassword(); + } + + private void UppercaseCell_OnChanged(object sender, ToggledEventArgs e) + { + _settings.AddOrUpdateValue(Constants.PasswordGeneratorUppercase, UppercaseCell.On); + + if(InvalidState()) + { + _settings.AddOrUpdateValue(Constants.PasswordGeneratorLowercase, true); + LowercaseCell.On = true; + } + + Model.Password = _passwordGenerationService.GeneratePassword(); + } + + private bool InvalidState() + { + return !LowercaseCell.On && !UppercaseCell.On && !NumbersCell.On && !SpecialCell.On; + } + + // TODO: move to standalone reusable control public class SliderViewCell : ExtendedViewCell, IDisposable { diff --git a/src/App/Pages/Tools/ToolsPasswordGeneratorSettingsPage.cs b/src/App/Pages/Tools/ToolsPasswordGeneratorSettingsPage.cs deleted file mode 100644 index 704631749..000000000 --- a/src/App/Pages/Tools/ToolsPasswordGeneratorSettingsPage.cs +++ /dev/null @@ -1,194 +0,0 @@ -using System; -using System.Threading.Tasks; -using Acr.UserDialogs; -using Bit.App.Abstractions; -using Bit.App.Controls; -using Bit.App.Resources; -using Plugin.Connectivity.Abstractions; -using Plugin.Settings.Abstractions; -using Xamarin.Forms; -using XLabs.Ioc; -using Bit.App.Utilities; - -namespace Bit.App.Pages -{ - public class ToolsPasswordGeneratorSettingsPage : ExtendedContentPage - { - private readonly IUserDialogs _userDialogs; - private readonly ISettings _settings; - - public ToolsPasswordGeneratorSettingsPage() - { - _userDialogs = Resolver.Resolve(); - _settings = Resolver.Resolve(); - - Init(); - } - - public ExtendedSwitchCell UppercaseCell { get; set; } - public ExtendedSwitchCell LowercaseCell { get; set; } - public ExtendedSwitchCell SpecialCell { get; set; } - public ExtendedSwitchCell NumbersCell { get; set; } - public ExtendedSwitchCell AvoidAmbiguousCell { get; set; } - public StepperCell SpecialMinCell { get; set; } - public StepperCell NumbersMinCell { get; set; } - - public void Init() - { - UppercaseCell = new ExtendedSwitchCell - { - Text = "A-Z", - On = _settings.GetValueOrDefault(Constants.PasswordGeneratorUppercase, true) - }; - - LowercaseCell = new ExtendedSwitchCell - { - Text = "a-z", - On = _settings.GetValueOrDefault(Constants.PasswordGeneratorLowercase, true) - }; - - SpecialCell = new ExtendedSwitchCell - { - Text = "!@#$%^&*", - On = _settings.GetValueOrDefault(Constants.PasswordGeneratorSpecial, true) - }; - - NumbersCell = new ExtendedSwitchCell - { - Text = "0-9", - On = _settings.GetValueOrDefault(Constants.PasswordGeneratorNumbers, true) - }; - - AvoidAmbiguousCell = new ExtendedSwitchCell - { - Text = AppResources.AvoidAmbiguousCharacters, - On = !_settings.GetValueOrDefault(Constants.PasswordGeneratorAmbiguous, false) - }; - - NumbersMinCell = new StepperCell(AppResources.MinNumbers, - _settings.GetValueOrDefault(Constants.PasswordGeneratorMinNumbers, 1), 0, 5, 1); - SpecialMinCell = new StepperCell(AppResources.MinSpecial, - _settings.GetValueOrDefault(Constants.PasswordGeneratorMinSpecial, 1), 0, 5, 1); - - var table = new ExtendedTableView - { - EnableScrolling = true, - Intent = TableIntent.Settings, - HasUnevenRows = true, - EnableSelection = false, - Root = new TableRoot - { - new TableSection(Helpers.GetEmptyTableSectionTitle()) - { - UppercaseCell, - LowercaseCell, - NumbersCell, - SpecialCell - }, - new TableSection(Helpers.GetEmptyTableSectionTitle()) - { - NumbersMinCell, - SpecialMinCell - }, - new TableSection(Helpers.GetEmptyTableSectionTitle()) - { - AvoidAmbiguousCell - } - } - }; - - if(Device.RuntimePlatform == Device.iOS) - { - table.RowHeight = -1; - table.EstimatedRowHeight = 44; - } - - Title = AppResources.Settings; - Content = table; - } - - protected override void OnAppearing() - { - base.OnAppearing(); - SpecialCell.OnChanged += SpecialCell_OnChanged; - AvoidAmbiguousCell.OnChanged += AvoidAmbiguousCell_OnChanged; - UppercaseCell.OnChanged += UppercaseCell_OnChanged; - LowercaseCell.OnChanged += LowercaseCell_OnChanged; - NumbersCell.OnChanged += NumbersCell_OnChanged; - NumbersMinCell.InitEvents(); - SpecialMinCell.InitEvents(); - } - - protected override void OnDisappearing() - { - base.OnDisappearing(); - SpecialCell.OnChanged -= SpecialCell_OnChanged; - AvoidAmbiguousCell.OnChanged -= AvoidAmbiguousCell_OnChanged; - UppercaseCell.OnChanged -= UppercaseCell_OnChanged; - LowercaseCell.OnChanged -= LowercaseCell_OnChanged; - NumbersCell.OnChanged -= NumbersCell_OnChanged; - NumbersMinCell.Dispose(); - SpecialMinCell.Dispose(); - - _settings.AddOrUpdateValue(Constants.PasswordGeneratorMinNumbers, - Convert.ToInt32(NumbersMinCell.Stepper.Value)); - - _settings.AddOrUpdateValue(Constants.PasswordGeneratorMinSpecial, - Convert.ToInt32(SpecialMinCell.Stepper.Value)); - } - - private void AvoidAmbiguousCell_OnChanged(object sender, ToggledEventArgs e) - { - _settings.AddOrUpdateValue(Constants.PasswordGeneratorAmbiguous, !AvoidAmbiguousCell.On); - } - - private void NumbersCell_OnChanged(object sender, ToggledEventArgs e) - { - _settings.AddOrUpdateValue(Constants.PasswordGeneratorNumbers, NumbersCell.On); - - if(InvalidState()) - { - _settings.AddOrUpdateValue(Constants.PasswordGeneratorLowercase, true); - LowercaseCell.On = true; - } - } - - private void SpecialCell_OnChanged(object sender, ToggledEventArgs e) - { - _settings.AddOrUpdateValue(Constants.PasswordGeneratorSpecial, SpecialCell.On); - - if(InvalidState()) - { - _settings.AddOrUpdateValue(Constants.PasswordGeneratorLowercase, true); - LowercaseCell.On = true; - } - } - - private void LowercaseCell_OnChanged(object sender, ToggledEventArgs e) - { - _settings.AddOrUpdateValue(Constants.PasswordGeneratorLowercase, LowercaseCell.On); - - if(InvalidState()) - { - _settings.AddOrUpdateValue(Constants.PasswordGeneratorUppercase, true); - UppercaseCell.On = true; - } - } - - private void UppercaseCell_OnChanged(object sender, ToggledEventArgs e) - { - _settings.AddOrUpdateValue(Constants.PasswordGeneratorUppercase, UppercaseCell.On); - - if(InvalidState()) - { - _settings.AddOrUpdateValue(Constants.PasswordGeneratorLowercase, true); - LowercaseCell.On = true; - } - } - - private bool InvalidState() - { - return !LowercaseCell.On && !UppercaseCell.On && !NumbersCell.On && !SpecialCell.On; - } - } -}