PIN settings now fully functional.
MODIFY
WalletWasabi.Gui/Controls/LockScreen/LockScreen.xaml.cs
WalletWasabi.Gui/Controls/LockScreen/LockScreen.xaml.cs
@@ -68,7 +68,7 @@ namespace WalletWasabi.Gui.Controls.LockScreen
switch (obj)
{
case LockScreenType.PINLock:
- var pinLock = new PINLock();
+ var pinLock = new PinLock();
CurrentLockScreen = pinLock;
this.WhenAnyValue(x => x.PINHash)

RENAME
WalletWasabi.Gui/Controls/LockScreen/PINLock.xaml.cs
WalletWasabi.Gui/Controls/LockScreen/PinLock.xaml.cs
@@ -11,18 +11,21 @@ using Avalonia.Interactivity;
using System.Reactive.Linq;
using System.Security.Cryptography;
using WalletWasabi.Helpers;
+using System.Reactive;
namespace WalletWasabi.Gui.Controls.LockScreen
{
- public class PINLock : LockScreenBase
+ public class PinLock : LockScreenBase
{
public Grid Shade { get; }
+ public ReactiveCommand<string, Unit> KeyPadCommand { get; }
+
private NoparaPasswordBox PinLockPwdBox;
internal string PINHash { get; set; }
- public PINLock() : base()
+ public PinLock() : base()
{
InitializeComponent();
@@ -30,12 +33,17 @@ namespace WalletWasabi.Gui.Controls.LockScreen
this.PinLockPwdBox = this.FindControl<NoparaPasswordBox>("PinLockPwdBox");
PinLockPwdBox.WhenAnyValue(x => x.Password)
- .ObserveOn(RxApp.MainThreadScheduler)
.Select(Guard.Correct)
.Where(x => x != string.Empty)
.DistinctUntilChanged()
.Throttle(TimeSpan.FromSeconds(1d))
+ .ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(CheckPIN);
+
+ KeyPadCommand = ReactiveCommand.Create<string>((arg) =>
+ {
+ PinLockPwdBox.Password += arg;
+ });
}
private void CheckPIN(string obj)

MODIFY
WalletWasabi.Gui/Tabs/SettingsView.xaml
WalletWasabi.Gui/Tabs/SettingsView.xaml
<controls:GroupBox Title="Screen Lock" TextBlock.FontSize="16" Padding="10" Margin="0 5 10 5">
<StackPanel Orientation="Vertical" Spacing="5">
<StackPanel Margin="0 10" Orientation="Horizontal" Spacing="5">
- <ToggleButton IsChecked="{Binding EnablePINLock, Mode=OneWay}" Content="{Binding EnablePINLock, Converter={StaticResource BooleanStringConverter}, ConverterParameter=On:Off}" Margin="0 0 10 0" Command="{Binding EnablePINLockCommand}" />
+ <ToggleButton IsChecked="{Binding EnablePINEntry}" Content="{Binding EnablePINEntry, Converter={StaticResource BooleanStringConverter}, ConverterParameter=On:Off}" Margin="0 0 10 0" Command="{Binding EnablePINLockCommand}" />
<TextBlock VerticalAlignment="Center">Use PIN to unlock the screen.</TextBlock>
</StackPanel>
- <StackPanel Orientation="Vertical" Spacing="5" IsVisible="{Binding EnablePINLock, Mode=OneWay}">
- <controls:NoparaPasswordBox Watermark="Old PIN" Password="{Binding OldPINPwdBox}" UseFloatingWatermark="True"/>
- <controls:NoparaPasswordBox Watermark="New PIN" Password="{Binding NewPINPwdBox}" UseFloatingWatermark="True"/>
- <Button Content="Confirm"/>
+ <StackPanel Orientation="Vertical" Spacing="5">
+ <controls:NoparaPasswordBox Watermark="PIN" Password="{Binding OldPINPwdBox}" UseFloatingWatermark="True"/>
+ <controls:NoparaPasswordBox Watermark="Confirm PIN" Password="{Binding NewPINPwdBox}" UseFloatingWatermark="True"/>
+ <TextBlock Text="{Binding ConfirmPINWarningMessage}" Classes="warningMessage" Margin="0 0 3 0" />
</StackPanel>
</StackPanel>
</controls:GroupBox>

MODIFY
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
@@ -12,6 +12,7 @@ using System.Reactive.Disposables;
using System.Reactive.Linq;
using WalletWasabi.Gui.ViewModels;
using WalletWasabi.Gui.ViewModels.Validation;
+using WalletWasabi.Helpers;
namespace WalletWasabi.Gui.Tabs
{
@@ -34,12 +35,12 @@ namespace WalletWasabi.Gui.Tabs
private string _dustThreshold;
private string _oldPINPwdBox;
private string _newPINPwdBox;
+ private string _confirmPINWarningMessage;
private AsyncLock ConfigLock { get; } = new AsyncLock();
public ReactiveCommand<Unit, Unit> OpenConfigFileCommand { get; }
public ReactiveCommand<Unit, Unit> LurkingWifeModeCommand { get; }
public ReactiveCommand<Unit, Unit> EnablePINLockCommand { get; }
- public ReactiveCommand<Unit, Unit> SetPINLockCommand { get; }
public SettingsViewModel(Global global) : base(global, "Settings")
{
@@ -99,7 +100,7 @@ namespace WalletWasabi.Gui.Tabs
IsModified = await Global.Config.CheckFileChangeAsync();
- EnablePINLock = Global.UiConfig.LockScreenPinHash != string.Empty;
+ EnablePINEntry = Global.UiConfig.LockScreenPinHash != string.Empty;
});
OpenConfigFileCommand = ReactiveCommand.Create(OpenConfigFile);
@@ -112,21 +113,44 @@ namespace WalletWasabi.Gui.Tabs
EnablePINLockCommand = ReactiveCommand.CreateFromTask(async () =>
{
- EnablePINLock = !EnablePINLock;
+ if (_oldPINPwdBox != _newPINPwdBox)
+ {
+ ConfirmPINWarningMessage = "Both PIN entries does not match.";
+ EnablePINEntry = !EnablePINEntry;
+ return;
+ }
- if (!EnablePINLock)
+ if (_oldPINPwdBox == string.Empty ||
+ _newPINPwdBox == string.Empty)
{
- Global.UiConfig.LockScreenPinHash = string.Empty;
+ ConfirmPINWarningMessage = "Both PIN entries must be filled out.";
+ EnablePINEntry = !EnablePINEntry;
+ return;
}
- await Global.UiConfig.ToFileAsync();
- });
+ var uiConfigPINHash = Global.UiConfig.LockScreenPinHash;
+ var enteredPINHash = HashHelpers.GenerateSha256Hash(_newPINPwdBox);
- SetPINLockCommand = ReactiveCommand.CreateFromTask(async () =>
+ if (EnablePINEntry)
{
- EnablePINLock = !EnablePINLock;
-
+ Global.UiConfig.LockScreenPinHash = enteredPINHash;
await Global.UiConfig.ToFileAsync();
+ }
+ else
+ {
+ if (uiConfigPINHash != enteredPINHash)
+ {
+ ConfirmPINWarningMessage = "Wrong PIN.";
+ EnablePINEntry = true;
+ return;
+ }
+ Global.UiConfig.LockScreenPinHash = string.Empty;
+ await Global.UiConfig.ToFileAsync();
+ }
+
+ OldPINPwdBox = string.Empty;
+ NewPINPwdBox = string.Empty;
+ ConfirmPINWarningMessage = string.Empty;
});
}
@@ -244,26 +268,30 @@ namespace WalletWasabi.Gui.Tabs
public bool LurkingWifeMode => Global.UiConfig.LurkingWifeMode is true;
- public bool EnablePINLock
+ public bool EnablePINEntry
{
get => _enablePINLock;
set => this.RaiseAndSetIfChanged(ref _enablePINLock, value);
}
- [ValidateMethod(nameof(ValidateOldPINPwdBox))]
public string OldPINPwdBox
{
get => _oldPINPwdBox;
set => this.RaiseAndSetIfChanged(ref _oldPINPwdBox, value);
}
- [ValidateMethod(nameof(ValidateNewPINPwdBox))]
public string NewPINPwdBox
{
get => _newPINPwdBox;
set => this.RaiseAndSetIfChanged(ref _newPINPwdBox, value);
}
+ public string ConfirmPINWarningMessage
+ {
+ get => _confirmPINWarningMessage;
+ set => this.RaiseAndSetIfChanged(ref _confirmPINWarningMessage, value);
+ }
+
private void Save()
{
var isValid = string.IsNullOrEmpty(ValidateTorHost())
@@ -447,28 +475,6 @@ namespace WalletWasabi.Gui.Tabs
return "Invalid port.";
}
- private string ValidateOldPINPwdBox()
- {
- if (OldPINPwdBox == string.Empty)
- return "Empty PIN is not allowed.";
-
- if (OldPINPwdBox != NewPINPwdBox)
- return "PIN Entries doesnt match.";
-
- return string.Empty;
- }
-
- private object ValidateNewPINPwdBox()
- {
- if (NewPINPwdBox == string.Empty)
- return "Empty PIN is not allowed.";
-
- if (NewPINPwdBox != OldPINPwdBox)
- return "PIN Entries doesnt match.";
-
- return string.Empty;
- }
-
private void OpenConfigFile()
{
IoHelpers.OpenFileInTextEditor(Global.Config.FilePath);

MODIFY
WalletWasabi.Gui/UiConfig.cs
WalletWasabi.Gui/UiConfig.cs
@@ -22,6 +22,7 @@ namespace WalletWasabi.Gui
{
private bool? _lurkingWifeMode;
private bool? _lockScreenActive;
+ private string _lockScreenPinHash;
private LockScreenType? _lockScreenType;
/// <inheritdoc />
@@ -61,7 +62,11 @@ namespace WalletWasabi.Gui
}
[JsonProperty(PropertyName = "LockScreenPinHash")]
- public string LockScreenPinHash { get; internal set; }
+ public string LockScreenPinHash
+ {
+ get => _lockScreenPinHash;
+ set => this.RaiseAndSetIfChanged(ref _lockScreenPinHash, value);
+ }
public UiConfig()
{

PIN settings now fully functional.