Add dynamic behavior.
MODIFY
WalletWasabi.Gui/App.xaml
WalletWasabi.Gui/App.xaml
<StyleInclude Source="resm:WalletWasabi.Gui.Controls.TogglePasswordBox.xaml?assembly=WalletWasabi.Gui" />
<StyleInclude Source="resm:WalletWasabi.Gui.Controls.MultiTextBox.xaml?assembly=WalletWasabi.Gui" />
<StyleInclude Source="resm:WalletWasabi.Gui.Controls.EditableTextBlock.xaml?assembly=WalletWasabi.Gui" />
+ <StyleInclude Source="resm:WalletWasabi.Gui.Controls.Shields.xaml?assembly=WalletWasabi.Gui" />
</Application.Styles>
<Application.DataTemplates>
<DataTemplate DataType="Views:MainView">

MODIFY
WalletWasabi.Gui/Config.cs
WalletWasabi.Gui/Config.cs
@@ -80,9 +80,8 @@ namespace WalletWasabi.Gui
get => _mixUntilAnonymitySet;
internal set
{
- if (_mixUntilAnonymitySet != value)
+ if (RaiseAndSetIfChanged(ref _mixUntilAnonymitySet, value))
{
- _mixUntilAnonymitySet = value;
if (ServiceConfiguration != default)
{
ServiceConfiguration.MixUntilAnonymitySet = value;

ADD
WalletWasabi.Gui/Controls/Shields.cs
+using Avalonia;
+using Avalonia.Controls.Primitives;
+using Avalonia.Data;
+using Avalonia.Styling;
+using ReactiveUI;
+using System;
+using System.Reactive.Linq;
+using WalletWasabi.Gui.Models;
+
+namespace WalletWasabi.Gui.Controls
+{
+ public class Shields : TemplatedControl, IStyleable
+ {
+ Type IStyleable.StyleKey => typeof(Shields);
+
+ public static readonly StyledProperty<bool> IsPrivacyCriticalVisibleProperty =
+ AvaloniaProperty.Register<Shields, bool>(nameof(IsPrivacyCriticalVisible), defaultBindingMode: BindingMode.OneWay);
+
+ public bool IsPrivacyCriticalVisible
+ {
+ get => GetValue(IsPrivacyCriticalVisibleProperty);
+ set => SetValue(IsPrivacyCriticalVisibleProperty, value);
+ }
+
+ public static readonly StyledProperty<bool> IsPrivacySomeVisibleProperty =
+ AvaloniaProperty.Register<Shields, bool>(nameof(IsPrivacySomeVisible), defaultBindingMode: BindingMode.OneWay);
+
+ public bool IsPrivacySomeVisible
+ {
+ get => GetValue(IsPrivacySomeVisibleProperty);
+ set => SetValue(IsPrivacySomeVisibleProperty, value);
+ }
+
+ public static readonly StyledProperty<bool> IsPrivacyFineVisibleProperty =
+ AvaloniaProperty.Register<Shields, bool>(nameof(IsPrivacyFineVisible), defaultBindingMode: BindingMode.OneWay);
+
+ public bool IsPrivacyFineVisible
+ {
+ get => GetValue(IsPrivacyFineVisibleProperty);
+ set => SetValue(IsPrivacyFineVisibleProperty, value);
+ }
+
+ public static readonly StyledProperty<bool> IsPrivacyStrongVisibleProperty =
+ AvaloniaProperty.Register<Shields, bool>(nameof(IsPrivacyStrongVisible), defaultBindingMode: BindingMode.OneWay);
+
+ public bool IsPrivacyStrongVisible
+ {
+ get => GetValue(IsPrivacyStrongVisibleProperty);
+ set => SetValue(IsPrivacyStrongVisibleProperty, value);
+ }
+
+ public static readonly StyledProperty<bool> IsPrivacySaiyanVisibleProperty =
+ AvaloniaProperty.Register<Shields, bool>(nameof(IsPrivacySaiyanVisible), defaultBindingMode: BindingMode.OneWay);
+
+ public bool IsPrivacySaiyanVisible
+ {
+ get => GetValue(IsPrivacySaiyanVisibleProperty);
+ set => SetValue(IsPrivacySaiyanVisibleProperty, value);
+ }
+
+ public static readonly StyledProperty<ShieldState> ShieldStateProperty =
+ AvaloniaProperty.Register<Shields, ShieldState>(nameof(ShieldState), defaultBindingMode: BindingMode.OneWay);
+
+ public ShieldState ShieldState
+ {
+ get => GetValue(ShieldStateProperty);
+ set => SetValue(ShieldStateProperty, value);
+ }
+
+ public Shields()
+ {
+ this.GetObservable(ShieldStateProperty)
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .Subscribe(x => ShieldState = x);
+
+ this.WhenAnyValue(x => x.ShieldState)
+ .Where(x => x != null)
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .Subscribe(st =>
+ {
+ IsPrivacyCriticalVisible = st.IsPrivacyCriticalVisible;
+ IsPrivacySomeVisible = st.IsPrivacySomeVisible;
+ IsPrivacyFineVisible = st.IsPrivacyFineVisible;
+ IsPrivacyStrongVisible = st.IsPrivacyStrongVisible;
+ IsPrivacySaiyanVisible = st.IsPrivacySaiyanVisible;
+ }
+ );
+ }
+ }
+}

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/CoinListView.xaml
WalletWasabi.Gui/Controls/WalletExplorer/CoinListView.xaml
<StackPanel Margin="0 10 0 0" Spacing="10" DockPanel.Dock="Bottom" Orientation="Horizontal">
<StackPanel Spacing="5" Orientation="Horizontal" IsVisible="{Binding SelectAllPrivateVisible}">
<CheckBox Content="Select" IsThreeState="True" IsChecked="{Binding SelectPrivateCheckBoxState}" Command="{Binding SelectPrivateCheckBoxCommand}" />
- <DrawingPresenter Height="16" Width="16" VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource PrivacyStrong}" />
+ <controls:Shields ShieldState ="{Binding SelectAllPrivateShieldState}" />
<TextBlock Text="Coins" />
</StackPanel>
<StackPanel Spacing="5" Orientation="Horizontal" IsVisible="{Binding SelectAllNonPrivateVisible}">
<CheckBox Content="Select" IsThreeState="True" IsChecked="{Binding SelectNonPrivateCheckBoxState}" Command="{Binding SelectNonPrivateCheckBoxCommand}" />
- <DrawingPresenter Height="16" Width="16" VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource PrivacyCritical}" />
- <DrawingPresenter Height="16" Width="16" VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource PrivacySome}" />
- <DrawingPresenter Height="16" Width="16" VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource PrivacyFine}" />
+ <controls:Shields ShieldState ="{Binding SelectAllNonPrivateShieldState}" />
<TextBlock Text="Coins" />
</StackPanel>
<CheckBox Content="Select All" IsThreeState="True" IsChecked="{Binding SelectAllCheckBoxState}" Command="{Binding SelectAllCheckBoxCommand}" />

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/CoinListViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/CoinListViewModel.cs
@@ -43,6 +43,8 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
private bool _labelExposeCommonOwnershipWarning;
private bool _selectAllNonPrivateVisible;
private bool _selectAllPrivateVisible;
+ private ShieldState _selectAllPrivateShieldState;
+ private ShieldState _selectAllNonPrivateShieldState;
public Global Global { get; }
public CoinListContainerType CoinListContainerType { get; }
@@ -185,6 +187,18 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
set => this.RaiseAndSetIfChanged(ref _selectAllPrivateVisible, value);
}
+ public ShieldState SelectAllPrivateShieldState
+ {
+ get => _selectAllPrivateShieldState;
+ set => this.RaiseAndSetIfChanged(ref _selectAllPrivateShieldState, value);
+ }
+
+ public ShieldState SelectAllNonPrivateShieldState
+ {
+ get => _selectAllNonPrivateShieldState;
+ set => this.RaiseAndSetIfChanged(ref _selectAllNonPrivateShieldState, value);
+ }
+
private bool? GetCheckBoxesSelectedState(Func<CoinViewModel, bool> coinFilterPredicate)
{
var coins = Coins.Where(coinFilterPredicate).ToArray();
@@ -415,10 +429,37 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
})
.DisposeWith(Disposables);
+ Global.Config.WhenAnyValue(x => x.MixUntilAnonymitySet)
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .Subscribe(x => RefreshSelectCheckBoxesShields(x))
+ .DisposeWith(Disposables);
+
SetSelections();
SetCoinJoinStatusWidth();
}
+ private void RefreshSelectCheckBoxesShields(int mixUntilAnonymitySet)
+ {
+ var isCriticalPrivate = false;
+ var isSomePrivate = mixUntilAnonymitySet <= Global.Config.PrivacyLevelSome;
+ var isFinePrivate = mixUntilAnonymitySet <= Global.Config.PrivacyLevelFine;
+ var isStrongPrivate = mixUntilAnonymitySet <= Global.Config.PrivacyLevelStrong;
+
+ SelectAllNonPrivateShieldState = new ShieldState(
+ !isCriticalPrivate,
+ !isSomePrivate,
+ !isFinePrivate,
+ !isStrongPrivate
+ );
+
+ SelectAllPrivateShieldState = new ShieldState(
+ isCriticalPrivate,
+ isSomePrivate,
+ isFinePrivate,
+ isStrongPrivate
+ );
+ }
+
private void ClearRootList()
{
IEnumerable<CoinViewModel> toRemoves = RootList?.Items?.ToList() ?? Enumerable.Empty<CoinViewModel>(); // Clone so we can unsubscribe after clear.

ADD
WalletWasabi.Gui/Models/ShieldState.cs
+namespace WalletWasabi.Gui.Models
+{
+ public class ShieldState
+ {
+ public bool IsPrivacyCriticalVisible { get; }
+ public bool IsPrivacySomeVisible { get; }
+ public bool IsPrivacyFineVisible { get; }
+ public bool IsPrivacyStrongVisible { get; }
+ public bool IsPrivacySaiyanVisible { get; }
+
+ public ShieldState(bool isPrivacyCriticalVisible, bool isPrivacySomeVisible, bool isPrivacyFineVisible, bool isPrivacyStrongVisible, bool isPrivacySaiyanVisible = false)
+ {
+ IsPrivacyCriticalVisible = isPrivacyCriticalVisible;
+ IsPrivacySomeVisible = isPrivacySomeVisible;
+ IsPrivacyFineVisible = isPrivacyFineVisible;
+ IsPrivacyStrongVisible = isPrivacyStrongVisible;
+ IsPrivacySaiyanVisible = isPrivacySaiyanVisible;
+ }
+ }
+}

Add dynamic behavior.