refactor lock screen for simplicity and to make it reusable.
DELETE
WalletWasabi.Gui/Controls/LockScreen/ILockScreenViewModel.cs
-using System;
-
-namespace WalletWasabi.Gui.Controls.LockScreen
-{
- public interface ILockScreenViewModel : IDisposable
- {
- }
-}

DELETE
WalletWasabi.Gui/Controls/LockScreen/LockScreenViewModel.cs
-using System;
-using ReactiveUI;
-using System.Reactive.Disposables;
-using WalletWasabi.Helpers;
-using System.Reactive.Linq;
-using WalletWasabi.Gui.ViewModels;
-using Splat;
-
-namespace WalletWasabi.Gui.Controls.LockScreen
-{
- public class LockScreenViewModel : ViewModelBase
- {
- private CompositeDisposable Disposables { get; }
-
- public LockScreenViewModel()
- {
- Disposables = new CompositeDisposable();
- }
-
- private ILockScreenViewModel _activeLockScreen;
-
- public ILockScreenViewModel ActiveLockScreen
- {
- get => _activeLockScreen;
- set => this.RaiseAndSetIfChanged(ref _activeLockScreen, value);
- }
-
- private ObservableAsPropertyHelper<string> _pinHash;
- public string PinHash => _pinHash?.Value ?? default;
-
- private bool _isLocked;
-
- public bool IsLocked
- {
- get => _isLocked;
- set => this.RaiseAndSetIfChanged(ref _isLocked, value);
- }
-
- public void Initialize()
- {
- var global = Locator.Current.GetService<Global>();
-
- global.UiConfig
- .WhenAnyValue(x => x.LockScreenActive)
- .ObserveOn(RxApp.MainThreadScheduler)
- .BindTo(this, y => y.IsLocked)
- .DisposeWith(Disposables);
-
- this.WhenAnyValue(x => x.IsLocked)
- .ObserveOn(RxApp.MainThreadScheduler)
- .BindTo(global.UiConfig, y => y.LockScreenActive)
- .DisposeWith(Disposables);
-
- _pinHash = global.UiConfig
- .WhenAnyValue(x => x.LockScreenPinHash)
- .ObserveOn(RxApp.MainThreadScheduler)
- .Do(x => CheckLockScreenType(x))
- .ToProperty(this, x => x.PinHash);
- }
-
- private void CheckLockScreenType(string currentHash)
- {
- ActiveLockScreen?.Dispose();
-
- if (currentHash.Length != 0)
- {
- ActiveLockScreen = new PinLockScreenViewModel(this);
- }
- else
- {
- ActiveLockScreen = new SlideLockScreenViewModel(this);
- }
- }
- }
-}

ADD
WalletWasabi.Gui/Controls/LockScreen/LockScreenViewModelBase.cs
+using System;
+using ReactiveUI;
+using System.Reactive.Disposables;
+using WalletWasabi.Helpers;
+using System.Reactive.Linq;
+using WalletWasabi.Gui.ViewModels;
+using Splat;
+
+namespace WalletWasabi.Gui.Controls.LockScreen
+{
+ public abstract class LockScreenViewModelBase : ViewModelBase
+ {
+ private bool _isLocked;
+ private CompositeDisposable Disposables { get; }
+
+ public LockScreenViewModelBase()
+ {
+ Disposables = new CompositeDisposable();
+
+ var global = Locator.Current.GetService<Global>();
+
+ global.UiConfig
+ .WhenAnyValue(x => x.LockScreenActive)
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .BindTo(this, y => y.IsLocked)
+ .DisposeWith(Disposables);
+
+ this.WhenAnyValue(x => x.IsLocked)
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .BindTo(global.UiConfig, y => y.LockScreenActive)
+ .DisposeWith(Disposables);
+ }
+
+ public bool IsLocked
+ {
+ get => _isLocked;
+ set => this.RaiseAndSetIfChanged(ref _isLocked, value);
+ }
+
+ protected abstract void OnInitialise(CompositeDisposable disposables);
+ }
+}

