mirror of
https://github.com/wismna/ModernKeePass.git
synced 2025-10-03 15:40:18 -04:00
Password generation button with display toggle and indicator is now a user control
SetCredentials user controls now uses PasswordGenerationBox user control Some layout improvements in EntryDetailsPage WIP Clipboard suspend issues
This commit is contained in:
@@ -42,6 +42,7 @@ namespace ModernKeePass.Actions
|
||||
var dataPackage = new DataPackage { RequestedOperation = DataPackageOperation.Copy };
|
||||
dataPackage.SetText(IsProtected ? cryptography.UnProtect(Text).GetAwaiter().GetResult() : Text);
|
||||
Clipboard.SetContent(dataPackage);
|
||||
Clipboard.Flush();
|
||||
_dispatcher.Start();
|
||||
|
||||
return null;
|
||||
@@ -49,8 +50,14 @@ namespace ModernKeePass.Actions
|
||||
|
||||
private void Dispatcher_Tick(object sender, object e)
|
||||
{
|
||||
Clipboard.SetContent(null);
|
||||
_dispatcher.Stop();
|
||||
try
|
||||
{
|
||||
Clipboard.SetContent(null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_dispatcher.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,14 +8,14 @@ namespace ModernKeePass.Controls
|
||||
{
|
||||
public event EventHandler<RoutedEventArgs> ButtonClick;
|
||||
|
||||
public string ButtonSymbol
|
||||
public string ButtonContent
|
||||
{
|
||||
get { return (string)GetValue(ButtonSymbolProperty); }
|
||||
set { SetValue(ButtonSymbolProperty, value); }
|
||||
get { return (string)GetValue(ButtonContentProperty); }
|
||||
set { SetValue(ButtonContentProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty ButtonSymbolProperty =
|
||||
public static readonly DependencyProperty ButtonContentProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(ButtonSymbol),
|
||||
nameof(ButtonContent),
|
||||
typeof(string),
|
||||
typeof(PasswordBoxWithButton),
|
||||
new PropertyMetadata("", (o, args) => { }));
|
||||
|
87
WinAppCommon/Controls/PasswordGenerationBox.cs
Normal file
87
WinAppCommon/Controls/PasswordGenerationBox.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace ModernKeePass.Controls
|
||||
{
|
||||
public class PasswordGenerationBox : SearchBox
|
||||
{
|
||||
public event EventHandler<RoutedEventArgs> ButtonClick;
|
||||
|
||||
public string ButtonSymbol
|
||||
{
|
||||
get { return (string)GetValue(ButtonSymbolProperty); }
|
||||
set { SetValue(ButtonSymbolProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty ButtonSymbolProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(ButtonSymbol),
|
||||
typeof(string),
|
||||
typeof(PasswordGenerationBox),
|
||||
new PropertyMetadata("", (o, args) => { }));
|
||||
|
||||
public string ButtonTooltip
|
||||
{
|
||||
get { return (string)GetValue(ButtonTooltipProperty); }
|
||||
set { SetValue(ButtonTooltipProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty ButtonTooltipProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(ButtonTooltip),
|
||||
typeof(string),
|
||||
typeof(PasswordGenerationBox),
|
||||
new PropertyMetadata(string.Empty, (o, args) => { }));
|
||||
|
||||
public string Password
|
||||
{
|
||||
get { return (string)GetValue(PasswordProperty); }
|
||||
set { SetValue(PasswordProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty PasswordProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(Password),
|
||||
typeof(string),
|
||||
typeof(PasswordGenerationBox),
|
||||
new PropertyMetadata(string.Empty, (o, args) => { }));
|
||||
|
||||
public bool IsButtonEnabled
|
||||
{
|
||||
get { return (bool)GetValue(IsButtonEnabledProperty); }
|
||||
set { SetValue(IsButtonEnabledProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty IsButtonEnabledProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(IsButtonEnabled),
|
||||
typeof(bool),
|
||||
typeof(PasswordGenerationBox),
|
||||
new PropertyMetadata(true, (o, args) => { }));
|
||||
|
||||
public bool IsPasswordRevealEnabled
|
||||
{
|
||||
get { return (bool)GetValue(IsPasswordRevealEnabledProperty); }
|
||||
set { SetValue(IsPasswordRevealEnabledProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty IsPasswordRevealEnabledProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(IsPasswordRevealEnabled),
|
||||
typeof(bool),
|
||||
typeof(PasswordGenerationBox),
|
||||
new PropertyMetadata(true, (o, args) => { }));
|
||||
|
||||
|
||||
public PasswordGenerationBox()
|
||||
{
|
||||
DefaultStyleKey = typeof(PasswordGenerationBox);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
var actionButton = GetTemplateChild("ActionButton") as Button;
|
||||
if (actionButton != null)
|
||||
{
|
||||
actionButton.Click += (sender, e) => ButtonClick?.Invoke(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,14 +9,14 @@ namespace ModernKeePass.Controls
|
||||
{
|
||||
public event EventHandler<RoutedEventArgs> ButtonClick;
|
||||
|
||||
public string ButtonSymbol
|
||||
public string ButtonContent
|
||||
{
|
||||
get { return (string)GetValue(ButtonSymbolProperty); }
|
||||
set { SetValue(ButtonSymbolProperty, value); }
|
||||
get { return (string)GetValue(ButtonContentProperty); }
|
||||
set { SetValue(ButtonContentProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty ButtonSymbolProperty =
|
||||
public static readonly DependencyProperty ButtonContentProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(ButtonSymbol),
|
||||
nameof(ButtonContent),
|
||||
typeof(string),
|
||||
typeof(TextBoxWithButton),
|
||||
new PropertyMetadata("", (o, args) => { }));
|
||||
|
7
WinAppCommon/Messages/PasswordGeneratedMessage.cs
Normal file
7
WinAppCommon/Messages/PasswordGeneratedMessage.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Messages
|
||||
{
|
||||
public class PasswordGeneratedMessage
|
||||
{
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,113 @@
|
||||
using System.Threading.Tasks;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using MediatR;
|
||||
using Messages;
|
||||
using ModernKeePass.Application.Common.Interfaces;
|
||||
using ModernKeePass.Application.Security.Commands.GeneratePassword;
|
||||
using ModernKeePass.Common;
|
||||
|
||||
namespace ModernKeePass.ViewModels
|
||||
{
|
||||
public class PasswordGenerationBoxControlVm: ViewModelBase
|
||||
{
|
||||
private readonly IMediator _mediator;
|
||||
private readonly ISettingsProxy _settings;
|
||||
private readonly ICredentialsProxy _credentials;
|
||||
private string _password;
|
||||
private bool _isRevealPassword;
|
||||
|
||||
public double PasswordComplexityIndicator => _credentials.EstimatePasswordComplexity(Password);
|
||||
public double PasswordLength
|
||||
{
|
||||
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.PasswordLength, 25); }
|
||||
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.PasswordLength, value); }
|
||||
}
|
||||
public bool UpperCasePatternSelected
|
||||
{
|
||||
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.UpperCasePattern, true); }
|
||||
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.UpperCasePattern, value); }
|
||||
}
|
||||
public bool LowerCasePatternSelected
|
||||
{
|
||||
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.LowerCasePattern, true); }
|
||||
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.LowerCasePattern, value); }
|
||||
}
|
||||
public bool DigitsPatternSelected
|
||||
{
|
||||
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.DigitsPattern, true); }
|
||||
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.DigitsPattern, value); }
|
||||
}
|
||||
public bool MinusPatternSelected
|
||||
{
|
||||
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.MinusPattern, false); }
|
||||
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.MinusPattern, value); }
|
||||
}
|
||||
public bool UnderscorePatternSelected
|
||||
{
|
||||
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.UnderscorePattern, false); }
|
||||
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.UnderscorePattern, value); }
|
||||
}
|
||||
public bool SpacePatternSelected
|
||||
{
|
||||
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.SpacePattern, false); }
|
||||
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.SpacePattern, value); }
|
||||
}
|
||||
public bool SpecialPatternSelected
|
||||
{
|
||||
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.SpecialPattern, true); }
|
||||
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.SpecialPattern, value); }
|
||||
}
|
||||
public bool BracketsPatternSelected
|
||||
{
|
||||
get { return _settings.GetSetting(Constants.Settings.PasswordGenerationOptions.BracketsPattern, false); }
|
||||
set { _settings.PutSetting(Constants.Settings.PasswordGenerationOptions.BracketsPattern, value); }
|
||||
}
|
||||
public string CustomChars { get; set; } = string.Empty;
|
||||
|
||||
public string Password
|
||||
{
|
||||
get { return _password; }
|
||||
set
|
||||
{
|
||||
Set(() => Password, ref _password, value);
|
||||
RaisePropertyChanged(() => PasswordComplexityIndicator);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRevealPassword
|
||||
{
|
||||
get { return _isRevealPassword; }
|
||||
set { Set(() => IsRevealPassword, ref _isRevealPassword, value); }
|
||||
}
|
||||
|
||||
public RelayCommand GeneratePasswordCommand { get; }
|
||||
|
||||
public PasswordGenerationBoxControlVm(IMediator mediator, ISettingsProxy settings, ICredentialsProxy credentials)
|
||||
{
|
||||
_mediator = mediator;
|
||||
_settings = settings;
|
||||
_credentials = credentials;
|
||||
|
||||
GeneratePasswordCommand = new RelayCommand(async () => await GeneratePassword());
|
||||
}
|
||||
|
||||
private async Task GeneratePassword()
|
||||
{
|
||||
Password = await _mediator.Send(new GeneratePasswordCommand
|
||||
{
|
||||
BracketsPatternSelected = BracketsPatternSelected,
|
||||
CustomChars = CustomChars,
|
||||
DigitsPatternSelected = DigitsPatternSelected,
|
||||
LowerCasePatternSelected = LowerCasePatternSelected,
|
||||
MinusPatternSelected = MinusPatternSelected,
|
||||
PasswordLength = (int)PasswordLength,
|
||||
SpacePatternSelected = SpacePatternSelected,
|
||||
SpecialPatternSelected = SpecialPatternSelected,
|
||||
UnderscorePatternSelected = UnderscorePatternSelected,
|
||||
UpperCasePatternSelected = UpperCasePatternSelected
|
||||
});
|
||||
MessengerInstance.Send(new PasswordGeneratedMessage { Password = Password });
|
||||
}
|
||||
}
|
||||
}
|
@@ -13,7 +13,6 @@ namespace ModernKeePass.ViewModels
|
||||
public class SetCredentialsVm : ViewModelBase
|
||||
{
|
||||
private readonly IMediator _mediator;
|
||||
private readonly ICredentialsProxy _credentials;
|
||||
private readonly IResourceProxy _resource;
|
||||
private readonly IFileProxy _file;
|
||||
|
||||
@@ -48,10 +47,9 @@ namespace ModernKeePass.ViewModels
|
||||
get { return _password; }
|
||||
set
|
||||
{
|
||||
_password = value;
|
||||
Set(() => Password, ref _password, value);
|
||||
RaisePropertyChanged(nameof(IsPasswordValid));
|
||||
RaisePropertyChanged(nameof(IsValid));
|
||||
RaisePropertyChanged(nameof(PasswordComplexityIndicator));
|
||||
GenerateCredentialsCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
}
|
||||
@@ -60,7 +58,7 @@ namespace ModernKeePass.ViewModels
|
||||
get { return _confirmPassword; }
|
||||
set
|
||||
{
|
||||
_confirmPassword = value;
|
||||
Set(() => ConfirmPassword, ref _confirmPassword, value);
|
||||
RaisePropertyChanged(nameof(IsPasswordValid));
|
||||
RaisePropertyChanged(nameof(IsValid));
|
||||
GenerateCredentialsCommand.RaiseCanExecuteChanged();
|
||||
@@ -85,8 +83,6 @@ namespace ModernKeePass.ViewModels
|
||||
set { Set(() => KeyFileText, ref _keyFileText, value); }
|
||||
}
|
||||
|
||||
public double PasswordComplexityIndicator => _credentials.EstimatePasswordComplexity(Password);
|
||||
|
||||
public bool IsPasswordValid => HasPassword && Password == ConfirmPassword || !HasPassword;
|
||||
public bool IsKeyFileValid => HasKeyFile && !string.IsNullOrEmpty(KeyFilePath) || !HasKeyFile;
|
||||
public bool IsValid => HasPassword && Password == ConfirmPassword || HasKeyFile && !string.IsNullOrEmpty(KeyFilePath) && (HasPassword || HasKeyFile);
|
||||
@@ -102,10 +98,9 @@ namespace ModernKeePass.ViewModels
|
||||
private string _keyFilePath;
|
||||
private string _keyFileText;
|
||||
|
||||
public SetCredentialsVm(IMediator mediator, ICredentialsProxy credentials, IResourceProxy resource, IFileProxy file)
|
||||
public SetCredentialsVm(IMediator mediator, IResourceProxy resource, IFileProxy file)
|
||||
{
|
||||
_mediator = mediator;
|
||||
_credentials = credentials;
|
||||
_resource = resource;
|
||||
_file = file;
|
||||
|
||||
@@ -114,6 +109,12 @@ namespace ModernKeePass.ViewModels
|
||||
GenerateCredentialsCommand = new RelayCommand(GenerateCredentials, () => IsValid);
|
||||
|
||||
_keyFileText = resource.GetResourceValue("CompositeKeyDefaultKeyFile");
|
||||
|
||||
MessengerInstance.Register<PasswordGeneratedMessage>(this, message =>
|
||||
{
|
||||
Password = message.Password;
|
||||
ConfirmPassword = message.Password;
|
||||
});
|
||||
}
|
||||
|
||||
private async Task OpenKeyFile()
|
||||
|
@@ -68,6 +68,7 @@ namespace ModernKeePass.ViewModels
|
||||
SimpleIoc.Default.Register<SetCredentialsVm>();
|
||||
SimpleIoc.Default.Register<TopMenuVm>();
|
||||
SimpleIoc.Default.Register<ColorPickerControlVm>();
|
||||
SimpleIoc.Default.Register<PasswordGenerationBoxControlVm>();
|
||||
SimpleIoc.Default.Register<NewVm>();
|
||||
SimpleIoc.Default.Register<OpenVm>();
|
||||
SimpleIoc.Default.Register<RecentVm>();
|
||||
@@ -84,6 +85,7 @@ namespace ModernKeePass.ViewModels
|
||||
public SetCredentialsVm SetCredentials => ServiceLocator.Current.GetInstance<SetCredentialsVm>(Guid.NewGuid().ToString());
|
||||
public TopMenuVm TopMenu => ServiceLocator.Current.GetInstance<TopMenuVm>(Guid.NewGuid().ToString());
|
||||
public ColorPickerControlVm ColorPicker => ServiceLocator.Current.GetInstance<ColorPickerControlVm>(Guid.NewGuid().ToString());
|
||||
public PasswordGenerationBoxControlVm PasswordGenerationBox => ServiceLocator.Current.GetInstance<PasswordGenerationBoxControlVm>(Guid.NewGuid().ToString());
|
||||
public NewVm New => ServiceLocator.Current.GetInstance<NewVm>(Guid.NewGuid().ToString());
|
||||
public OpenVm Open => ServiceLocator.Current.GetInstance<OpenVm>(Guid.NewGuid().ToString());
|
||||
public RecentVm Recent => ServiceLocator.Current.GetInstance<RecentVm>(Guid.NewGuid().ToString());
|
||||
|
@@ -40,6 +40,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\EntryFieldValueChangedMessage.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\FileNotFoundMessage.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\NavigateToPageMessage.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\PasswordGeneratedMessage.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\SaveErrorMessage.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\AboutVm.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\EntryFieldVm.cs" />
|
||||
@@ -50,6 +51,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Settings\GeneralVm.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Settings\SecurityVm.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\ColorPickerControlVm.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\PasswordGenerationBoxControlVm.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\ViewModelLocatorCommon.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\ListMenuItemVm.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\MainMenuItemVm.cs" />
|
||||
|
Reference in New Issue
Block a user