polishing the detection view
MODIFY
WalletWasabi.Fluent/ViewModels/AddWallet/HardwareWallet/ConnectHardwareWalletViewModel.cs
WalletWasabi.Fluent/ViewModels/AddWallet/HardwareWallet/ConnectHardwareWalletViewModel.cs
@@ -4,28 +4,39 @@ using System.Linq;
using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
+using System.Timers;
using NBitcoin;
using ReactiveUI;
using WalletWasabi.Fluent.ViewModels.Navigation;
using WalletWasabi.Hwi.Exceptions;
using WalletWasabi.Hwi.Models;
using WalletWasabi.Wallets;
+using Timer = System.Timers.Timer;
namespace WalletWasabi.Fluent.ViewModels.AddWallet.HardwareWallet
{
public class ConnectHardwareWalletViewModel : RoutableViewModel
{
private string _message;
+ private bool _nothingShowUpMessageVisibility;
public ConnectHardwareWalletViewModel(string walletName, Network network, WalletManager walletManager)
{
WalletName = walletName;
- HardwareWalletOperations = new HardwareWalletOperations(walletManager, network); // TODO: call dispose
+ HardwareWalletOperations = new HardwareWalletOperations(walletManager, network);
HardwareWalletOperations.HardwareWalletsFound += OnHardwareWalletsFound;
+ HardwareWalletOperations.SearchingHasNoResult += OnSearchingHasNoResult;
+ HardwareWalletOperations.PassphraseTimer.Elapsed += OnPassphraseNeeded;
_message = "";
}
+ public bool NothingShowUpMessageVisibility
+ {
+ get => _nothingShowUpMessageVisibility;
+ set => this.RaiseAndSetIfChanged(ref _nothingShowUpMessageVisibility, value);
+ }
+
public string WalletName { get; }
public string Message
@@ -36,8 +47,20 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet.HardwareWallet
public HardwareWalletOperations HardwareWalletOperations { get; }
+ private void OnSearchingHasNoResult(object? sender, EventArgs e)
+ {
+ NothingShowUpMessageVisibility = true;
+ }
+
+ private void OnPassphraseNeeded(object sender, ElapsedEventArgs e)
+ {
+ Message = "Check your device and enter your passphrase.";
+ }
+
private void OnHardwareWalletsFound(object? sender, HwiEnumerateEntry[] devices)
{
+ NothingShowUpMessageVisibility = false;
+
if (devices.Length > 1)
{
Message = "Make sure you have only one hardware wallet connected to the PC.";

MODIFY
WalletWasabi.Fluent/ViewModels/AddWallet/HardwareWallet/HardwareWalletOperations.cs
WalletWasabi.Fluent/ViewModels/AddWallet/HardwareWallet/HardwareWalletOperations.cs
using System;
-using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
-using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using NBitcoin;
-using ReactiveUI;
using WalletWasabi.Blockchain.Keys;
using WalletWasabi.Hwi;
using WalletWasabi.Hwi.Models;
using WalletWasabi.Logging;
using WalletWasabi.Wallets;
+using Timer = System.Timers.Timer;
namespace WalletWasabi.Fluent.ViewModels.AddWallet.HardwareWallet
{
public class HardwareWalletOperations : IDisposable
{
public event EventHandler<HwiEnumerateEntry[]>? HardwareWalletsFound;
+ public event EventHandler? SearchingHasNoResult;
public HardwareWalletOperations(WalletManager walletManager, Network network)
{
WalletManager = walletManager;
Network = network;
Client = new HwiClient(network);
-
DisposeCts = new CancellationTokenSource();
+ Stopwatch = new Stopwatch();
+
+ PassphraseTimer = new Timer(8000) {AutoReset = false};
StartDetection();
}
@@ -44,11 +45,20 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet.HardwareWallet
public Task? DetectionTask { get; set; }
+ public Stopwatch Stopwatch { get; }
+
+ public Timer PassphraseTimer { get; }
+
private void OnHardwareWalletsFound(HwiEnumerateEntry[] wallet)
{
HardwareWalletsFound?.Invoke(this,wallet);
}
+ private void OnSearchingHasNoResult()
+ {
+ SearchingHasNoResult?.Invoke(this,EventArgs.Empty);
+ }
+
public async Task GenerateWalletAsync(string walletName)
{
var selectedDevice = SelectedDevice;
@@ -101,14 +111,17 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet.HardwareWallet
protected async Task HardwareWalletDetectionAsync(CancellationTokenSource detectionCts)
{
+ int nothingFoundCounter = 0;
+
while (!detectionCts.IsCancellationRequested)
{
- var sw = Stopwatch.StartNew();
+ Stopwatch.Start();
try
{
using var timeoutCts = new CancellationTokenSource(TimeSpan.FromMinutes(3));
+ PassphraseTimer.Start();
var detectedHardwareWallets =
(await Client.EnumerateAsync(timeoutCts.Token)
.ConfigureAwait(false))
@@ -122,6 +135,10 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet.HardwareWallet
{
OnHardwareWalletsFound(detectedHardwareWallets);
}
+ else
+ {
+ nothingFoundCounter++;
+ }
}
catch (Exception ex)
{
@@ -130,13 +147,23 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet.HardwareWallet
Logger.LogError(ex);
}
}
+ finally
+ {
+ PassphraseTimer.Stop();
+
+ if (nothingFoundCounter >= 3)
+ {
+ OnSearchingHasNoResult();
+ nothingFoundCounter = 0;
+ }
+ }
// Too fast enumeration causes the detected hardware wallets to be unable to provide the fingerprint.
// Wait at least 5 seconds between two enumerations.
- sw.Stop();
- if (sw.Elapsed.Milliseconds < 5000)
+ Stopwatch.Stop();
+ if (Stopwatch.Elapsed.Milliseconds < 5000)
{
- await Task.Delay(5000 - sw.Elapsed.Milliseconds).ConfigureAwait(false);
+ await Task.Delay(5000 - Stopwatch.Elapsed.Milliseconds).ConfigureAwait(false);
}
}
}
@@ -150,6 +177,7 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet.HardwareWallet
DisposeCts.Dispose();
DetectionCts?.Dispose();
DetectionTask?.Dispose();
+ PassphraseTimer.Dispose();
});
}
}

MODIFY
WalletWasabi.Fluent/Views/AddWallet/HardwareWallet/ConnectHardwareWalletView.axaml
WalletWasabi.Fluent/Views/AddWallet/HardwareWallet/ConnectHardwareWalletView.axaml
Caption="Connect your hardware wallet to the PC"
EnableCancel="True" CancelContent="Cancel"
EnableBack="True">
+ <DockPanel LastChildFill="True">
- <DockPanel>
-
- <c:InfoMessage DockPanel.Dock="Bottom" Classes="h8" IsVisible="False">
- <StackPanel>
- <TextBlock Text="Nothing showing up?"/>
- <StackPanel Orientation="Horizontal">
- <Button Content="Click here" Classes="h8 plain activeHyperLink" Foreground="{DynamicResource SystemAccentColor}" />
- <TextBlock Text=" for more help."/>
- </StackPanel>
- </StackPanel>
- </c:InfoMessage>
-
- <DockPanel>
-
- <StackPanel VerticalAlignment="Top" DockPanel.Dock="Top" Margin="0 20 0 0">
- <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="40">
+ <StackPanel DockPanel.Dock="Top" VerticalAlignment="Top" HorizontalAlignment="Center" Margin="0 20 0 0" Spacing="40" Orientation="Horizontal">
<Image Height="100" Source="/Assets/HardwareIcons/ledger.png" />
<Image Height="100" Source="/Assets/HardwareIcons/coldcard.png" />
<Image Height="100" Source="/Assets/HardwareIcons/trezor.png" />
<Image Height="100" Source="/Assets/HardwareIcons/generic.png" />
</StackPanel>
- <TextBlock Text="{Binding Message}" HorizontalAlignment="Center" Margin="0 100 0 0"/>
+
+ <Panel DockPanel.Dock="Bottom">
+
+ <TextBlock Text="{Binding Message}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0 0 0 200"/>
+
+ <c:ProgressRing IsIndeterminate="True" VerticalAlignment="Center" HorizontalAlignment="Center" Height="100" Width="100" />
+
+ <c:InfoMessage Classes="h8" IsVisible="{Binding NothingShowUpMessageVisibility}" VerticalAlignment="Bottom" HorizontalAlignment="Left">
+ <StackPanel>
+ <TextBlock Text="Nothing show up?"/>
+ <TextBlock Text="Click on the link for more help."/>
</StackPanel>
+ </c:InfoMessage>
- <c:ProgressRing IsIndeterminate="True" VerticalAlignment="Center" Height="100" Width="100" />
+ <Button Content="More information and help with Hardware Wallets" Classes="h8 plain activeHyperLink" HorizontalAlignment="Center" VerticalAlignment="Bottom" Foreground="{DynamicResource SystemAccentColor}" />
+ </Panel>
</DockPanel>
- </DockPanel>
-
</c:ContentArea>
</UserControl>

polishing the detection view