Integrate dialog in TransactionPreview
MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Advanced/WalletCoins/WalletCoinsViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Advanced/WalletCoins/WalletCoinsViewModel.cs
@@ -131,7 +131,7 @@ public partial class WalletCoinsViewModel : RoutableViewModel
IsFixedAmount = true,
};
- Navigate().To(new TransactionPreviewViewModel(wallet, info));
+ Navigate().To(new TransactionPreviewViewModel(wallet, _walletVm, info));
}
private FlatTreeDataGridSource<WalletCoinViewModel> CreateGridSource(IEnumerable<WalletCoinViewModel> coins)

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendViewModel.cs
@@ -11,21 +11,18 @@ using ReactiveUI;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Fluent.Models;
using WalletWasabi.Fluent.Validation;
+using WalletWasabi.Fluent.ViewModels.Dialogs;
using WalletWasabi.Fluent.ViewModels.Navigation;
+using WalletWasabi.Fluent.ViewModels.Wallets.Home.Tiles;
using WalletWasabi.Logging;
using WalletWasabi.Models;
using WalletWasabi.Tor.Http;
using WalletWasabi.Tor.Socks5.Pool.Circuits;
using WalletWasabi.Userfacing;
+using WalletWasabi.WabiSabi.Client;
using WalletWasabi.Wallets;
using WalletWasabi.WebClients.PayJoin;
using Constants = WalletWasabi.Helpers.Constants;
-using WalletWasabi.Fluent.ViewModels.Dialogs;
-using WalletWasabi.WabiSabi.Client;
-using WalletWasabi.Fluent.ViewModels.Wallets.Home.Tiles;
-using System.Reactive;
-using System.Collections.ObjectModel;
-using WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryItems;
namespace WalletWasabi.Fluent.ViewModels.Wallets.Send;
@@ -103,7 +100,8 @@ public partial class SendViewModel : RoutableViewModel
return allFilled && !hasError;
});
- NextCommand = ReactiveCommand.CreateFromTask(async () =>
+ NextCommand = ReactiveCommand.CreateFromTask(
+ async () =>
{
var labelDialog = new LabelEntryDialogViewModel(_wallet, _parsedLabel);
var result = await NavigateDialogAsync(labelDialog, NavigationTarget.CompactDialogScreen);
@@ -120,8 +118,9 @@ public partial class SendViewModel : RoutableViewModel
IsFixedAmount = _isFixedAmount
};
- Navigate().To(new TransactionPreviewViewModel(_wallet, transactionInfo));
- }, nextCommandCanExecute);
+ Navigate().To(new TransactionPreviewViewModel(_wallet, walletVm, transactionInfo));
+ },
+ nextCommandCanExecute);
this.WhenAnyValue(x => x.ConversionReversed)
.Skip(1)

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/TransactionPreviewViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/TransactionPreviewViewModel.cs
@@ -37,7 +37,7 @@ public partial class TransactionPreviewViewModel : RoutableViewModel
[AutoNotify] private TransactionSummaryViewModel? _displayedTransactionSummary;
[AutoNotify] private bool _canUndo;
- public TransactionPreviewViewModel(Wallet wallet, TransactionInfo info)
+ public TransactionPreviewViewModel(Wallet wallet, WalletViewModel walletViewModel, TransactionInfo info)
{
_undoHistory = new();
_wallet = wallet;
@@ -46,8 +46,8 @@ public partial class TransactionPreviewViewModel : RoutableViewModel
_cancellationTokenSource = new CancellationTokenSource();
PrivacySuggestions = new PrivacySuggestionsFlyoutViewModel();
- CurrentTransactionSummary = new TransactionSummaryViewModel(this, _wallet, _info);
- PreviewTransactionSummary = new TransactionSummaryViewModel(this, _wallet, _info, true);
+ CurrentTransactionSummary = new TransactionSummaryViewModel(this, walletViewModel, _wallet, _info);
+ PreviewTransactionSummary = new TransactionSummaryViewModel(this, walletViewModel, _wallet, _info, true);
TransactionSummaries = new List<TransactionSummaryViewModel>
{
@@ -132,6 +132,8 @@ public partial class TransactionPreviewViewModel : RoutableViewModel
});
ChangePocketCommand = ReactiveCommand.CreateFromTask(OnChangePocketsAsync);
+
+ EnableCoinControlCommand = ReactiveCommand.Create(() => CurrentTransactionSummary.IsCoinControlVisible = true);
}
public TransactionSummaryViewModel CurrentTransactionSummary { get; }
@@ -149,6 +151,7 @@ public partial class TransactionPreviewViewModel : RoutableViewModel
public ICommand ChangePocketCommand { get; }
public ICommand UndoCommand { get; }
+ public ICommand EnableCoinControlCommand { get; }
private async Task OnExportPsbtAsync()
{
@@ -369,14 +372,15 @@ public partial class TransactionPreviewViewModel : RoutableViewModel
_info.MinimumRequiredAmount = minimumRequiredAmount;
var selectPocketsDialog =
- await NavigateDialogAsync(new PrivacyControlViewModel(_wallet, _info, usedCoins: Transaction?.SpentCoins, isSilent: doSilentPocketSelection));
+ await NavigateDialogAsync(new PrivacyControlViewModel(_wallet, _info, Transaction?.SpentCoins, doSilentPocketSelection));
if (selectPocketsDialog.Kind == DialogResultKind.Normal && selectPocketsDialog.Result is { })
{
_info.Coins = selectPocketsDialog.Result;
return true;
}
- else if (selectPocketsDialog.Kind != DialogResultKind.Normal)
+
+ if (selectPocketsDialog.Kind != DialogResultKind.Normal)
{
return false;
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/TransactionSummaryViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/TransactionSummaryViewModel.cs
+using System.Collections.Generic;
using System.Linq;
-using NBitcoin;
+using System.Reactive;
+using System.Reactive.Linq;
using ReactiveUI;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Blockchain.TransactionBuilding;
+using WalletWasabi.Blockchain.TransactionOutputs;
using WalletWasabi.Fluent.Extensions;
using WalletWasabi.Fluent.Helpers;
+using WalletWasabi.Fluent.ViewModels.CoinControl;
+using WalletWasabi.Fluent.ViewModels.Dialogs.Base;
+using WalletWasabi.Fluent.ViewModels.Navigation;
using WalletWasabi.Wallets;
namespace WalletWasabi.Fluent.ViewModels.Wallets.Send;
@@ -23,8 +29,9 @@ public partial class TransactionSummaryViewModel : ViewModelBase
[AutoNotify] private bool _isOtherPocketSelectionPossible;
[AutoNotify] private SmartLabel _labels = SmartLabel.Empty;
[AutoNotify] private SmartLabel _recipient = SmartLabel.Empty;
+ [AutoNotify] private bool _isCoinControlVisible;
- public TransactionSummaryViewModel(TransactionPreviewViewModel parent, Wallet wallet, TransactionInfo info, bool isPreview = false)
+ public TransactionSummaryViewModel(TransactionPreviewViewModel parent, WalletViewModel walletViewModel, Wallet wallet, TransactionInfo info, bool isPreview = false)
{
Parent = parent;
_wallet = wallet;
@@ -36,8 +43,39 @@ public partial class TransactionSummaryViewModel : ViewModelBase
AddressText = info.Destination.ToString();
PayJoinUrl = info.PayJoinClient?.PaymentUrl.AbsoluteUri;
IsPayJoin = PayJoinUrl is not null;
+
+ var selectCoinsInteraction = SelectCoinsInteraction(walletViewModel);
+
+ SelectCoinsCommand = ReactiveCommand.CreateFromObservable(() => selectCoinsInteraction.Handle(info));
+ SelectCoinsCommand.Do(
+ list =>
+ {
+ info.Coins = list;
+
+ // UpdateTransactionSummary here, but how??
+ }).Subscribe();
}
+ private static Interaction<TransactionInfo, List<SmartCoin>> SelectCoinsInteraction(WalletViewModel walletViewModel)
+ {
+ var selectCoinsInteraction = new Interaction<TransactionInfo, List<SmartCoin>>();
+ selectCoinsInteraction.RegisterHandler(
+ async context =>
+ {
+ var navigateDialog = await MainViewModel.Instance.DialogScreen.NavigateDialogAsync(new SelectCoinsDialogViewModel(walletViewModel));
+
+ if (navigateDialog.Kind == DialogResultKind.Normal)
+ {
+ context.SetOutput(navigateDialog.Result!.ToList());
+ }
+
+ context.SetOutput(new List<SmartCoin>());
+ });
+ return selectCoinsInteraction;
+ }
+
+ public ReactiveCommand<Unit, List<SmartCoin>> SelectCoinsCommand { get; }
+
public TransactionPreviewViewModel Parent { get; }
public bool IsPreview { get; }

MODIFY
WalletWasabi.Fluent/Views/Wallets/Send/TransactionPreviewView.axaml
WalletWasabi.Fluent/Views/Wallets/Send/TransactionPreviewView.axaml
EnableSkip="{Binding PreferPsbtWorkflow}" SkipContent="Send Now"
IsBusy="{Binding IsBusy}"
ScrollViewer.VerticalScrollBarVisibility="Auto">
+
+ <i:Interaction.Behaviors>
+ <behaviors:ExecuteCommandOnKeyDownBehavior Key="LeftAlt" Command="{Binding EnableCoinControlCommand}" />
+ </i:Interaction.Behaviors>
+
<c:ContentArea.Title>
<DockPanel>
<TextBlock Text="Preview Transaction" />

Integrate dialog in TransactionPreview