RENAME
WalletWasabi.Gui/Controls/LockScreen/PinLockScreen.xaml.cs
WalletWasabi.Gui/Controls/LockScreen/PinLockScreenView.xaml.cs
@@ -9,10 +9,10 @@ using Avalonia.LogicalTree;
namespace WalletWasabi.Gui.Controls.LockScreen
{
- public class PinLockScreen : UserControl
+ public class PinLockScreenView : UserControl
{
- public static readonly DirectProperty<PinLockScreen, bool> IsLockedProperty =
- AvaloniaProperty.RegisterDirect<PinLockScreen, bool>(nameof(IsLocked), o => o.IsLocked, (o, v) => o.IsLocked = v);
+ public static readonly DirectProperty<PinLockScreenView, bool> IsLockedProperty =
+ AvaloniaProperty.RegisterDirect<PinLockScreenView, bool>(nameof(IsLocked), o => o.IsLocked, (o, v) => o.IsLocked = v);
private bool _isLocked;
@@ -22,7 +22,7 @@ namespace WalletWasabi.Gui.Controls.LockScreen
set => SetAndRaise(IsLockedProperty, ref _isLocked, value);
}
- public PinLockScreen() : base()
+ public PinLockScreenView() : base()
{
InitializeComponent();

MODIFY
WalletWasabi.Gui/Controls/LockScreen/PinLockScreenViewModel.cs
WalletWasabi.Gui/Controls/LockScreen/PinLockScreenViewModel.cs
@@ -7,34 +7,16 @@ using System.Reactive.Disposables;
using System.Reactive.Linq;
using WalletWasabi.Gui.Helpers;
using WalletWasabi.Logging;
+using Splat;
namespace WalletWasabi.Gui.Controls.LockScreen
{
- public class PinLockScreenViewModel : ViewModelBase, ILockScreenViewModel
+ public class PinLockScreenViewModel : LockScreenViewModelBase
{
- private LockScreenViewModel ParentVM { get; }
-
- private CompositeDisposable Disposables { get; }
-
- public ReactiveCommand<string, Unit> KeyPadCommand { get; }
-
- private ObservableAsPropertyHelper<bool> _isLocked;
- public bool IsLocked => _isLocked?.Value ?? false;
-
private string _pinInput;
- public string PinInput
+ public PinLockScreenViewModel()
{
- get => _pinInput;
- set => this.RaiseAndSetIfChanged(ref _pinInput, value);
- }
-
- public PinLockScreenViewModel(LockScreenViewModel lockScreenViewModel)
- {
- ParentVM = Guard.NotNull(nameof(lockScreenViewModel), lockScreenViewModel);
-
- Disposables = new CompositeDisposable();
-
KeyPadCommand = ReactiveCommand.Create<string>((arg) =>
{
if (arg == "BACK")
@@ -64,7 +46,9 @@ namespace WalletWasabi.Gui.Controls.LockScreen
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(x =>
{
- if (ParentVM.PinHash != HashHelpers.GenerateSha256Hash(x))
+ var global = Locator.Current.GetService<Global>();
+
+ if (global.UiConfig.LockScreenPinHash != HashHelpers.GenerateSha256Hash(x))
{
NotificationHelpers.Error("PIN is incorrect!");
}
@@ -76,28 +60,32 @@ namespace WalletWasabi.Gui.Controls.LockScreen
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(x =>
{
- if (ParentVM.PinHash == HashHelpers.GenerateSha256Hash(x))
+ var global = Locator.Current.GetService<Global>();
+
+ if (global.UiConfig.LockScreenPinHash == HashHelpers.GenerateSha256Hash(x))
{
- ParentVM.IsLocked = false;
+ IsLocked = false;
PinInput = string.Empty;
}
});
- _isLocked = ParentVM
- .WhenAnyValue(x => x.IsLocked)
- .ObserveOn(RxApp.MainThreadScheduler)
- .ToProperty(this, x => x.IsLocked)
- .DisposeWith(Disposables);
-
this.WhenAnyValue(x => x.IsLocked)
.Where(x => !x)
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ => PinInput = string.Empty);
}
- public void Dispose()
+ protected override void OnInitialise(CompositeDisposable disposables)
+ {
+ var global = Locator.Current.GetService<Global>();
+ }
+
+ public string PinInput
{
- Disposables?.Dispose();
+ get => _pinInput;
+ set => this.RaiseAndSetIfChanged(ref _pinInput, value);
}
+
+ public ReactiveCommand<string, Unit> KeyPadCommand { get; }
}
}

RENAME
WalletWasabi.Gui/Controls/LockScreen/SlideLockScreen.xaml.cs
WalletWasabi.Gui/Controls/LockScreen/SlideLockScreenView.xaml.cs
@@ -12,10 +12,10 @@ using System.Reactive.Disposables;
namespace WalletWasabi.Gui.Controls.LockScreen
{
- public class SlideLockScreen : UserControl
+ public class SlideLockScreenView : UserControl
{
- public static readonly DirectProperty<SlideLockScreen, bool> IsLockedProperty =
- AvaloniaProperty.RegisterDirect<SlideLockScreen, bool>(nameof(IsLocked), o => o.IsLocked, (o, v) => o.IsLocked = v);
+ public static readonly DirectProperty<SlideLockScreenView, bool> IsLockedProperty =
+ AvaloniaProperty.RegisterDirect<SlideLockScreenView, bool>(nameof(IsLocked), o => o.IsLocked, (o, v) => o.IsLocked = v);
private bool _isLocked;
@@ -25,8 +25,8 @@ namespace WalletWasabi.Gui.Controls.LockScreen
set => SetAndRaise(IsLockedProperty, ref _isLocked, value);
}
- public static readonly DirectProperty<SlideLockScreen, double> OffsetProperty =
- AvaloniaProperty.RegisterDirect<SlideLockScreen, double>(nameof(Offset), o => o.Offset, (o, v) => o.Offset = v);
+ public static readonly DirectProperty<SlideLockScreenView, double> OffsetProperty =
+ AvaloniaProperty.RegisterDirect<SlideLockScreenView, double>(nameof(Offset), o => o.Offset, (o, v) => o.Offset = v);
private double _offset;
@@ -36,8 +36,8 @@ namespace WalletWasabi.Gui.Controls.LockScreen
set => SetAndRaise(OffsetProperty, ref _offset, value);
}
- public static readonly DirectProperty<SlideLockScreen, bool> DoneAnimatingProperty =
- AvaloniaProperty.RegisterDirect<SlideLockScreen, bool>(nameof(DoneAnimating), o => o.DoneAnimating, (o, v) => o.DoneAnimating = v);
+ public static readonly DirectProperty<SlideLockScreenView, bool> DoneAnimatingProperty =
+ AvaloniaProperty.RegisterDirect<SlideLockScreenView, bool>(nameof(DoneAnimating), o => o.DoneAnimating, (o, v) => o.DoneAnimating = v);
private bool _doneAnimating;
@@ -50,7 +50,7 @@ namespace WalletWasabi.Gui.Controls.LockScreen
private TranslateTransform TargetTransform { get; } = new TranslateTransform();
private Thumb DragThumb { get; }
- public SlideLockScreen() : base()
+ public SlideLockScreenView() : base()
{
InitializeComponent();
@@ -78,36 +78,36 @@ namespace WalletWasabi.Gui.Controls.LockScreen
this.WhenAnyValue(x => x.Offset)
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(x => TargetTransform.Y = x)
- .DisposeWith(vm.Disposables);
+ ;//.DisposeWith(vm.Disposables);
this.WhenAnyValue(x => x.Bounds)
.Select(x => x.Height)
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(x => vm.BoundsHeight = x)
- .DisposeWith(vm.Disposables);
+ ;//.DisposeWith(vm.Disposables);
this.WhenAnyValue(x => x.DoneAnimating)
.Where(x => x)
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ => vm.StateChanged = false)
- .DisposeWith(vm.Disposables);
+ ;//.DisposeWith(vm.Disposables);
Observable.FromEventPattern(DragThumb, nameof(DragThumb.DragCompleted))
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ => vm.IsUserDragging = false)
- .DisposeWith(vm.Disposables);
+ ;//.DisposeWith(vm.Disposables);
Observable.FromEventPattern(DragThumb, nameof(DragThumb.DragStarted))
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ => vm.IsUserDragging = true)
- .DisposeWith(vm.Disposables);
+ ;//.DisposeWith(vm.Disposables);
Observable.FromEventPattern<VectorEventArgs>(DragThumb, nameof(DragThumb.DragDelta))
.Where(e => e.EventArgs.Vector.Y < 0)
.Select(e => e.EventArgs.Vector.Y)
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(x => vm.Offset = x)
- .DisposeWith(vm.Disposables);
+ ;//.DisposeWith(vm.Disposables);
vm.WhenAnyValue(x => x.StateChanged)
.ObserveOn(RxApp.MainThreadScheduler)
@@ -122,11 +122,11 @@ namespace WalletWasabi.Gui.Controls.LockScreen
Classes.Remove("statechanged");
}
})
- .DisposeWith(vm.Disposables);
+ ;//.DisposeWith(vm.Disposables);
Clock.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(vm.OnClockTick)
- .DisposeWith(vm.Disposables);
+ ;//.DisposeWith(vm.Disposables);
}
}
}

