Make label suggestions action dependent
MODIFY
WalletWasabi.Fluent/Helpers/WalletHelpers.cs
WalletWasabi.Fluent/Helpers/WalletHelpers.cs
@@ -22,22 +22,14 @@ public static class WalletHelpers
return keyManager.IsHardwareWallet ? WalletType.Hardware : WalletType.Normal;
}
- public static IEnumerable<string> GetLabels()
- {
- // Don't refresh wallet list as it may be slow.
- IEnumerable<SmartLabel> labels = Services.WalletManager.GetWallets(refreshWalletList: false)
+ public static IEnumerable<SmartLabel> GetTransactionLabels() => Services.BitcoinStore.TransactionStore.GetLabels();
+
+ public static IEnumerable<SmartLabel> GetAddressLabels() =>
+ Services.WalletManager
+ .GetWallets(refreshWalletList: false) // Don't refresh wallet list as it may be slow.
.Select(x => x.KeyManager)
.SelectMany(x => x.GetLabels());
- var txStore = Services.BitcoinStore.TransactionStore;
- if (txStore is { })
- {
- labels = labels.Concat(txStore.GetLabels());
- }
-
- return labels.SelectMany(x => x.Labels);
- }
-
public static (ErrorSeverity Severity, string Message)? ValidateWalletName(string walletName)
{
string walletFilePath = Path.Combine(Services.WalletManager.WalletDirectories.WalletsDir, $"{walletName}.json");

MODIFY
WalletWasabi.Fluent/ViewModels/Dialogs/LabelEntryDialogViewModel.cs
WalletWasabi.Fluent/ViewModels/Dialogs/LabelEntryDialogViewModel.cs
@@ -21,7 +21,7 @@ public partial class LabelEntryDialogViewModel : DialogViewModelBase<SmartLabel?
public LabelEntryDialogViewModel(Wallet wallet, TransactionInfo info)
{
_wallet = wallet;
- SuggestionLabels = new SuggestionLabelsViewModel(3)
+ SuggestionLabels = new SuggestionLabelsViewModel(Intent.Send, 3)
{
Labels = { info.UserLabels.Labels }
};

ADD
WalletWasabi.Fluent/ViewModels/Wallets/Labels/Intent.cs
+namespace WalletWasabi.Fluent.ViewModels.Wallets.Labels;
+
+public enum Intent
+{
+ Send,
+ Receive
+}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Labels/SuggestionLabelViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Labels/SuggestionLabelViewModel.cs
@@ -2,13 +2,13 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Labels;
public class SuggestionLabelViewModel : ViewModelBase
{
- public SuggestionLabelViewModel(string label, int count)
+ public SuggestionLabelViewModel(string label, int score)
{
Label = label;
- Count = count;
+ Score = score;
}
public string Label { get; }
- public int Count { get; }
+ public int Score { get; }
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Labels/SuggestionLabelsViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Labels/SuggestionLabelsViewModel.cs
@@ -19,8 +19,9 @@ public partial class SuggestionLabelsViewModel : ViewModelBase
[AutoNotify] private bool _isCurrentTextValid;
- public SuggestionLabelsViewModel(int topSuggestionsCount, IEnumerable<string>? labels = null)
+ public SuggestionLabelsViewModel(Intent intent, int topSuggestionsCount, IEnumerable<string>? labels = null)
{
+ Intent = intent;
_sourceLabels = new SourceList<SuggestionLabelViewModel>();
_topSuggestions = new ObservableCollectionExtended<string>();
_suggestions = new ObservableCollectionExtended<string>();
@@ -36,8 +37,29 @@ public partial class SuggestionLabelsViewModel : ViewModelBase
public ObservableCollection<string> Labels => _labels;
+ public Intent Intent { get; }
+
public void UpdateLabels()
{
+ var labelPool = new Dictionary<string, int>(); // int: score.
+ foreach (var label in WalletHelpers.GetAddressLabels().SelectMany(x => x.Labels))
+ {
+ var score = Intent == Intent.Receive ? 10 : 1;
+ if (!labelPool.TryAdd(label, score))
+ {
+ labelPool[label] += score;
+ }
+ }
+
+ foreach (var label in WalletHelpers.GetTransactionLabels().SelectMany(x => x.Labels))
+ {
+ var score = Intent == Intent.Send ? 10 : 1;
+ if (!labelPool.TryAdd(label, score))
+ {
+ labelPool[label] += score;
+ }
+ }
+
var unwantedLabelSuggestions = new[]
{
"test", // Often people use the string "test" as a label. It obviously cannot be a real label, just a test label.
@@ -46,24 +68,24 @@ public partial class SuggestionLabelsViewModel : ViewModelBase
"zerolink dequeued change" // Obsolated autogenerated label from old WW1 versions.
};
- var labels = WalletHelpers
- .GetLabels()
+ var labels = labelPool
.Where(x =>
- !unwantedLabelSuggestions.Any(y => y.Equals(x, StringComparison.OrdinalIgnoreCase))
- && !x.StartsWith("change of (", StringComparison.OrdinalIgnoreCase)); // An obsolated autogenerated label pattern was from old WW1 versions starting with "change of (".
+ !unwantedLabelSuggestions.Any(y => y.Equals(x.Key, StringComparison.OrdinalIgnoreCase))
+ && !x.Key.StartsWith("change of (", StringComparison.OrdinalIgnoreCase)); // An obsolated autogenerated label pattern was from old WW1 versions starting with "change of (".
- var mostUsedLabels = labels.GroupBy(x => x)
+ var mostUsedLabels = labels
+ .GroupBy(x => x.Key)
.Select(x => new
{
Label = x.Key,
- Count = x.Count()
+ Score = x.Sum(y => y.Value)
})
- .OrderByDescending(x => x.Count)
+ .OrderByDescending(x => x.Score)
.ToList();
_sourceLabels.Clear();
_sourceLabels.AddRange(
- mostUsedLabels.Select(x => new SuggestionLabelViewModel(x.Label, x.Count)));
+ mostUsedLabels.Select(x => new SuggestionLabelViewModel(x.Label, x.Score)));
}
private void CreateSuggestions(int topSuggestionsCount)
@@ -75,7 +97,7 @@ public partial class SuggestionLabelsViewModel : ViewModelBase
_sourceLabels
.Connect()
.Filter(suggestionLabelsFilter)
- .Sort(SortExpressionComparer<SuggestionLabelViewModel>.Descending(x => x.Count).ThenByAscending(x => x.Label))
+ .Sort(SortExpressionComparer<SuggestionLabelViewModel>.Descending(x => x.Score).ThenByAscending(x => x.Label))
.Top(topSuggestionsCount)
.Transform(x => x.Label)
.ObserveOn(RxApp.MainThreadScheduler)
@@ -85,7 +107,7 @@ public partial class SuggestionLabelsViewModel : ViewModelBase
_sourceLabels
.Connect()
.Filter(suggestionLabelsFilter)
- .Sort(SortExpressionComparer<SuggestionLabelViewModel>.Descending(x => x.Count).ThenByAscending(x => x.Label))
+ .Sort(SortExpressionComparer<SuggestionLabelViewModel>.Descending(x => x.Score).ThenByAscending(x => x.Label))
.Transform(x => x.Label)
.ObserveOn(RxApp.MainThreadScheduler)
.Bind(_suggestions)

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Receive/AddressLabelEditViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Receive/AddressLabelEditViewModel.cs
@@ -14,7 +14,7 @@ public partial class AddressLabelEditViewModel : RoutableViewModel
public AddressLabelEditViewModel(ReceiveAddressesViewModel owner, HdPubKey hdPubKey, KeyManager keyManager)
{
- SuggestionLabels = new SuggestionLabelsViewModel(3, hdPubKey.Label);
+ SuggestionLabels = new SuggestionLabelsViewModel(Intent.Receive, 3, hdPubKey.Label);
SetupCancel(enableCancel: true, enableCancelOnEscape: true, enableCancelOnPressed: true);

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Receive/ReceiveViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Receive/ReceiveViewModel.cs
@@ -31,7 +31,7 @@ public partial class ReceiveViewModel : RoutableViewModel
EnableBack = false;
- SuggestionLabels = new SuggestionLabelsViewModel(3);
+ SuggestionLabels = new SuggestionLabelsViewModel(Intent.Receive, 3);
var nextCommandCanExecute =
SuggestionLabels

Make label suggestions action dependent