mirror of
https://github.com/bitwarden/android.git
synced 2024-11-01 07:35:52 +03:00
generator UI elements
This commit is contained in:
parent
28473dd85f
commit
018a7c9f96
3 changed files with 351 additions and 42 deletions
|
@ -22,35 +22,174 @@
|
||||||
Order="Secondary" />
|
Order="Secondary" />
|
||||||
</ContentPage.ToolbarItems>
|
</ContentPage.ToolbarItems>
|
||||||
|
|
||||||
<StackLayout Spacing="20">
|
<ContentPage.Resources>
|
||||||
<StackLayout StyleClass="box">
|
<ResourceDictionary>
|
||||||
<controls:MonoLabel
|
<u:InverseBoolConverter x:Key="inverseBool" />
|
||||||
Text="{Binding Password}"
|
</ResourceDictionary>
|
||||||
Margin="0, 20"
|
</ContentPage.Resources>
|
||||||
StyleClass="text-lg"
|
|
||||||
HorizontalOptions="Center" />
|
<ScrollView>
|
||||||
<StackLayout Orientation="Horizontal">
|
<StackLayout Spacing="20">
|
||||||
<Button Text="{u:I18n RegeneratePassword}"
|
<StackLayout StyleClass="box">
|
||||||
HorizontalOptions="FillAndExpand"
|
<controls:MonoLabel
|
||||||
Clicked="Regenerate_Clicked"></Button>
|
Text="{Binding Password}"
|
||||||
<Button Text="{u:I18n CopyPassword}"
|
Margin="0, 20"
|
||||||
HorizontalOptions="FillAndExpand"
|
StyleClass="text-lg"
|
||||||
Clicked="Copy_Clicked"></Button>
|
HorizontalOptions="Center" />
|
||||||
|
<StackLayout Orientation="Horizontal">
|
||||||
|
<Button Text="{u:I18n RegeneratePassword}"
|
||||||
|
HorizontalOptions="FillAndExpand"
|
||||||
|
Clicked="Regenerate_Clicked"></Button>
|
||||||
|
<Button Text="{u:I18n CopyPassword}"
|
||||||
|
HorizontalOptions="FillAndExpand"
|
||||||
|
Clicked="Copy_Clicked"></Button>
|
||||||
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout StyleClass="box-row-header">
|
<StackLayout StyleClass="box">
|
||||||
<Label Text="{u:I18n Options}"
|
<StackLayout StyleClass="box-row-header">
|
||||||
StyleClass="box-header, box-header-platform" />
|
<Label Text="{u:I18n Options}"
|
||||||
</StackLayout>
|
StyleClass="box-header, box-header-platform" />
|
||||||
<StackLayout StyleClass="box-row, box-row-input">
|
</StackLayout>
|
||||||
<Label
|
<StackLayout StyleClass="box-row, box-row-input">
|
||||||
Text="{u:I18n Type}"
|
<Label
|
||||||
StyleClass="box-label" />
|
Text="{u:I18n Type}"
|
||||||
<Picker
|
StyleClass="box-label" />
|
||||||
ItemsSource="{Binding TypeOptions, Mode=OneTime}"
|
<Picker
|
||||||
SelectedIndex="{Binding TypeSelectedIndex}"
|
ItemsSource="{Binding TypeOptions, Mode=OneTime}"
|
||||||
StyleClass="box-value" />
|
SelectedIndex="{Binding TypeSelectedIndex}"
|
||||||
|
StyleClass="box-value" />
|
||||||
|
</StackLayout>
|
||||||
|
<StackLayout Spacing="0"
|
||||||
|
Padding="0"
|
||||||
|
IsVisible="{Binding IsPassword, Converter={StaticResource inverseBool}}">
|
||||||
|
<StackLayout StyleClass="box-row, box-row-stepper">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n NumberOfWords}"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
VerticalOptions="FillAndExpand"
|
||||||
|
VerticalTextAlignment="Center" />
|
||||||
|
<Label
|
||||||
|
Text="{Binding NumWords}"
|
||||||
|
StyleClass="box-label, box-sub-label"
|
||||||
|
HorizontalOptions="FillAndExpand"
|
||||||
|
HorizontalTextAlignment="End"
|
||||||
|
VerticalOptions="FillAndExpand"
|
||||||
|
VerticalTextAlignment="Center" />
|
||||||
|
<Stepper
|
||||||
|
Value="{Binding NumWords}"
|
||||||
|
Minimum="3"
|
||||||
|
Maximum="20"
|
||||||
|
Increment="1" />
|
||||||
|
</StackLayout>
|
||||||
|
<BoxView StyleClass="box-row-separator" />
|
||||||
|
<StackLayout StyleClass="box-row, box-row-input">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n WordSeparator}"
|
||||||
|
StyleClass="box-label" />
|
||||||
|
<Entry
|
||||||
|
Text="{Binding WordSeparator}"
|
||||||
|
StyleClass="box-value" />
|
||||||
|
</StackLayout>
|
||||||
|
</StackLayout>
|
||||||
|
<StackLayout Spacing="0" Padding="0" IsVisible="{Binding IsPassword}">
|
||||||
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
<Label
|
||||||
|
Text="A-Z"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
HorizontalOptions="StartAndExpand" />
|
||||||
|
<Switch
|
||||||
|
IsToggled="{Binding Uppercase}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
HorizontalOptions="End" />
|
||||||
|
</StackLayout>
|
||||||
|
<BoxView StyleClass="box-row-separator" />
|
||||||
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
<Label
|
||||||
|
Text="a-z"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
HorizontalOptions="StartAndExpand" />
|
||||||
|
<Switch
|
||||||
|
IsToggled="{Binding Lowercase}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
HorizontalOptions="End" />
|
||||||
|
</StackLayout>
|
||||||
|
<BoxView StyleClass="box-row-separator" />
|
||||||
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
<Label
|
||||||
|
Text="0-9"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
HorizontalOptions="StartAndExpand" />
|
||||||
|
<Switch
|
||||||
|
IsToggled="{Binding Number}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
HorizontalOptions="End" />
|
||||||
|
</StackLayout>
|
||||||
|
<BoxView StyleClass="box-row-separator" />
|
||||||
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
<Label
|
||||||
|
Text="!@#$%^&*"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
HorizontalOptions="StartAndExpand" />
|
||||||
|
<Switch
|
||||||
|
IsToggled="{Binding Special}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
HorizontalOptions="End" />
|
||||||
|
</StackLayout>
|
||||||
|
<BoxView StyleClass="box-row-separator" />
|
||||||
|
<StackLayout StyleClass="box-row, box-row-stepper">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n MinNumbers}"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
VerticalOptions="FillAndExpand"
|
||||||
|
VerticalTextAlignment="Center" />
|
||||||
|
<Label
|
||||||
|
Text="{Binding MinNumber}"
|
||||||
|
StyleClass="box-label, box-sub-label"
|
||||||
|
HorizontalOptions="FillAndExpand"
|
||||||
|
HorizontalTextAlignment="End"
|
||||||
|
VerticalOptions="FillAndExpand"
|
||||||
|
VerticalTextAlignment="Center" />
|
||||||
|
<Stepper
|
||||||
|
Value="{Binding MinNumber}"
|
||||||
|
Minimum="0"
|
||||||
|
Maximum="5"
|
||||||
|
Increment="1" />
|
||||||
|
</StackLayout>
|
||||||
|
<BoxView StyleClass="box-row-separator" />
|
||||||
|
<StackLayout StyleClass="box-row, box-row-stepper">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n MinSpecial}"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
VerticalOptions="FillAndExpand"
|
||||||
|
VerticalTextAlignment="Center" />
|
||||||
|
<Label
|
||||||
|
Text="{Binding MinSpecial}"
|
||||||
|
StyleClass="box-label, box-sub-label"
|
||||||
|
HorizontalOptions="FillAndExpand"
|
||||||
|
HorizontalTextAlignment="End"
|
||||||
|
VerticalOptions="FillAndExpand"
|
||||||
|
VerticalTextAlignment="Center" />
|
||||||
|
<Stepper
|
||||||
|
Value="{Binding MinSpecial}"
|
||||||
|
Minimum="0"
|
||||||
|
Maximum="5"
|
||||||
|
Increment="1" />
|
||||||
|
</StackLayout>
|
||||||
|
<BoxView StyleClass="box-row-separator" />
|
||||||
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n AvoidAmbiguousCharacters}"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
HorizontalOptions="StartAndExpand" />
|
||||||
|
<Switch
|
||||||
|
IsToggled="{Binding AvoidAmbiguous}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
HorizontalOptions="End" />
|
||||||
|
</StackLayout>
|
||||||
|
<BoxView StyleClass="box-row-separator" />
|
||||||
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</ScrollView>
|
||||||
|
|
||||||
</pages:BaseContentPage>
|
</pages:BaseContentPage>
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Models.Domain;
|
using Bit.Core.Models.Domain;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
|
@ -17,7 +15,18 @@ namespace Bit.App.Pages
|
||||||
private PasswordGenerationOptions _options;
|
private PasswordGenerationOptions _options;
|
||||||
private string _password;
|
private string _password;
|
||||||
private bool _isPassword;
|
private bool _isPassword;
|
||||||
|
private bool _uppercase;
|
||||||
|
private bool _lowercase;
|
||||||
|
private bool _number;
|
||||||
|
private bool _special;
|
||||||
|
private bool _avoidAmbiguous;
|
||||||
|
private int _minNumber;
|
||||||
|
private int _minSpecial;
|
||||||
|
private int _length;
|
||||||
|
private int _numWords;
|
||||||
|
private string _wordSeparator;
|
||||||
private int _typeSelectedIndex;
|
private int _typeSelectedIndex;
|
||||||
|
private bool _doneIniting;
|
||||||
|
|
||||||
public GeneratorPageViewModel()
|
public GeneratorPageViewModel()
|
||||||
{
|
{
|
||||||
|
@ -42,10 +51,134 @@ namespace Bit.App.Pages
|
||||||
set => SetProperty(ref _isPassword, value);
|
set => SetProperty(ref _isPassword, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PasswordGenerationOptions Options
|
public int Length
|
||||||
{
|
{
|
||||||
get => _options;
|
get => _length;
|
||||||
set => SetProperty(ref _options, value);
|
set
|
||||||
|
{
|
||||||
|
if(SetProperty(ref _length, value))
|
||||||
|
{
|
||||||
|
_options.Length = value;
|
||||||
|
var task = SaveOptionsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Uppercase
|
||||||
|
{
|
||||||
|
get => _uppercase;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(SetProperty(ref _uppercase, value))
|
||||||
|
{
|
||||||
|
_options.Uppercase = value;
|
||||||
|
var task = SaveOptionsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Lowercase
|
||||||
|
{
|
||||||
|
get => _lowercase;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(SetProperty(ref _lowercase, value))
|
||||||
|
{
|
||||||
|
_options.Lowercase = value;
|
||||||
|
var task = SaveOptionsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Number
|
||||||
|
{
|
||||||
|
get => _number;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(SetProperty(ref _number, value))
|
||||||
|
{
|
||||||
|
_options.Number = value;
|
||||||
|
var task = SaveOptionsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Special
|
||||||
|
{
|
||||||
|
get => _special;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(SetProperty(ref _special, value))
|
||||||
|
{
|
||||||
|
_options.Special = value;
|
||||||
|
var task = SaveOptionsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AvoidAmbiguous
|
||||||
|
{
|
||||||
|
get => _avoidAmbiguous;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(SetProperty(ref _avoidAmbiguous, value))
|
||||||
|
{
|
||||||
|
_options.Ambiguous = !value;
|
||||||
|
var task = SaveOptionsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MinNumber
|
||||||
|
{
|
||||||
|
get => _minNumber;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(SetProperty(ref _minNumber, value))
|
||||||
|
{
|
||||||
|
_options.MinNumber = value;
|
||||||
|
var task = SaveOptionsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MinSpecial
|
||||||
|
{
|
||||||
|
get => _minSpecial;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(SetProperty(ref _minSpecial, value))
|
||||||
|
{
|
||||||
|
_options.MinSpecial = value;
|
||||||
|
var task = SaveOptionsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int NumWords
|
||||||
|
{
|
||||||
|
get => _numWords;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(SetProperty(ref _numWords, value))
|
||||||
|
{
|
||||||
|
_options.NumWords = value;
|
||||||
|
var task = SaveOptionsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string WordSeparator
|
||||||
|
{
|
||||||
|
get => _wordSeparator;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(SetProperty(ref _wordSeparator, value))
|
||||||
|
{
|
||||||
|
_options.WordSeparator = value;
|
||||||
|
var task = SaveOptionsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int TypeSelectedIndex
|
public int TypeSelectedIndex
|
||||||
|
@ -55,29 +188,37 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
if(SetProperty(ref _typeSelectedIndex, value))
|
if(SetProperty(ref _typeSelectedIndex, value))
|
||||||
{
|
{
|
||||||
TypeChanged();
|
IsPassword = value == 0;
|
||||||
|
var task = SaveOptionsAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InitAsync()
|
public async Task InitAsync()
|
||||||
{
|
{
|
||||||
Options = await _passwordGenerationService.GetOptionsAsync();
|
_options = await _passwordGenerationService.GetOptionsAsync();
|
||||||
TypeSelectedIndex = Options.Type == "passphrase" ? 1 : 0;
|
LoadFromOptions();
|
||||||
Password = await _passwordGenerationService.GeneratePasswordAsync(Options);
|
Password = await _passwordGenerationService.GeneratePasswordAsync(_options);
|
||||||
await _passwordGenerationService.AddHistoryAsync(Password);
|
await _passwordGenerationService.AddHistoryAsync(Password);
|
||||||
|
_doneIniting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RegenerateAsync()
|
public async Task RegenerateAsync()
|
||||||
{
|
{
|
||||||
Password = await _passwordGenerationService.GeneratePasswordAsync(Options);
|
Password = await _passwordGenerationService.GeneratePasswordAsync(_options);
|
||||||
await _passwordGenerationService.AddHistoryAsync(Password);
|
await _passwordGenerationService.AddHistoryAsync(Password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SaveOptionsAsync(bool regenerate = true)
|
public async Task SaveOptionsAsync(bool regenerate = true)
|
||||||
{
|
{
|
||||||
_passwordGenerationService.NormalizeOptions(Options);
|
if(!_doneIniting)
|
||||||
await _passwordGenerationService.SaveOptionsAsync(Options);
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SetOptions();
|
||||||
|
_passwordGenerationService.NormalizeOptions(_options);
|
||||||
|
await _passwordGenerationService.SaveOptionsAsync(_options);
|
||||||
|
LoadFromOptions();
|
||||||
if(regenerate)
|
if(regenerate)
|
||||||
{
|
{
|
||||||
await RegenerateAsync();
|
await RegenerateAsync();
|
||||||
|
@ -90,11 +231,33 @@ namespace Bit.App.Pages
|
||||||
_platformUtilsService.ShowToast("success", null, AppResources.CopiedPassword);
|
_platformUtilsService.ShowToast("success", null, AppResources.CopiedPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void TypeChanged()
|
private void LoadFromOptions()
|
||||||
{
|
{
|
||||||
|
AvoidAmbiguous = !_options.Ambiguous.GetValueOrDefault();
|
||||||
|
TypeSelectedIndex = _options.Type == "passphrase" ? 1 : 0;
|
||||||
IsPassword = TypeSelectedIndex == 0;
|
IsPassword = TypeSelectedIndex == 0;
|
||||||
Options.Type = IsPassword ? "password" : "passphrase";
|
MinNumber = _options.MinNumber.GetValueOrDefault();
|
||||||
await SaveOptionsAsync();
|
MinSpecial = _options.MinSpecial.GetValueOrDefault();
|
||||||
|
Special = _options.Special.GetValueOrDefault();
|
||||||
|
Number = _options.Number.GetValueOrDefault();
|
||||||
|
NumWords = _options.NumWords.GetValueOrDefault();
|
||||||
|
WordSeparator = _options.WordSeparator;
|
||||||
|
Uppercase = _options.Uppercase.GetValueOrDefault();
|
||||||
|
Lowercase = _options.Lowercase.GetValueOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetOptions()
|
||||||
|
{
|
||||||
|
_options.Ambiguous = !AvoidAmbiguous;
|
||||||
|
_options.Type = TypeSelectedIndex == 1 ? "passphrase" : "password";
|
||||||
|
_options.MinNumber = MinNumber;
|
||||||
|
_options.MinSpecial = MinSpecial;
|
||||||
|
_options.Special = Special;
|
||||||
|
_options.NumWords = NumWords;
|
||||||
|
_options.Number = Number;
|
||||||
|
_options.WordSeparator = WordSeparator;
|
||||||
|
_options.Uppercase = Uppercase;
|
||||||
|
_options.Lowercase = Lowercase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,6 +257,13 @@
|
||||||
<Setter Property="Orientation"
|
<Setter Property="Orientation"
|
||||||
Value="Horizontal" />
|
Value="Horizontal" />
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style TargetType="StackLayout"
|
||||||
|
Class="box-row-stepper">
|
||||||
|
<Setter Property="Orientation"
|
||||||
|
Value="Horizontal" />
|
||||||
|
<Setter Property="Spacing"
|
||||||
|
Value="10" />
|
||||||
|
</Style>
|
||||||
<Style TargetType="Button"
|
<Style TargetType="Button"
|
||||||
ApplyToDerivedTypes="True"
|
ApplyToDerivedTypes="True"
|
||||||
Class="box-row-button">
|
Class="box-row-button">
|
||||||
|
|
Loading…
Reference in a new issue