MODIFY
WalletWasabi.Gui/Controls/LockScreen/SlideLockScreenViewModel.cs
WalletWasabi.Gui/Controls/LockScreen/SlideLockScreenViewModel.cs
@@ -8,7 +8,7 @@ using Avalonia;
namespace WalletWasabi.Gui.Controls.LockScreen
{
- public class SlideLockScreenViewModel : ViewModelBase, ILockScreenViewModel
+ public class SlideLockScreenViewModel : LockScreenViewModelBase
{
private enum SlideLockState
{
@@ -18,10 +18,7 @@ namespace WalletWasabi.Gui.Controls.LockScreen
}
private SlideLockState _state = SlideLockState.Idle;
- public CompositeDisposable Disposables { get; }
- private LockScreenViewModel _parentVM;
- private ObservableAsPropertyHelper<bool> _isLocked;
- public bool IsLocked => _isLocked?.Value ?? false;
+
private bool _isUserDragging;
@@ -76,18 +73,8 @@ namespace WalletWasabi.Gui.Controls.LockScreen
public readonly double ThresholdPercent = 1 / 6d;
public readonly double Stiffness = 0.12d;
- public SlideLockScreenViewModel(LockScreenViewModel lockScreenViewModel)
+ protected override void OnInitialise(CompositeDisposable disposables)
{
- _parentVM = Guard.NotNull(nameof(lockScreenViewModel), lockScreenViewModel);
-
- Disposables = new CompositeDisposable();
-
- _isLocked = _parentVM
- .WhenAnyValue(x => x.IsLocked)
- .ObserveOn(RxApp.MainThreadScheduler)
- .ToProperty(this, x => x.IsLocked)
- .DisposeWith(Disposables);
-
this.WhenAnyValue(x => x.TargetOffset)
.DistinctUntilChanged()
.ObserveOn(RxApp.MainThreadScheduler)
@@ -96,12 +83,7 @@ namespace WalletWasabi.Gui.Controls.LockScreen
StateChanged = false;
StateChanged = true;
})
- .DisposeWith(Disposables);
- }
-
- public void Dispose()
- {
- Disposables?.Dispose();
+ .DisposeWith(disposables);
}
internal void OnClockTick(TimeSpan _)
@@ -138,7 +120,7 @@ namespace WalletWasabi.Gui.Controls.LockScreen
break;
case SlideLockState.UserDragPassedThreshold:
- _parentVM.IsLocked = false;
+ IsLocked = false;
_state = SlideLockState.Idle;
break;
}

