This commit is contained in:
TheXamlGuy
2024-02-01 22:13:45 +00:00
parent 6dbe2db584
commit 4edb0a7eb5
21 changed files with 126 additions and 85 deletions
@@ -4,8 +4,9 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:windows="using:Hyperbar.UI.Windows"> xmlns:windows="using:Hyperbar.UI.Windows">
<FlipView <Button>sfsdf</Button>
<!--<FlipView
Width="360" Width="360"
ItemTemplateSelector="{Binding Converter={windows:DataTemplateConverter}}" ItemTemplateSelector="{Binding Converter={windows:DataTemplateConverter}}"
ItemsSource="{Binding}" /> ItemsSource="{Binding}" />-->
</UserControl> </UserControl>
@@ -7,9 +7,9 @@ public class PrimaryWidgetConfigurationHandler(IMediator mediator,
IFactory<PrimaryCommandConfiguration, IWidgetComponentViewModel?> factory, IFactory<PrimaryCommandConfiguration, IWidgetComponentViewModel?> factory,
IProvider<PrimaryCommandConfiguration, IWidgetComponentViewModel?> provider, IProvider<PrimaryCommandConfiguration, IWidgetComponentViewModel?> provider,
ICache<(Guid ParentId, Guid Id), PrimaryCommandConfiguration> cache) : ICache<(Guid ParentId, Guid Id), PrimaryCommandConfiguration> cache) :
INotificationHandler<ConfigurationChanged<PrimaryWidgetConfiguration>> INotificationHandler<Changed<PrimaryWidgetConfiguration>>
{ {
public async Task Handle(ConfigurationChanged<PrimaryWidgetConfiguration> notification, public async Task Handle(Changed<PrimaryWidgetConfiguration> notification,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
List<KeyValuePair<(Guid ParentId, Guid Id), PrimaryCommandConfiguration>> items = []; List<KeyValuePair<(Guid ParentId, Guid Id), PrimaryCommandConfiguration>> items = [];
@@ -13,6 +13,7 @@ public static class IServiceCollectionExtensions
services.AddHandler<WidgetExtensionEnumerator>(); services.AddHandler<WidgetExtensionEnumerator>();
services.AddHandler<WidgetExtensionHandler>(); services.AddHandler<WidgetExtensionHandler>();
services.AddHandler<WidgetHostHandler>(); services.AddHandler<WidgetHostHandler>();
services.AddHandler<WidgetStartedHandler>();
return services; return services;
} }
@@ -0,0 +1,21 @@
namespace Hyperbar.Widget;
public class WidgetAvailabilityChangedHandler(IWidgetHost host) :
INotificationHandler<Changed<WidgetAvailability>>
{
public async Task Handle(Changed<WidgetAvailability> args,
CancellationToken cancellationToken)
{
if (args.Value is WidgetAvailability widgetAvailability)
{
if (widgetAvailability.Value)
{
await host.StartAsync(cancellationToken);
}
else
{
await host.StopAsync(cancellationToken);
}
}
}
}
+8 -8
View File
@@ -25,13 +25,18 @@ public class WidgetBuilder :
}) })
.ConfigureServices((context, services) => .ConfigureServices((context, services) =>
{ {
services.AddHostedService<WidgetService>(); services.AddSingleton<IWidgetHost, WidgetHost>();
services.AddScoped<IServiceFactory>(provider => services.AddScoped<IServiceFactory>(provider =>
new ServiceFactory((type, parameters) => new ServiceFactory((type, parameters) =>
ActivatorUtilities.CreateInstance(provider, type, parameters!))); ActivatorUtilities.CreateInstance(provider, type, parameters!)));
services.AddScoped<IMediator, Mediator>(); services.AddScoped<IMediator, Mediator>();
services.AddScoped<IDisposer, Disposer>(); services.AddScoped<IDisposer, Disposer>();
services.AddSingleton<IValue<WidgetAvailability>, Value<WidgetAvailability>>(); services.AddHandler<WidgetAvailabilityChangedHandler>();
services.AddValueChangedNotification<WidgetConfiguration,
WidgetAvailability>((config) => (args) =>
{
args.Value = config.IsEnabled;
});
}); });
} }
@@ -40,9 +45,7 @@ public class WidgetBuilder :
public IWidgetHost Build() public IWidgetHost Build()
{ {
IHost host = hostBuilder.Build(); IHost host = hostBuilder.Build();
return host.Services.GetRequiredService<IWidgetHost>();
return (IWidgetHost)ActivatorUtilities.CreateInstance(host.Services,
typeof(WidgetHost), host);
} }
public IWidgetBuilder UseConfiguration<TConfiguration>(Action<TConfiguration> configurationDelegate) public IWidgetBuilder UseConfiguration<TConfiguration>(Action<TConfiguration> configurationDelegate)
@@ -56,7 +59,6 @@ public class WidgetBuilder :
} }
configurationRegistered = true; configurationRegistered = true;
TConfiguration configuration = new(); TConfiguration configuration = new();
configurationDelegate(configuration); configurationDelegate(configuration);
@@ -88,7 +90,6 @@ public class WidgetBuilder :
} }
viewModelTemplateRegistered = true; viewModelTemplateRegistered = true;
hostBuilder.ConfigureServices(services => hostBuilder.ConfigureServices(services =>
{ {
services.AddWidgetTemplate<TViewModel>(); services.AddWidgetTemplate<TViewModel>();
@@ -107,7 +108,6 @@ public class WidgetBuilder :
} }
viewModelTemplateRegistered = true; viewModelTemplateRegistered = true;
hostBuilder.ConfigureServices(services => hostBuilder.ConfigureServices(services =>
{ {
services.AddWidgetTemplate<TWidgetContent, TWidgetTemplate>(); services.AddWidgetTemplate<TWidgetContent, TWidgetTemplate>();
+1 -1
View File
@@ -11,7 +11,7 @@ public class WidgetConfiguration
internal Guid Id { get; set; } = Guid.NewGuid(); internal Guid Id { get; set; } = Guid.NewGuid();
[JsonInclude] [JsonInclude]
internal bool Enabled { get; set; } internal bool IsEnabled { get; set; }
} }
public class WidgetConfiguration<TConfiguration>; public class WidgetConfiguration<TConfiguration>;
@@ -1,4 +0,0 @@
namespace Hyperbar.Widget;
public record WidgetConfigurationChanged<TConfiguration> : INotification;
+10 -5
View File
@@ -1,14 +1,19 @@
namespace Hyperbar.Widget; namespace Hyperbar.Widget;
public class WidgetConfigurationHandler(IValue<WidgetAvailability> widgetAvailability) : public class WidgetConfigurationHandler(IEnumerable<IConfigurationValueChangedNotification<WidgetConfiguration>>
INotificationHandler<ConfigurationChanged<WidgetConfiguration>> configurationValueChangedNotifications ) :
INotificationHandler<Changed<WidgetConfiguration>>
{ {
public async Task Handle(ConfigurationChanged<WidgetConfiguration> notification, public async Task Handle(Changed<WidgetConfiguration> args,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
if (notification.Configuration is WidgetConfiguration configuration) if (args.Value is WidgetConfiguration configuration)
{ {
await widgetAvailability.SetAsync(args => args with { Value = configuration.Enabled }); foreach (IConfigurationValueChangedNotification<WidgetConfiguration> notification in
configurationValueChangedNotifications)
{
await notification.PublishAsync(configuration);
}
} }
} }
} }
+6 -8
View File
@@ -6,15 +6,15 @@ namespace Hyperbar.Widget;
public sealed class WidgetHost : public sealed class WidgetHost :
IWidgetHost IWidgetHost
{ {
private readonly IHost host; private readonly IServiceProvider services;
private readonly IMediator mediator; private readonly IMediator mediator;
private readonly IProxyService<IMediator> proxyMediator; private readonly IProxyService<IMediator> proxyMediator;
public WidgetHost(IHost host, public WidgetHost(IServiceProvider services,
IMediator mediator, IMediator mediator,
IProxyService<IMediator> proxyMediator) IProxyService<IMediator> proxyMediator)
{ {
this.host = host; this.services = services;
this.mediator = mediator; this.mediator = mediator;
this.proxyMediator = proxyMediator; this.proxyMediator = proxyMediator;
@@ -24,7 +24,7 @@ public sealed class WidgetHost :
public WidgetConfiguration Configuration => public WidgetConfiguration Configuration =>
Services.GetRequiredService<WidgetConfiguration>(); Services.GetRequiredService<WidgetConfiguration>();
public IServiceProvider Services => host.Services; public IServiceProvider Services => services;
public void Dispose() public void Dispose()
{ {
@@ -33,8 +33,6 @@ public sealed class WidgetHost :
public async Task StartAsync(CancellationToken cancellationToken = default) public async Task StartAsync(CancellationToken cancellationToken = default)
{ {
await host.StartAsync(cancellationToken);
if (proxyMediator.Proxy is IMediator mediator) if (proxyMediator.Proxy is IMediator mediator)
{ {
await mediator.PublishAsync(new Started<IWidgetHost>(this), await mediator.PublishAsync(new Started<IWidgetHost>(this),
@@ -45,8 +43,8 @@ public sealed class WidgetHost :
cancellationToken); cancellationToken);
} }
public async Task StopAsync(CancellationToken cancellationToken = default) public Task StopAsync(CancellationToken cancellationToken = default)
{ {
await host.StopAsync(cancellationToken); return Task.CompletedTask;
} }
} }
+1 -14
View File
@@ -2,22 +2,9 @@
namespace Hyperbar.Widget; namespace Hyperbar.Widget;
public class WidgetHostHandler(IMediator mediator) : public class WidgetHostHandler :
INotificationHandler<Created<IWidgetHost>> INotificationHandler<Created<IWidgetHost>>
{ {
//public async Task Handle(Started<IWidgetHost> notification,
// CancellationToken cancellationToken)
//{
// if (notification.Value is IWidgetHost host)
// {
// if (host.Services.GetService<IWidgetViewModel>() is IWidgetViewModel viewModel)
// {
// await mediator.PublishAsync(new Created<IWidgetViewModel>(viewModel),
// nameof(WidgetViewModel), cancellationToken);
// }
// }
//}
public async Task Handle(Created<IWidgetHost> notification, public async Task Handle(Created<IWidgetHost> notification,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
+20
View File
@@ -0,0 +1,20 @@
using Microsoft.Extensions.DependencyInjection;
namespace Hyperbar.Widget;
public class WidgetStartedHandler(IMediator mediator) :
INotificationHandler<Started<IWidgetHost>>
{
public async Task Handle(Started<IWidgetHost> notification,
CancellationToken cancellationToken)
{
if (notification.Value is IWidgetHost host)
{
if (host.Services.GetService<IWidgetViewModel>() is IWidgetViewModel viewModel)
{
await mediator.PublishAsync(new Created<IWidgetViewModel>(viewModel),
nameof(WidgetViewModel), cancellationToken);
}
}
}
}
@@ -4,9 +4,9 @@ namespace Hyperbar.Windows;
public class AppConfigurationChangedHandler(DesktopBar desktopFlyout, public class AppConfigurationChangedHandler(DesktopBar desktopFlyout,
AppConfiguration configuration) : AppConfiguration configuration) :
INotificationHandler<ConfigurationChanged<AppConfiguration>> INotificationHandler<Changed<AppConfiguration>>
{ {
public Task Handle(ConfigurationChanged<AppConfiguration> notification, CancellationToken cancellationToken) public Task Handle(Changed<AppConfiguration> notification, CancellationToken cancellationToken)
{ {
desktopFlyout.Placement = configuration.Placement; desktopFlyout.Placement = configuration.Placement;
return Task.CompletedTask; return Task.CompletedTask;
@@ -1,5 +0,0 @@
namespace Hyperbar;
public record ConfigurationChanged<TConfiguration>(TConfiguration Configuration) : INotification
where TConfiguration :
class;
@@ -1,6 +1,7 @@
namespace Hyperbar; namespace Hyperbar;
public class ConfigurationInitializer<TConfiguration>(IConfigurationMonitor<TConfiguration> monitor, public class ConfigurationInitializer<TConfiguration>(IMediator mediator,
IConfigurationMonitor<TConfiguration> monitor,
IConfigurationReader<TConfiguration> reader, IConfigurationReader<TConfiguration> reader,
IConfigurationWriter<TConfiguration> writer, IConfigurationWriter<TConfiguration> writer,
IConfigurationFactory<TConfiguration> factory) : IConfigurationFactory<TConfiguration> factory) :
@@ -11,14 +12,16 @@ public class ConfigurationInitializer<TConfiguration>(IConfigurationMonitor<TCon
{ {
public async Task InitializeAsync() public async Task InitializeAsync()
{ {
if (!reader.TryRead(out TConfiguration? _)) if (!reader.TryRead(out TConfiguration? configuration))
{ {
if (factory.Create() is object defaultConfiguration) if (factory.Create() is object defaultConfiguration)
{ {
configuration = (TConfiguration?)defaultConfiguration;
writer.Write(defaultConfiguration); writer.Write(defaultConfiguration);
} }
} }
await mediator.PublishAsync(new Changed<TConfiguration>(configuration));
await monitor.InitializeAsync(); await monitor.InitializeAsync();
} }
} }
@@ -16,7 +16,7 @@ public class ConfigurationMonitor<TConfiguration>(IConfigurationFile<TConfigurat
{ {
if (reader.Read() is { } configuration) if (reader.Read() is { } configuration)
{ {
await mediator.PublishAsync(new ConfigurationChanged<TConfiguration>(configuration)); await mediator.PublishAsync(new Changed<TConfiguration>(configuration));
} }
} }
@@ -0,0 +1,24 @@
namespace Hyperbar;
public class ConfigurationValueChangedNotification<TConfiguration, TValue>(IMediator mediator,
Func<TConfiguration, Action<TValue>> factory) :
IConfigurationValueChangedNotification<TConfiguration>
where TConfiguration :
class
where TValue :
class, new()
{
private TValue? value;
public async Task PublishAsync(TConfiguration configuration)
{
TValue newValue = new();
factory(configuration).Invoke(newValue);
if (value is null || !value.Equals(newValue))
{
value = newValue;
await mediator.PublishAsync(new Changed<TValue>(value));
}
}
}
@@ -0,0 +1,6 @@
namespace Hyperbar;
public interface IConfigurationValueChangedNotification<TConfiguration>
{
Task PublishAsync(TConfiguration configuration);
}
@@ -9,6 +9,20 @@ namespace Hyperbar;
public static class IServiceCollectionExtensions public static class IServiceCollectionExtensions
{ {
public static IServiceCollection AddValueChangedNotification<TConfiguration, TValue>(this IServiceCollection services,
Func<TConfiguration, Action<TValue>> factory)
where TConfiguration :
class
where TValue :
class, new()
{
services.AddSingleton<IConfigurationValueChangedNotification<TConfiguration>>(provider =>
new ConfigurationValueChangedNotification<TConfiguration, TValue>(provider.GetRequiredService<IMediator>(),
factory));
return services;
}
public static IServiceCollection AddCache<TKey, TValue>(this IServiceCollection services) public static IServiceCollection AddCache<TKey, TValue>(this IServiceCollection services)
where TKey : where TKey :
notnull notnull
-9
View File
@@ -1,9 +0,0 @@
namespace Hyperbar;
public interface IValue<TValue>
where TValue :
notnull, new()
{
Task SetAsync(Func<TValue, TValue> updateDelgate);
}
-21
View File
@@ -1,21 +0,0 @@
namespace Hyperbar;
public class Value<TValue>(IMediator mediator) :
IValue<TValue>
where TValue :
notnull, new ()
{
private TValue? current;
public async Task SetAsync(Func<TValue, TValue> updateDelgate)
{
if (updateDelgate.Invoke(current ?? new TValue()) is TValue value)
{
if (current is null || !value.Equals(current))
{
current = value;
await mediator.PublishAsync(new Changed<TValue>(current));
}
}
}
}
+1 -1
View File
@@ -5,6 +5,6 @@ public interface INotificationHandler<in TNotification> :
where TNotification : where TNotification :
INotification INotification
{ {
Task Handle(TNotification notification, Task Handle(TNotification args,
CancellationToken cancellationToken); CancellationToken cancellationToken);
} }