Make SlideLock slide up when unlocking. Add a visual indicator below too.
MODIFY
WalletWasabi.Gui/Controls/LockScreen/SlideLockScreen.xaml.cs
WalletWasabi.Gui/Controls/LockScreen/SlideLockScreen.xaml.cs
@@ -27,6 +27,33 @@ 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);
+
+ private double _offset;
+
+ public double Offset
+ {
+ get => _offset;
+ 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);
+
+ private bool _doneAnimating;
+
+ public bool DoneAnimating
+ {
+ get => _doneAnimating;
+ set => SetAndRaise(DoneAnimatingProperty, ref _doneAnimating, value);
+ }
+
+
private TranslateTransform TargetTransform { get; } = new TranslateTransform();
private Thumb DragThumb { get; }
@@ -34,20 +61,23 @@ namespace WalletWasabi.Gui.Controls.LockScreen
{
var vm = this.DataContext as SlideLockScreenViewModel;
- vm.WhenAnyValue(x => x.Offset)
+ this.WhenAnyValue(x => x.Offset)
.Subscribe(x => TargetTransform.Y = x)
.DisposeWith(vm.Disposables);
- vm.WhenAnyValue(x => x.IsLocked)
- .Where(x => x)
- .Subscribe(x => vm.Offset = 0)
- .DisposeWith(vm.Disposables);
-
this.WhenAnyValue(x => x.Bounds)
.Select(x => x.Height)
- .Subscribe(x => vm.Threshold = x * vm.ThresholdPercent)
+ .Subscribe(x => vm.BoundsHeight = x)
+ .DisposeWith(vm.Disposables);
+
+ this.WhenAnyValue(x => x.DoneAnimating)
+ .Subscribe(x =>
+ {
+ if (x) vm.StateChanged = false;
+ })
.DisposeWith(vm.Disposables);
+
Observable.FromEventPattern(DragThumb, nameof(DragThumb.DragCompleted))
.Subscribe(e => vm.IsUserDragging = false)
.DisposeWith(vm.Disposables);
@@ -62,8 +92,21 @@ namespace WalletWasabi.Gui.Controls.LockScreen
.Subscribe(x => vm.Offset = x)
.DisposeWith(vm.Disposables);
- Clock.Where(x => vm.IsLocked)
- .Subscribe(vm.OnClockTick)
+ vm.WhenAnyValue(x => x.StateChanged)
+ .Subscribe(x =>
+ {
+ if (x)
+ {
+ this.Classes.Add("statechanged");
+ }
+ else
+ {
+ this.Classes.Remove("statechanged");
+ }
+ })
+ .DisposeWith(vm.Disposables);
+
+ Clock.Subscribe(vm.OnClockTick)
.DisposeWith(vm.Disposables);
}

MODIFY
WalletWasabi.Gui/Controls/LockScreen/SlideLockScreenViewModel.cs
WalletWasabi.Gui/Controls/LockScreen/SlideLockScreenViewModel.cs
@@ -10,6 +10,14 @@ namespace WalletWasabi.Gui.Controls.LockScreen
{
public class SlideLockScreenViewModel : ViewModelBase, ILockScreenViewModel
{
+ private enum SlideLockState
+ {
+ Idle,
+ UserIsDragging,
+ UserDragPassedThreshold,
+ }
+
+ private SlideLockState _state = SlideLockState.Idle;
public CompositeDisposable Disposables { get; }
private LockScreenViewModel _parentVM;
private ObservableAsPropertyHelper<bool> _isLocked;
@@ -22,11 +30,27 @@ namespace WalletWasabi.Gui.Controls.LockScreen
set => this.RaiseAndSetIfChanged(ref _isUserDragging, value);
}
- private double _threshold;
- public double Threshold
+ private double _boundsHeight;
+ public double BoundsHeight
+ {
+ get => _boundsHeight;
+ set => this.RaiseAndSetIfChanged(ref _boundsHeight, value);
+ }
+
+ public double _targetOffset;
+ public double TargetOffset
+ {
+ get => _targetOffset;
+ set => this.RaiseAndSetIfChanged(ref _targetOffset, value);
+ }
+
+ public double Threshold => BoundsHeight * ThresholdPercent;
+
+ private double _targetOpacity;
+ public double TargetOpacity
{
- get => _threshold;
- set => this.RaiseAndSetIfChanged(ref _threshold, value);
+ get => _targetOpacity;
+ set => this.RaiseAndSetIfChanged(ref _targetOpacity, value);
}
private double _offset;
@@ -36,6 +60,14 @@ namespace WalletWasabi.Gui.Controls.LockScreen
set => this.RaiseAndSetIfChanged(ref _offset, value);
}
+ private bool _stateChanged;
+
+ public bool StateChanged
+ {
+ get => _stateChanged;
+ set => this.RaiseAndSetIfChanged(ref _stateChanged, value);
+ }
+
public readonly double ThresholdPercent = 1 / 6d;
public readonly double Stiffness = 0.12d;
@@ -49,6 +81,15 @@ namespace WalletWasabi.Gui.Controls.LockScreen
.ObserveOn(RxApp.MainThreadScheduler)
.ToProperty(this, x => x.IsLocked)
.DisposeWith(Disposables);
+
+ this.WhenAnyValue(x => x.TargetOffset)
+ .DistinctUntilChanged()
+ .Subscribe(x =>
+ {
+ StateChanged = false;
+ StateChanged = true;
+ })
+ .DisposeWith(Disposables);
}
public void Dispose()
@@ -56,17 +97,49 @@ namespace WalletWasabi.Gui.Controls.LockScreen
Disposables?.Dispose();
}
- internal void OnClockTick(TimeSpan obj)
+ internal void OnClockTick(TimeSpan _)
{
- if (IsLocked & !IsUserDragging & Math.Abs(Offset) > Threshold)
+ switch (_state)
{
- _parentVM.IsLocked = false;
+ case SlideLockState.Idle:
+
+ if (IsUserDragging)
+ {
+ _state = SlideLockState.UserIsDragging;
return;
}
- else if (IsLocked & !IsUserDragging & Offset != 0)
+
+ if (IsLocked)
{
+ TargetOffset = 0;
+ TargetOpacity = 1;
Offset *= 1 - Stiffness;
}
+ else
+ {
+ TargetOpacity = 0;
+ TargetOffset = -BoundsHeight;
+ }
+
+ break;
+
+ case SlideLockState.UserIsDragging:
+ if (!IsUserDragging)
+ {
+ if (Math.Abs(Offset) > Threshold)
+ {
+ _state = SlideLockState.UserDragPassedThreshold;
+ }
+ else
+ _state = SlideLockState.Idle;
+ }
+ break;
+
+ case SlideLockState.UserDragPassedThreshold:
+ _parentVM.IsLocked = false;
+ _state = SlideLockState.Idle;
+ break;
+ }
}
}
}

Make SlideLock slide up when unlocking. Add a visual indicator below too.