MODIFY
WalletWasabi.Gui/ViewModels/MainWindowViewModel.cs
WalletWasabi.Gui/ViewModels/MainWindowViewModel.cs
@@ -9,6 +9,7 @@ using System;
using System.IO;
using System.Linq;
using System.Reactive;
+using System.Reactive.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using WalletWasabi.Gui.Controls.LockScreen;
@@ -61,9 +62,9 @@ namespace WalletWasabi.Gui.ViewModels
set => this.RaiseAndSetIfChanged(ref _statusBar, value);
}
- private LockScreenViewModel _lockScreen;
+ private LockScreenViewModelBase _lockScreen;
- public LockScreenViewModel LockScreen
+ public LockScreenViewModelBase LockScreen
{
get => _lockScreen;
set => this.RaiseAndSetIfChanged(ref _lockScreen, value);
@@ -92,11 +93,9 @@ namespace WalletWasabi.Gui.ViewModels
StatusBar = new StatusBarViewModel();
- LockScreen = new LockScreenViewModel();
+ DisplayWalletManager();
- LockScreen.Initialize();
- DisplayWalletManager();
}
public void Initialize()
@@ -109,6 +108,44 @@ namespace WalletWasabi.Gui.ViewModels
{
MainWindowViewModel.Instance.Title += $" - {global.Network}";
}
+
+ InitialiseLockScreen(global.UiConfig);
+ }
+
+ private void InitialiseLockScreen (UiConfig uiConfig)
+ {
+ uiConfig
+ .WhenAnyValue(x => x.LockScreenPinHash)
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .Subscribe(CheckLockScreenType);
+
+ uiConfig
+ .WhenAnyValue(x => x.LockScreenActive)
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .Subscribe(x =>
+ {
+ if (x)
+ {
+ CheckLockScreenType(uiConfig.LockScreenPinHash);
+ }
+ else
+ {
+ LockScreen.IsLocked = false;
+ }
+ });
+
+ }
+
+ private void CheckLockScreenType(string currentHash)
+ {
+ if (currentHash.Length != 0)
+ {
+ LockScreen = new PinLockScreenViewModel();
+ }
+ else
+ {
+ LockScreen = new SlideLockScreenViewModel();
+ }
}
private void DisplayWalletManager()

refactor lock screen for simplicity and to make it reusable.