Skip to content

Commit

Permalink
🎨 Show service connection indicator in the settings UI.
Browse files Browse the repository at this point in the history
  • Loading branch information
hexawyz committed Apr 30, 2024
1 parent 335d226 commit 9387f50
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 10 deletions.
20 changes: 20 additions & 0 deletions Exo.Settings.Ui/BooleanTemplateSelector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;

namespace Exo.Settings.Ui;

internal sealed class BooleanTemplateSelector : DataTemplateSelector
{
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public DataTemplate NullTemplate { get; set; }
public DataTemplate FalseTemplate { get; set; }
public DataTemplate TrueTemplate { get; set; }
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

protected override DataTemplate SelectTemplateCore(object item)
=> item is bool b ?
b ?
TrueTemplate :
FalseTemplate :
NullTemplate;
}
1 change: 1 addition & 0 deletions Exo.Settings.Ui/ChangedProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ internal static class ChangedProperty
public static readonly PropertyChangedEventArgs IsChanged = new(nameof(IsChanged));
public static readonly PropertyChangedEventArgs IsNotBusy = new(nameof(IsNotBusy));
public static readonly PropertyChangedEventArgs IsReady = new(nameof(IsReady));
public static readonly PropertyChangedEventArgs IsConnected = new(nameof(IsConnected));
public static readonly PropertyChangedEventArgs Properties = new(nameof(Properties));
public static readonly PropertyChangedEventArgs CurrentEffect = new(nameof(CurrentEffect));
public static readonly PropertyChangedEventArgs FriendlyName = new(nameof(FriendlyName));
Expand Down
70 changes: 65 additions & 5 deletions Exo.Settings.Ui/RootPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Exo.Settings.Ui"
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="{x:Bind ViewModel}"
mc:Ignorable="d">

<Grid>
Expand Down Expand Up @@ -52,14 +54,67 @@
AutomationProperties.AutomationId="AppTitleBar"
Canvas.ZIndex="1"
IsHitTestVisible="True">
<StackPanel VerticalAlignment="Center" Orientation="Horizontal">
<Grid VerticalAlignment="Center" Margin="0,0,146,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
x:Name="AppTitle"
Margin="12,0,0,0"
VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind AppTitleText}" />
</StackPanel>
<StackPanel Grid.Column="2" VerticalAlignment="Center" Orientation="Horizontal">
<!--<Grid Grid.Column="2" Margin="12,0,0,0">
<FontIcon Glyph="&#xF136;" Foreground="White" />
<FontIcon Glyph="&#xF137;" Foreground="Red" />
<FontIcon Glyph="&#xF13D;" Foreground="White" />
</Grid>
<Grid Grid.Column="2" Margin="12,0,0,0">
<FontIcon Glyph="&#xF136;" Foreground="White" />
<FontIcon Glyph="&#xF137;" Foreground="Lime" />
<FontIcon Glyph="&#xF13E;" Foreground="White" />
</Grid>
<Grid Grid.Column="2" Margin="12,0,0,0">
<FontIcon Glyph="&#xF385;" Foreground="Gray" />
<FontIcon Glyph="&#xE871;" Foreground="Red" />
</Grid>
<Grid Grid.Column="2" Margin="12,0,0,0">
<FontIcon Glyph="&#xF385;" Foreground="White" />
<FontIcon Glyph="&#xEB5B;" Foreground="Red" />
</Grid>
<Grid Grid.Column="2" Margin="12,0,0,0">
<FontIcon Glyph="&#xF385;" Foreground="Gray" />
<FontIcon Glyph="&#xED2E;" Foreground="Red" />
</Grid>
<Grid Grid.Column="2" Margin="12,0,0,0">
<FontIcon Glyph="&#xF385;" Foreground="Gray" />
<FontIcon Glyph="&#xF386;" Foreground="Lime" />
</Grid>
<Grid Grid.Column="2" Margin="12,0,0,0">
<FontIcon Glyph="&#xF385;" Foreground="Gray" />
<FontIcon Glyph="&#xEA81;" Foreground="Lime" />
</Grid>-->
<Grid Grid.Column="2" Margin="12,0,0,0">
<Grid.Resources>
<SolidColorBrush x:Key="DisconnectedColorBrush">Red</SolidColorBrush>
<SolidColorBrush x:Key="ConnectedColorBrush">Lime</SolidColorBrush>
<converters:BoolToObjectConverter x:Key="BooleanToColorConverter" TrueValue="{StaticResource ConnectedColorBrush}" FalseValue="{StaticResource DisconnectedColorBrush}" />
<converters:BoolToObjectConverter x:Key="BooleanToConnectionStatusTextConverter">
<converters:BoolToObjectConverter.FalseValue>Service Disconnected</converters:BoolToObjectConverter.FalseValue>
<converters:BoolToObjectConverter.TrueValue>Service Connected</converters:BoolToObjectConverter.TrueValue>
</converters:BoolToObjectConverter>
</Grid.Resources>
<ToolTipService.ToolTip>
<ToolTip Content="{Binding IsConnected, Mode=OneWay, Converter={StaticResource BooleanToConnectionStatusTextConverter}}" />
</ToolTipService.ToolTip>
<FontIcon Glyph="&#xF385;" Foreground="Gray" />
<FontIcon Glyph="&#xEA81;" Foreground="{Binding IsConnected, Mode=OneWay, Converter={StaticResource BooleanToColorConverter}}" />
</Grid>
</StackPanel>
</Grid>
</Border>

