AddWalletView rework
ADD
WalletWasabi.Fluent/Converters/ResolveApplicationResourceConverter.cs
+using System.Globalization;
+using Avalonia;
+using Avalonia.Data.Converters;
+
+namespace WalletWasabi.Fluent.Converters;
+
+// Not sure if there is a straight XAML-only way to do this
+// {StaticResource ResourceKey={Binding SomeString}} doesn't work :(
+public class ResolveApplicationResourceConverter : IValueConverter
+{
+ public static readonly ResolveApplicationResourceConverter Instance = new();
+
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (Application.Current is not { })
+ {
+ return null;
+ }
+
+ if (value is not string key || string.IsNullOrEmpty(key))
+ {
+ return null;
+ }
+
+ return
+ Application.Current.Styles.TryGetResource(key, out var resource)
+ ? resource
+ : throw new InvalidOperationException($"Resource '{key}' not found.");
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
+ throw new NotImplementedException();
+}

ADD
WalletWasabi.Fluent/Models/AddWalletPageOption.cs
+using ReactiveUI;
+using WalletWasabi.Fluent.Models;
+
+namespace WalletWasabi.Fluent.ViewModels.AddWallet;
+
+public partial class AddWalletPageOption : ReactiveObject
+{
+ [AutoNotify] private string? _title;
+ [AutoNotify] private string? _description;
+ [AutoNotify] private string? _iconName;
+
+ public WalletCreationOption CreationOption { get; init; }
+}

MODIFY
WalletWasabi.Fluent/ViewModels/AddWallet/AddWalletPageViewModel.cs
WalletWasabi.Fluent/ViewModels/AddWallet/AddWalletPageViewModel.cs
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Threading.Tasks;
-using System.Windows.Input;
using ReactiveUI;
using WalletWasabi.Fluent.Helpers;
using WalletWasabi.Fluent.Models;
@@ -25,17 +26,45 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet;
NavBarPosition = NavBarPosition.Bottom)]
public partial class AddWalletPageViewModel : DialogViewModelBase<Unit>
{
+ [AutoNotify] private AddWalletPageOption _selectedOption;
+
public AddWalletPageViewModel()
{
SelectionMode = NavBarItemSelectionMode.Button;
- CreateWalletCommand = ReactiveCommand.Create(OnCreateWallet);
-
- ConnectHardwareWalletCommand = ReactiveCommand.Create(OnConnectHardwareWallet);
-
- ImportWalletCommand = ReactiveCommand.CreateFromTask(async () => await OnImportWalletAsync());
+ Options = new()
+ {
+ new AddWalletPageOption
+ {
+ CreationOption = WalletCreationOption.AddNewWallet,
+ Title = "Create a new wallet",
+ Description = "Set up a new empty wallet.",
+ IconName = "add_regular"
+ },
+ new AddWalletPageOption
+ {
+ CreationOption = WalletCreationOption.ConnectToHardwareWallet,
+ Title = "Connect to hardware wallet",
+ Description = "Link your physical device to Wasabi.",
+ IconName = "calculator_regular"
+ },
+ new AddWalletPageOption
+ {
+ CreationOption = WalletCreationOption.ImportWallet,
+ Title = "Import a wallet",
+ Description = "Add an existing wallet file.",
+ IconName = "import_regular"
+ },
+ new AddWalletPageOption
+ {
+ CreationOption = WalletCreationOption.RecoverWallet,
+ Title = "Recover a wallet",
+ Description = "Lost access to your wallet? recover it by entering your recovery words.",
+ IconName = "recover_arrow_right_regular"
+ },
+ };
- RecoverWalletCommand = ReactiveCommand.Create(OnRecoverWallet);
+ _selectedOption = Options.First();
OpenCommand = ReactiveCommand.Create(async () =>
{
@@ -43,27 +72,13 @@ public partial class AddWalletPageViewModel : DialogViewModelBase<Unit>
await NavigateDialogAsync(this, NavigationTarget.DialogScreen);
MainViewModel.Instance.IsOobeBackgroundVisible = false;
});
- }
-
- public ICommand CreateWalletCommand { get; }
-
- public ICommand ConnectHardwareWalletCommand { get; }
- public ICommand ImportWalletCommand { get; }
-
- public ICommand RecoverWalletCommand { get; }
-
- private void OnCreateWallet()
- {
- Navigate().To(new WalletNamePageViewModel(WalletCreationOption.AddNewWallet));
+ NextCommand = ReactiveCommand.CreateFromTask(OnNextAsync);
}
- private void OnConnectHardwareWallet()
- {
- Navigate().To(new WalletNamePageViewModel(WalletCreationOption.ConnectToHardwareWallet));
- }
+ public List<AddWalletPageOption> Options { get; }
- private async Task OnImportWalletAsync()
+ private async Task ImportWalletAsync()
{
try
{
@@ -93,9 +108,18 @@ public partial class AddWalletPageViewModel : DialogViewModelBase<Unit>
}
}
- private void OnRecoverWallet()
+ private async Task OnNextAsync()
{
- Navigate().To(new WalletNamePageViewModel(WalletCreationOption.RecoverWallet));
+ var selected = SelectedOption ?? Options.First();
+
+ if (selected.CreationOption == WalletCreationOption.ImportWallet)
+ {
+ await ImportWalletAsync();
+ }
+ else
+ {
+ Navigate().To(new WalletNamePageViewModel(selected.CreationOption));
+ }
}
protected override void OnNavigatedTo(bool isInHistory, CompositeDisposable disposables)
@@ -104,5 +128,7 @@ public partial class AddWalletPageViewModel : DialogViewModelBase<Unit>
var enableCancel = Services.WalletManager.HasWallet();
SetupCancel(enableCancel: enableCancel, enableCancelOnEscape: enableCancel, enableCancelOnPressed: enableCancel);
+
+ SelectedOption = Options.First();
}
}