<NavigationView
Expand All @@ -73,8 +128,13 @@
IsBackEnabled="{x:Bind ContentFrame.CanGoBack, Mode=OneWay}"
DisplayModeChanged="OnPaneDisplayModeChanged"
ItemInvoked="OnNavigationItemInvoked"
BackRequested="OnNavigationBackRequested"
DataContext="{x:Bind ViewModel}">
BackRequested="OnNavigationBackRequested">
<NavigationView.Resources>
<Thickness x:Key="NavigationViewContentMargin">0,48,0,0</Thickness>
<Thickness x:Key="NavigationViewMinimalContentMargin">0,48,0,0</Thickness>
<Thickness x:Key="NavigationViewContentGridBorderThickness">1,1,0,0</Thickness>
<CornerRadius x:Key="NavigationViewContentGridCornerRadius">8,0,0,0</CornerRadius>
</NavigationView.Resources>
<NavigationView.MenuItems>
<NavigationViewItem Content="Devices" Tag="Devices">
<NavigationViewItem.Icon>
Expand All @@ -88,7 +148,7 @@
</NavigationViewItem>
<NavigationViewItem Content="Sensors" Tag="Sensors">
<NavigationViewItem.Icon>
<FontIcon Glyph="&#xEC49;" />
<FontIcon Glyph="&#xE9D9;" />
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem Content="Custom Menu" Tag="CustomMenu">
Expand Down
2 changes: 1 addition & 1 deletion Exo.Settings.Ui/SensorsPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public SensorsPage()

protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.Icon = "\uEC49";
ViewModel.Icon = "\uE9D9";
ViewModel.Title = "Sensors";
}
}
14 changes: 12 additions & 2 deletions Exo.Settings.Ui/ViewModels/SettingsServiceConnectionManager.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using Exo.Ui;
using Exo.Ui;
using Exo.Contracts.Ui.Settings;
using Grpc.Net.Client;
using ProtoBuf.Grpc.Client;
using System.Runtime.ExceptionServices;
using System.ComponentModel;

namespace Exo.Settings.Ui.ViewModels;