MODIFY
WalletWasabi.Fluent/Views/AddWallet/AddWalletPageView.axaml
WalletWasabi.Fluent/Views/AddWallet/AddWalletPageView.axaml
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:WalletWasabi.Fluent.ViewModels.AddWallet"
xmlns:c="using:WalletWasabi.Fluent.Controls"
+ xmlns:conv="using:WalletWasabi.Fluent.Converters"
mc:Ignorable="d" d:DesignWidth="428" d:DesignHeight="371"
x:DataType="vm:AddWalletPageViewModel"
x:CompileBindings="True"
<c:ContentArea Title="{Binding Title}"
EnableCancel="{Binding EnableCancel}"
EnableBack="{Binding EnableBack}"
- IsBusy="{Binding IsBusy}">
- <WrapPanel Orientation="Horizontal" Margin="0 0 0 20" HorizontalAlignment="Center">
+ IsBusy="{Binding IsBusy}"
+ EnableNext="True"
+ NextContent="Continue">
+ <ListBox Items="{Binding Options}" SelectedItem="{Binding SelectedOption}" Background="Transparent">
+ <ListBox.Styles>
+ <Style Selector="ListBoxItem">
+ <Setter Property="Cursor" Value="Hand" />
+ <Setter Property="Padding" Value="0 12 0 12"/>
+ </Style>
+ <Style Selector="ListBoxItem /template/ ContentPresenter#PART_ContentPresenter">
+ <Setter Property="Background" Value="Transparent" />
+ </Style>
+
+ <Style Selector="ListBoxItem:selected /template/ ContentPresenter#PART_ContentPresenter, ListBoxItem:pointerover /template/ ContentPresenter#PART_ContentPresenter">
+ <Setter Property="Background" Value="Transparent" />
+ </Style>
+ <Style Selector="ListBoxItem:selected Border#PART_DecorationBorderHover, ListBoxItem:selected Border#PART_DecorationBorderUnselected">
+ <Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColor}" />
+ </Style>
+
+ <Style Selector="ListBoxItem Border#PART_MainContentBorder">
+ <Setter Property="Padding" Value="12 25 12 25" />
+ <Setter Property="CornerRadius" Value="4" />
+ </Style>
+
+ <Style Selector="ListBoxItem Border#PART_DecorationBorderUnselected">
+ <Setter Property="Padding" Value="12 25 12 25" />
+ <Setter Property="CornerRadius" Value="4" />
+ <Setter Property="Margin" Value="5" />
+ <Setter Property="BorderBrush" Value="#14FFFFFF" />
+ <Setter Property="BorderThickness" Value="1" />
+ <Setter Property="Background" Value="{StaticResource OptimizePrivacyOptionSelectedColor}" />
+ <Setter Property="BoxShadow" Value="{StaticResource OptimizePrivacyOptionBoxShadow1}" />
+ </Style>
+
+ <Style Selector="ListBoxItem Border#PART_DecorationBorderHover">
+ <Setter Property="Padding" Value="12 25 12 25" />
+ <Setter Property="CornerRadius" Value="4" />
+ <Setter Property="Margin" Value="5" />
+ <Setter Property="BorderBrush" Value="#2AFFFFFF" />
+ <Setter Property="BorderThickness" Value="1" />
+ <Setter Property="Background" Value="{StaticResource OptimizePrivacyOptionSelectedColor}" />
+ <Setter Property="BoxShadow" Value="{StaticResource OptimizePrivacyOptionBoxShadow2}" />
+
+ <Setter Property="Opacity" Value="0" />
+ </Style>
+
+ <Style Selector="ListBoxItem:pointerover Border#PART_DecorationBorderHover">
+ <Setter Property="Opacity" Value="1" />
+ </Style>
+ </ListBox.Styles>
+ <ListBox.ItemsPanel>
+ <ItemsPanelTemplate>
+ <WrapPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" />
+ </ItemsPanelTemplate>
+ </ListBox.ItemsPanel>
+ <ListBox.DataTemplates>
+ <DataTemplate>
+ <c:SuggestionItem>
+ <StackPanel Spacing="20" Width="150" Height="210">
+ <TextBlock Text="{Binding Title}" TextWrapping="Wrap" TextAlignment="Center" Height="34"/>
+ <Viewbox HorizontalAlignment="Center" Height="70">
+ <PathIcon Data="{Binding IconName, Converter={x:Static conv:ResolveApplicationResourceConverter.Instance}}"
+ Foreground="{StaticResource SystemAccentColor}"/>
+ </Viewbox>
+ <TextBlock Text="{Binding Description}"
+ TextWrapping="Wrap"
+ TextAlignment="Center"/>
+ </StackPanel>
+ </c:SuggestionItem>
+ </DataTemplate>
+ </ListBox.DataTemplates>
+ </ListBox>
+
+
+
+
+ <!--<WrapPanel Orientation="Horizontal" Margin="0 0 0 20" HorizontalAlignment="Center">
<WrapPanel.Styles>
<Style Selector="c|TileButton">
<Setter Property="Margin" Value="4"/>
<c:TileButton Text="Recover a wallet"
Icon="{StaticResource recover_arrow_right_regular}"
Command="{Binding RecoverWalletCommand}" />
- </WrapPanel>
+ </WrapPanel>-->
</c:ContentArea>
</UserControl>

AddWalletView rework