internal sealed class SettingsServiceConnectionManager : ServiceConnectionManager
internal sealed class SettingsServiceConnectionManager : ServiceConnectionManager, INotifyPropertyChanged
{
private TaskCompletionSource<IDeviceService> _deviceServiceTaskCompletionSource;
private TaskCompletionSource<IMouseService> _mouseServiceTaskCompletionSource;
Expand All @@ -15,6 +16,11 @@ internal sealed class SettingsServiceConnectionManager : ServiceConnectionManage
private TaskCompletionSource<ISensorService> _sensorServiceTaskCompletionSource;
private TaskCompletionSource<IProgrammingService> _programmingServiceTaskCompletionSource;

public event PropertyChangedEventHandler? PropertyChanged;
private volatile bool _isConnected;

public bool IsConnected => _isConnected;

public SettingsServiceConnectionManager(string pipeName, int reconnectDelay) : base(pipeName, reconnectDelay)
{
_deviceServiceTaskCompletionSource = new();
Expand Down Expand Up @@ -45,22 +51,26 @@ public Task<IProgrammingService> GetProgrammingServiceAsync(CancellationToken ca

protected override void OnConnected(GrpcChannel channel)
{
_isConnected = true;
Connect(channel, _deviceServiceTaskCompletionSource);
Connect(channel, _mouseServiceTaskCompletionSource);
Connect(channel, _monitorServiceTaskCompletionSource);
Connect(channel, _lightingServiceTaskCompletionSource);
Connect(channel, _sensorServiceTaskCompletionSource);
Connect(channel, _programmingServiceTaskCompletionSource);
PropertyChanged?.Invoke(this, ChangedProperty.IsConnected);
}

protected override void OnDisconnected()
{
_isConnected = false;
Reset(ref _deviceServiceTaskCompletionSource);
Reset(ref _mouseServiceTaskCompletionSource);
Reset(ref _monitorServiceTaskCompletionSource);
Reset(ref _lightingServiceTaskCompletionSource);
Reset(ref _sensorServiceTaskCompletionSource);
Reset(ref _programmingServiceTaskCompletionSource);
PropertyChanged?.Invoke(this, ChangedProperty.IsConnected);
}

private static void Connect<T>(GrpcChannel channel, TaskCompletionSource<T> taskCompletionSource)
Expand Down
23 changes: 21 additions & 2 deletions Exo.Settings.Ui/ViewModels/SettingsViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
using System.ComponentModel;
using Exo.Settings.Ui.Services;
using Exo.Ui;
using Exo.Contracts.Ui.Settings;
using System.Threading.Channels;

namespace Exo.Settings.Ui.ViewModels;

internal sealed class SettingsViewModel : BindableObject
{
public SettingsServiceConnectionManager ConnectionManager { get; }
private readonly SynchronizationContext? _synchronizationContext;
private readonly IEditionService _editionService;
private readonly DevicesViewModel _devicesViewModel;
private readonly LightingViewModel _lightingViewModel;
Expand All @@ -19,7 +19,9 @@ internal sealed class SettingsViewModel : BindableObject

public SettingsViewModel(IEditionService editionService)
{
_synchronizationContext = SynchronizationContext.Current;
ConnectionManager = new("Local\\Exo.Service.Configuration", 100);
ConnectionManager.PropertyChanged += OnConnectionManagerPropertyChanged;
_editionService = editionService;
_devicesViewModel = new(ConnectionManager);
_lightingViewModel = new(ConnectionManager, _devicesViewModel, _editionService);
Expand All @@ -30,6 +32,21 @@ public SettingsViewModel(IEditionService editionService)
_title = string.Empty;
}

private void OnConnectionManagerPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(SettingsServiceConnectionManager.IsConnected))
{
if (_synchronizationContext is null)
{
NotifyPropertyChanged(e);
}
else
{
_synchronizationContext.Post(state => ((SettingsViewModel)state!).NotifyPropertyChanged(ChangedProperty.IsConnected), this);
}
}
}

public DevicesViewModel Devices => _devicesViewModel;
public LightingViewModel Lighting => _lightingViewModel;
public SensorsViewModel Sensors => _sensorsViewModel;
Expand All @@ -48,4 +65,6 @@ public string Title
get => _title;
set => SetValue(ref _title, value);
}

public bool IsConnected => ConnectionManager.IsConnected;
}

0 comments on commit 9387f50

Please sign in to comment.