diff --git a/Hyperbar.Windows.MediaController/BackwardRequest.cs b/Hyperbar.Windows.MediaController/BackwardRequest.cs index 6a7153c..bad2f0a 100644 --- a/Hyperbar.Windows.MediaController/BackwardRequest.cs +++ b/Hyperbar.Windows.MediaController/BackwardRequest.cs @@ -1,3 +1,3 @@ -namespace Hyperbar.Windows.Primary; +namespace Hyperbar.Windows.MediaController; public record BackwardRequest : INotification; diff --git a/Hyperbar.Windows.MediaController/FowardRequest.cs b/Hyperbar.Windows.MediaController/FowardRequest.cs index 7cb05d1..3cfae01 100644 --- a/Hyperbar.Windows.MediaController/FowardRequest.cs +++ b/Hyperbar.Windows.MediaController/FowardRequest.cs @@ -1,3 +1,3 @@ -namespace Hyperbar.Windows.Primary; +namespace Hyperbar.Windows.MediaController; public record FowardRequest : INotification; diff --git a/Hyperbar.Windows.MediaController/Hyperbar.Windows.MediaController.csproj b/Hyperbar.Windows.MediaController/Hyperbar.Windows.MediaController.csproj index 36a8d9c..e9aa82a 100644 --- a/Hyperbar.Windows.MediaController/Hyperbar.Windows.MediaController.csproj +++ b/Hyperbar.Windows.MediaController/Hyperbar.Windows.MediaController.csproj @@ -14,29 +14,18 @@ - - + + + + + + - - - MSBuild:Compile - - - - - MSBuild:Compile - - - - - MSBuild:Compile - - \ No newline at end of file diff --git a/Hyperbar.Windows.MediaController/Media.cs b/Hyperbar.Windows.MediaController/Media.cs new file mode 100644 index 0000000..ebd483e --- /dev/null +++ b/Hyperbar.Windows.MediaController/Media.cs @@ -0,0 +1,5 @@ +namespace Hyperbar.Windows.MediaController; + +public record Media; + + diff --git a/Hyperbar.Windows.MediaController/MediaController.cs b/Hyperbar.Windows.MediaController/MediaController.cs index 666e24d..9987288 100644 --- a/Hyperbar.Windows.MediaController/MediaController.cs +++ b/Hyperbar.Windows.MediaController/MediaController.cs @@ -1,19 +1,34 @@ using Windows.Media.Control; -namespace Hyperbar.Windows.Primary; +namespace Hyperbar.Windows.MediaController; public class MediaController : - INotificationHandler + INotificationHandler, + INotificationHandler { + private readonly IMediator mediator; private readonly GlobalSystemMediaTransportControlsSession session; - public MediaController(GlobalSystemMediaTransportControlsSession session, - IMediator mediator) + public MediaController(IMediator mediator, + GlobalSystemMediaTransportControlsSession session) { + this.mediator = mediator; this.session = session; + mediator.Subscribe(this); + + session.MediaPropertiesChanged += OnMediaPropertiesChanged; } - public async ValueTask Handle(PlayRequest notification, CancellationToken cancellationToken) => + private void OnMediaPropertiesChanged(GlobalSystemMediaTransportControlsSession sender, + MediaPropertiesChangedEventArgs args) + { + mediator.PublishAsync(new Changed()); + } + + public async ValueTask Handle(Play notification, CancellationToken cancellationToken) => await session.TryPlayAsync(); + + public async ValueTask Handle(Pause notification, CancellationToken cancellationToken) => + await session.TryPauseAsync(); } \ No newline at end of file diff --git a/Hyperbar.Windows.MediaController/MediaControllerFactory.cs b/Hyperbar.Windows.MediaController/MediaControllerFactory.cs new file mode 100644 index 0000000..4c78801 --- /dev/null +++ b/Hyperbar.Windows.MediaController/MediaControllerFactory.cs @@ -0,0 +1,34 @@ +using Windows.Media.Control; + +namespace Hyperbar.Windows.MediaController; + +public class MediaControllerFactory(IMediator mediator, + IServiceScopeFactory serviceScopeFactory) : + IFactory +{ + public MediaController? Create(GlobalSystemMediaTransportControlsSession value) + { + if (serviceScopeFactory.Create(value) is MediaController mediaController) + { + return mediaController; + + //if (serviceScope.ServiceProvider.GetService() is IServiceFactory serviceFactory) + //{ + // if (serviceFactory.Create(value) is MediaController mediaController) + // { + // //if (serviceScope.ServiceProvider.GetService>() + // // is IFactory factory) + // //{ + // // if (factory.Create() is MediaControllerViewModel mediaControllerViewModel) + // // { + // // _ = await mediator.PublishAsync(new Created(mediaControllerViewModel)); + // // } + // //} + + // } + //} + } + + return default; + } +} diff --git a/Hyperbar.Windows.MediaController/MediaControllerHandler.cs b/Hyperbar.Windows.MediaController/MediaControllerHandler.cs new file mode 100644 index 0000000..bfc9eab --- /dev/null +++ b/Hyperbar.Windows.MediaController/MediaControllerHandler.cs @@ -0,0 +1,28 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Hyperbar.Windows.MediaController; + +public class MediaControllerHandler(IMediator mediator, + IServiceScopeProvider scopeProvider) : + INotificationHandler> +{ + public async ValueTask Handle(Created notification, + CancellationToken cancellationToken) + { + if (scopeProvider.TryGet(notification.Value, out IServiceScope? serviceScope)) + { + if (serviceScope is not null) + { + if (serviceScope.ServiceProvider.GetService>() + is IFactory factory) + { + if (factory.Create() is MediaControllerViewModel mediaControllerViewModel) + { + await mediator.PublishAsync(new Created(mediaControllerViewModel), + cancellationToken); + } + } + } + } + } +} diff --git a/Hyperbar.Windows.MediaController/MediaControllerManager.cs b/Hyperbar.Windows.MediaController/MediaControllerManager.cs index fdfe3f6..5b91658 100644 --- a/Hyperbar.Windows.MediaController/MediaControllerManager.cs +++ b/Hyperbar.Windows.MediaController/MediaControllerManager.cs @@ -1,40 +1,15 @@ using System.Collections.Concurrent; -using System.Threading.Channels; using Windows.Media.Control; -namespace Hyperbar.Windows.Primary; - -public class MediaControllerManager : +namespace Hyperbar.Windows.MediaController; +public class MediaControllerManager(IMediator mediator, + IFactory factory) : IInitializer { private readonly ConcurrentDictionary cachedSessions = []; - private readonly IMediator mediator; - private readonly Queue mediaControllers; - private readonly IServiceFactory serviceFactory; - public MediaControllerManager(IServiceFactory serviceFactory, - IMediator mediator, - Queue mediaControllers) - { - this.serviceFactory = serviceFactory; - this.mediator = mediator; - this.mediaControllers = mediaControllers; - } - - private Channel d; public async Task InitializeAsync() { - d = Channel.CreateUnbounded(); - - _ = Task.Run(async () => { - - await foreach (var coordinates in d.Reader.ReadAllAsync()) - { - Console.WriteLine(coordinates); - } - }); - - GlobalSystemMediaTransportControlsSessionManager mediaTransportControlsSessionManager = await GlobalSystemMediaTransportControlsSessionManager.RequestAsync(); mediaTransportControlsSessionManager.SessionsChanged += OnSessionsChanged; @@ -50,14 +25,10 @@ public class MediaControllerManager : private async Task InitializeSessionAsync(GlobalSystemMediaTransportControlsSession session) { - if (serviceFactory.Create(session) is MediaController mediaController) + if (factory.Create(session) is MediaController mediaController) { - await d.Writer.WriteAsync(mediaController); - - mediaControllers.Enqueue(mediaController); - - cachedSessions.TryAdd(session, mediaController); await mediator.PublishAsync(new Created(mediaController)); + cachedSessions.TryAdd(session, mediaController); } } @@ -81,13 +52,4 @@ public class MediaControllerManager : await InitializeSessionAsync(session); } } - - private void RemoveSession(GlobalSystemMediaTransportControlsSession session) - { - if (serviceFactory.Create(session) is MediaController mediaController) - { - cachedSessions.TryAdd(session, mediaController); - - } - } } diff --git a/Hyperbar.Windows.MediaController/MediaControllerView.xaml b/Hyperbar.Windows.MediaController/MediaControllerView.xaml index f9d3f7f..d62effb 100644 --- a/Hyperbar.Windows.MediaController/MediaControllerView.xaml +++ b/Hyperbar.Windows.MediaController/MediaControllerView.xaml @@ -4,11 +4,16 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ui="using:Hyperbar.Windows.UI"> - - - - - - - + + + + + + + + + diff --git a/Hyperbar.Windows.MediaController/MediaControllerViewModel.cs b/Hyperbar.Windows.MediaController/MediaControllerViewModel.cs index 08e3fe4..6c9b939 100644 --- a/Hyperbar.Windows.MediaController/MediaControllerViewModel.cs +++ b/Hyperbar.Windows.MediaController/MediaControllerViewModel.cs @@ -1,17 +1,6 @@ using CommunityToolkit.Mvvm.Input; -namespace Hyperbar.Windows.Primary; - -//public class MediaControllerViewModelFactory(IServiceFactory service, -// IMediator mediator, -// Queue mediaControllers) : -// IFactory -//{ -// public MediaControllerViewModel Create() -// { -// throw new NotImplementedException(); -// } -//} +namespace Hyperbar.Windows.MediaController; public class MediaControllerViewModel : ObservableCollectionViewModel, @@ -24,11 +13,11 @@ public class MediaControllerViewModel : { TemplateFactory = templateFactory; - this.Add(); - this.Add("\uEB9E"); - this.Add("\uE768"); - this.Add("\uE769"); - this.Add("\uEB9D"); + Add(); + Add("Backward", "\uEB9E"); + Add("Play", "\uE768", new RelayCommand(async () => await mediator.SendAsync(new Play()))); + Add("Pause", "\uE769", new RelayCommand(async () => await mediator.PublishAsync(new Pause()))); + Add("Forward", "\uEB9D"); } public ITemplateFactory TemplateFactory { get; set; } diff --git a/Hyperbar.Windows.MediaController/MediaControllerViewModelFactory.cs b/Hyperbar.Windows.MediaController/MediaControllerViewModelFactory.cs new file mode 100644 index 0000000..e8c8b22 --- /dev/null +++ b/Hyperbar.Windows.MediaController/MediaControllerViewModelFactory.cs @@ -0,0 +1,10 @@ +namespace Hyperbar.Windows.MediaController; + +public class MediaControllerViewModelFactory(IServiceFactory service) : + IFactory +{ + public MediaControllerViewModel? Create() + { + return service.Create(); + } +} diff --git a/Hyperbar.Windows.MediaController/MediaControllerWidgetProvider.cs b/Hyperbar.Windows.MediaController/MediaControllerWidgetProvider.cs index 464c377..a2c1838 100644 --- a/Hyperbar.Windows.MediaController/MediaControllerWidgetProvider.cs +++ b/Hyperbar.Windows.MediaController/MediaControllerWidgetProvider.cs @@ -1,16 +1,22 @@ -using Hyperbar.Windows.MediaController; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using System.Collections.Concurrent; +using Windows.Media.Control; -namespace Hyperbar.Windows.Primary; +namespace Hyperbar.Windows.MediaController; public class MediaControllerWidgetProvider : IWidgetProvider { public void Create(HostBuilderContext comtext, IServiceCollection services) => services.AddWidgetTemplate() - .AddSingleton>() .AddSingleton() - .AddContentTemplate(); - + .AddTransient, ServiceScopeFactory>() + .AddTransient, ServiceScopeProvider>() + .AddSingleton>() + .AddTransient, MediaControllerFactory>() + .AddHandler() + .AddTransient, MediaControllerViewModelFactory>() + .AddContentTemplate() + .AddContentTemplate(); } \ No newline at end of file diff --git a/Hyperbar.Windows.MediaController/MediaControllerWidgetView.xaml b/Hyperbar.Windows.MediaController/MediaControllerWidgetView.xaml index f606297..f9dc3bc 100644 --- a/Hyperbar.Windows.MediaController/MediaControllerWidgetView.xaml +++ b/Hyperbar.Windows.MediaController/MediaControllerWidgetView.xaml @@ -6,21 +6,8 @@ xmlns:ui="using:Hyperbar.Windows.UI"> - - - - - - - - - + ItemsSource="{Binding}" /> diff --git a/Hyperbar.Windows.MediaController/MediaControllerWidgetViewModel.cs b/Hyperbar.Windows.MediaController/MediaControllerWidgetViewModel.cs index e8a5d87..631c70e 100644 --- a/Hyperbar.Windows.MediaController/MediaControllerWidgetViewModel.cs +++ b/Hyperbar.Windows.MediaController/MediaControllerWidgetViewModel.cs @@ -1,4 +1,4 @@ -namespace Hyperbar.Windows.Primary; +namespace Hyperbar.Windows.MediaController; public class MediaControllerWidgetViewModel(ITemplateFactory templateFactory, IServiceFactory serviceFactory, diff --git a/Hyperbar.Windows.MediaController/MediaInformationView.xaml b/Hyperbar.Windows.MediaController/MediaInformationView.xaml index 798e5dd..597b3ce 100644 --- a/Hyperbar.Windows.MediaController/MediaInformationView.xaml +++ b/Hyperbar.Windows.MediaController/MediaInformationView.xaml @@ -3,5 +3,23 @@ x:Class="Hyperbar.Windows.MediaController.MediaInformationView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - + + + + + + + + + + + + diff --git a/Hyperbar.Windows.MediaController/MediaInformationViewModel.cs b/Hyperbar.Windows.MediaController/MediaInformationViewModel.cs index 2752bf7..b127c1c 100644 --- a/Hyperbar.Windows.MediaController/MediaInformationViewModel.cs +++ b/Hyperbar.Windows.MediaController/MediaInformationViewModel.cs @@ -1,6 +1,6 @@ using CommunityToolkit.Mvvm.ComponentModel; -namespace Hyperbar.Windows.Primary; +namespace Hyperbar.Windows.MediaController; public partial class MediaInformationViewModel : WidgetComponentViewModel diff --git a/Hyperbar.Windows.MediaController/Pause.cs b/Hyperbar.Windows.MediaController/Pause.cs new file mode 100644 index 0000000..a8c349b --- /dev/null +++ b/Hyperbar.Windows.MediaController/Pause.cs @@ -0,0 +1,3 @@ +namespace Hyperbar.Windows.MediaController; + +public record Pause : INotification; diff --git a/Hyperbar.Windows.MediaController/PauseRequest.cs b/Hyperbar.Windows.MediaController/PauseRequest.cs deleted file mode 100644 index 8acbf03..0000000 --- a/Hyperbar.Windows.MediaController/PauseRequest.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Hyperbar.Windows.Primary; - -public record PauseRequest : INotification; diff --git a/Hyperbar.Windows.MediaController/Play.cs b/Hyperbar.Windows.MediaController/Play.cs new file mode 100644 index 0000000..41ee48a --- /dev/null +++ b/Hyperbar.Windows.MediaController/Play.cs @@ -0,0 +1,3 @@ +namespace Hyperbar.Windows.MediaController; + +public record Play : INotification; diff --git a/Hyperbar.Windows.MediaController/PlayRequest.cs b/Hyperbar.Windows.MediaController/PlayRequest.cs deleted file mode 100644 index 1e45b4a..0000000 --- a/Hyperbar.Windows.MediaController/PlayRequest.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Hyperbar.Windows.Primary; - -public record PlayRequest : INotification; diff --git a/Hyperbar.Windows.Primary/IPrimaryCommandConfiguration.cs b/Hyperbar.Windows.Primary/PrimaryCommandConfiguration.cs similarity index 76% rename from Hyperbar.Windows.Primary/IPrimaryCommandConfiguration.cs rename to Hyperbar.Windows.Primary/PrimaryCommandConfiguration.cs index c964863..c8540cf 100644 --- a/Hyperbar.Windows.Primary/IPrimaryCommandConfiguration.cs +++ b/Hyperbar.Windows.Primary/PrimaryCommandConfiguration.cs @@ -9,4 +9,8 @@ public class PrimaryCommandConfiguration public required Guid Id { get; set; } public required string Icon { get; set; } + + public required string Text { get; set; } + + public List? Commands { get; set; } = []; } \ No newline at end of file diff --git a/Hyperbar.Windows.Primary/PrimaryWidgetConfiguration.cs b/Hyperbar.Windows.Primary/PrimaryWidgetConfiguration.cs index 43a6370..73f977b 100644 --- a/Hyperbar.Windows.Primary/PrimaryWidgetConfiguration.cs +++ b/Hyperbar.Windows.Primary/PrimaryWidgetConfiguration.cs @@ -5,6 +5,6 @@ public class PrimaryWidgetConfiguration : { public static PrimaryWidgetConfiguration Defaults => new() { - new KeyAcceleratorCommandConfiguration { Id = Guid.NewGuid(), Icon = "\uE720", Key = 91, Modifiers = [] } + new KeyAcceleratorCommandConfiguration { Id = Guid.NewGuid(), Icon = "\uE720", Text = "Test", Key = 91, Modifiers = [] } }; } \ No newline at end of file diff --git a/Hyperbar.Windows.Primary/ConfigurationChangedHandler.cs b/Hyperbar.Windows.Primary/PrimaryWidgetConfigurationHandler.cs similarity index 84% rename from Hyperbar.Windows.Primary/ConfigurationChangedHandler.cs rename to Hyperbar.Windows.Primary/PrimaryWidgetConfigurationHandler.cs index 55a562c..cba4127 100644 --- a/Hyperbar.Windows.Primary/ConfigurationChangedHandler.cs +++ b/Hyperbar.Windows.Primary/PrimaryWidgetConfigurationHandler.cs @@ -1,9 +1,9 @@ namespace Hyperbar.Windows.Primary; -public class ConfigurationChangedHandler(IMediator mediator, +public class PrimaryWidgetConfigurationHandler(IMediator mediator, PrimaryWidgetConfiguration configuration, - IViewModelFactory factory, - IViewModelCache cache) : + IFactory factory, + ICache cache) : INotificationHandler> { public async ValueTask Handle(ConfigurationChanged notification, diff --git a/Hyperbar.Windows.Primary/PrimaryWidgetProvider.cs b/Hyperbar.Windows.Primary/PrimaryWidgetProvider.cs index 37dbfdb..7ece5f8 100644 --- a/Hyperbar.Windows.Primary/PrimaryWidgetProvider.cs +++ b/Hyperbar.Windows.Primary/PrimaryWidgetProvider.cs @@ -8,10 +8,10 @@ public class PrimaryWidgetProvider : { public void Create(HostBuilderContext comtext, IServiceCollection services) => services.AddConfiguration() - .AddSingleton, ViewModelCache>() - .AddTransient, WidgetComponentViewModelFactory>() + .AddSingleton, Cache>() + .AddTransient, WidgetComponentViewModelFactory>() .AddTransient, WidgetComponentViewModelEnumerator>() .AddWidgetTemplate() - .AddHandler(); + .AddHandler(); } \ No newline at end of file diff --git a/Hyperbar.Windows.Primary/WidgetComponentViewModelEnumerator.cs b/Hyperbar.Windows.Primary/WidgetComponentViewModelEnumerator.cs index 72d1a10..6721ba9 100644 --- a/Hyperbar.Windows.Primary/WidgetComponentViewModelEnumerator.cs +++ b/Hyperbar.Windows.Primary/WidgetComponentViewModelEnumerator.cs @@ -1,7 +1,7 @@ namespace Hyperbar.Windows.Primary; public class WidgetComponentViewModelEnumerator(PrimaryWidgetConfiguration configuration, - IViewModelFactory factory) : + IFactory factory) : IViewModelEnumerator { public IEnumerable Next() diff --git a/Hyperbar.Windows.Primary/WidgetComponentViewModelFactory.cs b/Hyperbar.Windows.Primary/WidgetComponentViewModelFactory.cs index 4dda507..957e5a8 100644 --- a/Hyperbar.Windows.Primary/WidgetComponentViewModelFactory.cs +++ b/Hyperbar.Windows.Primary/WidgetComponentViewModelFactory.cs @@ -4,31 +4,71 @@ namespace Hyperbar.Windows.Primary; public class WidgetComponentViewModelFactory(IServiceFactory service, IMediator mediator, - IViewModelCache cache) : - IViewModelFactory + ICache cache) : + IFactory { - public IWidgetComponentViewModel? Create(PrimaryCommandConfiguration value) + public IWidgetComponentViewModel? Create(PrimaryCommandConfiguration configuration) { - IWidgetComponentViewModel? viewModel = default; + WidgetComponentViewModel? viewModel = default; - if (value is KeyAcceleratorCommandConfiguration keyAcceleratorCommand) + if (configuration is KeyAcceleratorCommandConfiguration keyAcceleratorCommandConfiguration) { - viewModel = service.Create(keyAcceleratorCommand.Id, keyAcceleratorCommand.Icon, - new RelayCommand(async () => await mediator.SendAsync(new KeyAcceleratorRequest((VirtualKey) - keyAcceleratorCommand.Key, keyAcceleratorCommand.Modifiers? + viewModel = service.Create(keyAcceleratorCommandConfiguration.Id, + keyAcceleratorCommandConfiguration.Text, keyAcceleratorCommandConfiguration.Icon, + new RelayCommand(async () => await mediator.SendAsync(new KeyAccelerator((VirtualKey) + keyAcceleratorCommandConfiguration.Key, keyAcceleratorCommandConfiguration.Modifiers? .Select(modifier => (VirtualKey)modifier).ToArray())))); } - - if (value is ProcessCommandConfiguration commandConfiguration) + + if (configuration is ProcessCommandConfiguration processCommandConfiguration) { - viewModel = service.Create(commandConfiguration.Id, - commandConfiguration.Icon, new RelayCommand(async () => - await mediator.SendAsync(new ProcessRequest(commandConfiguration.Path)))); + if (processCommandConfiguration.Commands is { Count: > 0 } childCommandConfigurations) + { + List childViewModels = []; + + foreach (PrimaryCommandConfiguration childCommandConfiguration in childCommandConfigurations) + { + WidgetComponentViewModel? childViewModel = null; + + if (childCommandConfiguration is ProcessCommandConfiguration childProcessCommandConfiguration) + { + childViewModel = service.Create(childProcessCommandConfiguration.Id, + childProcessCommandConfiguration.Icon, childProcessCommandConfiguration.Text, + new RelayCommand(async () => await mediator.SendAsync(new StartProcess(childProcessCommandConfiguration.Path)))); + } + + if (childCommandConfiguration is KeyAcceleratorCommandConfiguration childKeyAcceleratorCommandConfiguration) + { + childViewModel = service.Create(childKeyAcceleratorCommandConfiguration.Id, + childKeyAcceleratorCommandConfiguration.Text, childKeyAcceleratorCommandConfiguration.Icon, + new RelayCommand(async () => + await mediator.SendAsync(new KeyAccelerator((VirtualKey)childKeyAcceleratorCommandConfiguration.Key, + childKeyAcceleratorCommandConfiguration.Modifiers?.Select(modifier => (VirtualKey)modifier).ToArray())))); + } + + if (childViewModel is not null) + { + childViewModels.Add(childViewModel); + cache.Add(childViewModel.Id, childViewModel); + } + } + + viewModel = service.Create(childViewModels, + processCommandConfiguration.Id, processCommandConfiguration.Text, + processCommandConfiguration.Icon, new RelayCommand(async () => + await mediator.SendAsync(new StartProcess(processCommandConfiguration.Path)))); + } + else + { + viewModel = service.Create(processCommandConfiguration.Id, + processCommandConfiguration.Text, processCommandConfiguration.Icon, new RelayCommand(async () => + await mediator.SendAsync(new StartProcess(processCommandConfiguration.Path)))); + } } if (viewModel is not null) { - cache.Add(value.Id, viewModel); + cache.Add(viewModel.Id, viewModel); } return viewModel; diff --git a/Hyperbar.Windows.UI/Extensions/WindowPlacement.cs b/Hyperbar.Windows.UI/Extensions/WindowPlacement.cs index c81b841..f7bc061 100644 --- a/Hyperbar.Windows.UI/Extensions/WindowPlacement.cs +++ b/Hyperbar.Windows.UI/Extensions/WindowPlacement.cs @@ -6,4 +6,4 @@ public enum WindowPlacement Top = 1, Right = 2, Bottom = 3, -} \ No newline at end of file +} diff --git a/Hyperbar.Windows/App.xaml.cs b/Hyperbar.Windows/App.xaml.cs index 13cf47e..2350969 100644 --- a/Hyperbar.Windows/App.xaml.cs +++ b/Hyperbar.Windows/App.xaml.cs @@ -1,4 +1,5 @@ using Hyperbar.Windows.Controls; +using Hyperbar.Windows.MediaController; using Hyperbar.Windows.Primary; using Hyperbar.Windows.UI; using Microsoft.Extensions.Configuration; @@ -50,7 +51,7 @@ public partial class App : services.AddHandler(); - //services.AddWidgetProvider(); + services.AddWidgetProvider(); services.AddWidgetProvider(); services.AddTransient(provider => diff --git a/Hyperbar.Windows/Hyperbar.Windows.csproj b/Hyperbar.Windows/Hyperbar.Windows.csproj index cf6c2ee..270c63a 100644 --- a/Hyperbar.Windows/Hyperbar.Windows.csproj +++ b/Hyperbar.Windows/Hyperbar.Windows.csproj @@ -16,6 +16,7 @@ + @@ -45,6 +46,11 @@ + + + MSBuild:Compile + + MSBuild:Compile diff --git a/Hyperbar.Windows/Lifecycles/IServiceCollectionExtensions.cs b/Hyperbar.Windows/Lifecycles/IServiceCollectionExtensions.cs index 4b33438..d80641b 100644 --- a/Hyperbar.Windows/Lifecycles/IServiceCollectionExtensions.cs +++ b/Hyperbar.Windows/Lifecycles/IServiceCollectionExtensions.cs @@ -28,24 +28,25 @@ namespace Hyperbar.Windows }) .ConfigureServices((context, isolatedServices) => { - isolatedServices.AddSingleton(provider => + isolatedServices.AddScoped(provider => new ServiceFactory((type, parameters) => ActivatorUtilities.CreateInstance(provider, type, parameters!))); isolatedServices.AddHostedService(); isolatedServices.AddTransient(); - isolatedServices.AddSingleton(); - isolatedServices.AddSingleton(); + isolatedServices.AddScoped(); + isolatedServices.AddScoped(); - isolatedServices.AddSingleton(); + isolatedServices.AddScoped(); isolatedServices.AddHandler(); - isolatedServices.AddHandler(); + isolatedServices.AddHandler(); isolatedServices.AddTransient(); isolatedServices.AddContentTemplate(); isolatedServices.AddContentTemplate(); + isolatedServices.AddContentTemplate(); builder.Create(context, isolatedServices); diff --git a/Hyperbar.Windows/Mediators/KeyAcceleratorHandler.cs b/Hyperbar.Windows/Mediators/KeyAcceleratorHandler.cs index 84e6b0a..5435cfc 100644 --- a/Hyperbar.Windows/Mediators/KeyAcceleratorHandler.cs +++ b/Hyperbar.Windows/Mediators/KeyAcceleratorHandler.cs @@ -1,26 +1,14 @@ using Hyperbar.Windows.Interop; -using System.Diagnostics; namespace Hyperbar.Windows; public class KeyAcceleratorHandler(IVirtualKeyboard virtualKeyboard) : - IRequestHandler + IRequestHandler { - public ValueTask Handle(KeyAcceleratorRequest request, + public ValueTask Handle(KeyAccelerator request, CancellationToken cancellationToken) { virtualKeyboard.Send((int)request.Key, request.Modifiers?.Select(modifier => (int)modifier).ToArray() ?? []); return default; } } - -public class ProcesssAcceleratorHandler : - IRequestHandler -{ - public ValueTask Handle(ProcessRequest request, - CancellationToken cancellationToken) - { - Process.Start(request.Process); - return default; - } -} diff --git a/Hyperbar.Windows/Mediators/StartProcessHandler.cs b/Hyperbar.Windows/Mediators/StartProcessHandler.cs new file mode 100644 index 0000000..3898f33 --- /dev/null +++ b/Hyperbar.Windows/Mediators/StartProcessHandler.cs @@ -0,0 +1,14 @@ +using System.Diagnostics; + +namespace Hyperbar.Windows; + +public class StartProcessHandler : + IRequestHandler +{ + public ValueTask Handle(StartProcess request, + CancellationToken cancellationToken) + { + Process.Start(request.Process); + return default; + } +} diff --git a/Hyperbar.Windows/Views/WidgetButtonView.xaml b/Hyperbar.Windows/Views/WidgetButtonView.xaml index 404e20f..f045a66 100644 --- a/Hyperbar.Windows/Views/WidgetButtonView.xaml +++ b/Hyperbar.Windows/Views/WidgetButtonView.xaml @@ -20,5 +20,6 @@ Command="{Binding Click}" Content="{Binding Icon}" FontFamily="{StaticResource SymbolThemeFontFamily}" - FontSize="16" /> + FontSize="16" + ToolTipService.ToolTip="{Binding Text}" /> \ No newline at end of file diff --git a/Hyperbar.Windows/Views/WidgetContainerView.xaml b/Hyperbar.Windows/Views/WidgetContainerView.xaml index fcdc2a1..b05e007 100644 --- a/Hyperbar.Windows/Views/WidgetContainerView.xaml +++ b/Hyperbar.Windows/Views/WidgetContainerView.xaml @@ -11,7 +11,7 @@ + + + + + + + + 0 + 40 + 38 + + + + + + + + + + + + + + + diff --git a/Hyperbar.Windows/Views/WidgetSplitButtonView.xaml.cs b/Hyperbar.Windows/Views/WidgetSplitButtonView.xaml.cs new file mode 100644 index 0000000..9cf97fb --- /dev/null +++ b/Hyperbar.Windows/Views/WidgetSplitButtonView.xaml.cs @@ -0,0 +1,9 @@ +using Microsoft.UI.Xaml.Controls; + +namespace Hyperbar.Windows; + +public sealed partial class WidgetSplitButtonView : + UserControl +{ + public WidgetSplitButtonView() => InitializeComponent(); +} diff --git a/Hyperbar.Windows/Views/WidgetView.xaml b/Hyperbar.Windows/Views/WidgetView.xaml index 24db384..95b55fa 100644 --- a/Hyperbar.Windows/Views/WidgetView.xaml +++ b/Hyperbar.Windows/Views/WidgetView.xaml @@ -6,7 +6,6 @@ xmlns:interactions="using:Microsoft.Xaml.Interactions.Core" xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:ui="using:Hyperbar.Windows.UI"> - diff --git a/Hyperbar/Commands/KeyAcceleratorRequest.cs b/Hyperbar/Commands/KeyAccelerator.cs similarity index 59% rename from Hyperbar/Commands/KeyAcceleratorRequest.cs rename to Hyperbar/Commands/KeyAccelerator.cs index fcbd357..aad44d4 100644 --- a/Hyperbar/Commands/KeyAcceleratorRequest.cs +++ b/Hyperbar/Commands/KeyAccelerator.cs @@ -1,5 +1,5 @@ namespace Hyperbar; -public record KeyAcceleratorRequest(VirtualKey Key, +public record KeyAccelerator(VirtualKey Key, VirtualKey[]? Modifiers = null) : IRequest; diff --git a/Hyperbar/Commands/ProcessRequest.cs b/Hyperbar/Commands/ProcessRequest.cs deleted file mode 100644 index b0b4bf5..0000000 --- a/Hyperbar/Commands/ProcessRequest.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Hyperbar; - -public record ProcessRequest(string Process) : IRequest; \ No newline at end of file diff --git a/Hyperbar/Commands/StartProcess.cs b/Hyperbar/Commands/StartProcess.cs new file mode 100644 index 0000000..9ecb089 --- /dev/null +++ b/Hyperbar/Commands/StartProcess.cs @@ -0,0 +1,3 @@ +namespace Hyperbar; + +public record StartProcess(string Process) : IRequest; \ No newline at end of file diff --git a/Hyperbar/Extensions/IServiceCollectionExtensions.cs b/Hyperbar/Extensions/IServiceCollectionExtensions.cs index 2885e30..b5fdc0a 100644 --- a/Hyperbar/Extensions/IServiceCollectionExtensions.cs +++ b/Hyperbar/Extensions/IServiceCollectionExtensions.cs @@ -119,16 +119,23 @@ public static class IServiceCollectionExtensions where THandler : IHandler { - if (typeof(THandler).GetInterface(typeof(INotificationHandler<>).Name) is { } notificationContract) + if (typeof(THandler).GetInterfaces() is { } contracts) { - if (notificationContract.GetGenericArguments() is { Length: 1 } arguments) + foreach (Type contract in contracts) { - Type notificationType = arguments[0]; + if (contract.Name == typeof(INotificationHandler<>).Name) + { + if (contract.GetGenericArguments() is { Length: 1 } arguments) + { + Type notificationType = arguments[0]; + + services.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime)); + services.Add(new ServiceDescriptor(typeof(INotificationHandler<>).MakeGenericType(notificationType), + provider => provider.GetRequiredService(), lifetime)); + } + } + } - services.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime)); - services.Add(new ServiceDescriptor(typeof(INotificationHandler<>).MakeGenericType(notificationType), - provider => provider.GetRequiredService(), lifetime)); - } } if (typeof(THandler).GetInterface(typeof(IHandler<,>).Name) is { } requestContract) @@ -150,20 +157,6 @@ public static class IServiceCollectionExtensions } } - if (typeof(THandler).GetInterface(typeof(IMappingHandler<,>).Name) is { } mappingContract) - { - if (mappingContract.GetGenericArguments() is { Length: 2 } arguments) - { - Type responseType = arguments[1]; - - services.AddTransient(typeof(THandler)); - services.AddTransient(responseType, provider => - { - return ((dynamic)provider.GetRequiredService()).Handle(); - }); - } - } - return services; } public static IServiceCollection AddWidgetTemplate(this IServiceCollection services) diff --git a/Hyperbar/Lifecycles/ViewModelCache.cs b/Hyperbar/Lifecycles/Cache.cs similarity index 63% rename from Hyperbar/Lifecycles/ViewModelCache.cs rename to Hyperbar/Lifecycles/Cache.cs index 265ced6..a2e8f75 100644 --- a/Hyperbar/Lifecycles/ViewModelCache.cs +++ b/Hyperbar/Lifecycles/Cache.cs @@ -4,13 +4,13 @@ using System.Reactive.Disposables; namespace Hyperbar; -public class ViewModelCache(IDisposer disposer) : - IViewModelCache +public class Cache(IDisposer disposer) : + ICache where TKey : notnull { - private readonly IDictionary cache = new Dictionary(); + private readonly IDictionary cache = new Dictionary(); - public TViewModel this[TKey key] + public TService this[TKey key] { get => cache[key]; set => cache[key] = value; @@ -18,13 +18,13 @@ public class ViewModelCache(IDisposer disposer) : public ICollection Keys => cache.Keys; - public ICollection Values => cache.Values; + public ICollection Values => cache.Values; public int Count => cache.Count; public bool IsReadOnly => false; - public void Add(TKey key, TViewModel value) + public void Add(TKey key, TService value) { disposer.Add(value!, Disposable.Create(() => { @@ -34,14 +34,14 @@ public class ViewModelCache(IDisposer disposer) : cache.Add(key, value); } - public void Add(KeyValuePair item) + public void Add(KeyValuePair item) { cache.Add(item); } public void Clear() => cache.Clear(); - public bool Contains(KeyValuePair item) + public bool Contains(KeyValuePair item) { return cache.Contains(item); } @@ -51,12 +51,12 @@ public class ViewModelCache(IDisposer disposer) : return cache.ContainsKey(key); } - public void CopyTo(KeyValuePair[] array, int arrayIndex) + public void CopyTo(KeyValuePair[] array, int arrayIndex) { cache.CopyTo(array, arrayIndex); } - public IEnumerator> GetEnumerator() + public IEnumerator> GetEnumerator() { return cache.GetEnumerator(); } @@ -66,12 +66,12 @@ public class ViewModelCache(IDisposer disposer) : return cache.Remove(key); } - public bool Remove(KeyValuePair item) + public bool Remove(KeyValuePair item) { return cache.Remove(item); } - public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TViewModel value) + public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TService value) { return cache.TryGetValue(key, out value); } diff --git a/Hyperbar/Lifecycles/IViewModelCache.cs b/Hyperbar/Lifecycles/ICache.cs similarity index 62% rename from Hyperbar/Lifecycles/IViewModelCache.cs rename to Hyperbar/Lifecycles/ICache.cs index fcb3e8a..7416019 100644 --- a/Hyperbar/Lifecycles/IViewModelCache.cs +++ b/Hyperbar/Lifecycles/ICache.cs @@ -1,6 +1,6 @@ namespace Hyperbar; -public interface IViewModelCache : +public interface ICache : IDictionary where TKey : notnull { diff --git a/Hyperbar/Lifecycles/IFactory.cs b/Hyperbar/Lifecycles/IFactory.cs new file mode 100644 index 0000000..7b73e95 --- /dev/null +++ b/Hyperbar/Lifecycles/IFactory.cs @@ -0,0 +1,12 @@ +namespace Hyperbar; + +public interface IFactory +{ + TService? Create(TParameter value); +} + + +public interface IFactory +{ + TService? Create(); +} diff --git a/Hyperbar/Lifecycles/IServiceFactory.cs b/Hyperbar/Lifecycles/IServiceFactory.cs index dcf52e1..9a0ef43 100644 --- a/Hyperbar/Lifecycles/IServiceFactory.cs +++ b/Hyperbar/Lifecycles/IServiceFactory.cs @@ -6,4 +6,4 @@ public interface IServiceFactory params object?[] parameters); TService Create(params object?[] parameters); -} \ No newline at end of file +} diff --git a/Hyperbar/Lifecycles/IServiceScopeFactory.cs b/Hyperbar/Lifecycles/IServiceScopeFactory.cs new file mode 100644 index 0000000..d5c3712 --- /dev/null +++ b/Hyperbar/Lifecycles/IServiceScopeFactory.cs @@ -0,0 +1,6 @@ +namespace Hyperbar; + +public interface IServiceScopeFactory +{ + TService? Create(params object?[] parameters); +} diff --git a/Hyperbar/Lifecycles/IServiceScopeProvider.cs b/Hyperbar/Lifecycles/IServiceScopeProvider.cs new file mode 100644 index 0000000..3d84d2a --- /dev/null +++ b/Hyperbar/Lifecycles/IServiceScopeProvider.cs @@ -0,0 +1,8 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Hyperbar; + +public interface IServiceScopeProvider +{ + bool TryGet(TService service, out IServiceScope? serviceScope); +} diff --git a/Hyperbar/Lifecycles/IViewModelFactory.cs b/Hyperbar/Lifecycles/IViewModelFactory.cs deleted file mode 100644 index 6d2c5ca..0000000 --- a/Hyperbar/Lifecycles/IViewModelFactory.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Hyperbar; - -public interface IViewModelFactory -{ - TViewModel? Create(TParameter value); -} diff --git a/Hyperbar/Lifecycles/ServiceScopeFactory.cs b/Hyperbar/Lifecycles/ServiceScopeFactory.cs new file mode 100644 index 0000000..167fc9f --- /dev/null +++ b/Hyperbar/Lifecycles/ServiceScopeFactory.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.DependencyInjection; +using System.Collections.Concurrent; + +namespace Hyperbar; + +public class ServiceScopeFactory(IServiceScopeFactory serviceScopeFactory, + ConcurrentDictionary services) : + IServiceScopeFactory + where TService : notnull +{ + public TService? Create(params object?[] parameters) + { + if (serviceScopeFactory.CreateScope() is IServiceScope serviceScope) + { + if (serviceScope.ServiceProvider.GetService() is IServiceFactory serviceFactory) + { + if (serviceFactory.Create(parameters) is TService service) + { + services.TryAdd(service, serviceScope); + return service; + } + } + } + + return default; + } +} \ No newline at end of file diff --git a/Hyperbar/Lifecycles/ServiceScopeProvider.cs b/Hyperbar/Lifecycles/ServiceScopeProvider.cs new file mode 100644 index 0000000..7f6f8b2 --- /dev/null +++ b/Hyperbar/Lifecycles/ServiceScopeProvider.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.DependencyInjection; +using System.Collections.Concurrent; + +namespace Hyperbar; + +public class ServiceScopeProvider(ConcurrentDictionary services) : + IServiceScopeProvider + where TService : notnull +{ + public bool TryGet(TService service, + out IServiceScope? serviceScope) + { + if (services.TryGetValue(service, out IServiceScope? value)) + { + serviceScope = value; + return true; + } + + serviceScope = null; + return false; + } +} diff --git a/Hyperbar/Mediators/IMappingHandler.cs b/Hyperbar/Mediators/IMappingHandler.cs deleted file mode 100644 index 2b39e8f..0000000 --- a/Hyperbar/Mediators/IMappingHandler.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Hyperbar; - -public interface IMappingHandler : IHandler -{ - TTo Handle(); -} \ No newline at end of file diff --git a/Hyperbar/Mediators/Mediator.cs b/Hyperbar/Mediators/Mediator.cs index 96e5135..dbe0514 100644 --- a/Hyperbar/Mediators/Mediator.cs +++ b/Hyperbar/Mediators/Mediator.cs @@ -1,5 +1,5 @@ using Microsoft.Extensions.DependencyInjection; -using System.Runtime.CompilerServices; +using System.Collections.Concurrent; namespace Hyperbar; @@ -8,7 +8,7 @@ public class Mediator(IServiceProvider provider) : { private readonly SynchronizationContext? context = SynchronizationContext.Current; - private readonly ConditionalWeakTable subjects = []; + private readonly ConcurrentDictionary> subjects = []; public ValueTask PublishAsync(TNotification notification, CancellationToken cancellationToken = default) @@ -18,11 +18,14 @@ public class Mediator(IServiceProvider provider) : List> handlers = provider.GetServices>().ToList(); - foreach (KeyValuePair handler in subjects) + foreach (KeyValuePair> handler in subjects) { if (handler.Key == typeof(TNotification)) { - handlers.Add(handler.Value); + foreach (dynamic value in handler.Value) + { + handlers.Add(value); + } } } @@ -80,7 +83,11 @@ public class Mediator(IServiceProvider provider) : if (interfaceType.GetGenericArguments() is { Length: 1 } arguments) { Type notificationType = arguments[0]; - subjects.Add(notificationType, subject); + subjects.AddOrUpdate(notificationType, [subject], (value, collection) => + { + collection.Add(subject); + return collection; + }); } } } diff --git a/Hyperbar/Views/Changed.cs b/Hyperbar/Views/Changed.cs new file mode 100644 index 0000000..0c72d25 --- /dev/null +++ b/Hyperbar/Views/Changed.cs @@ -0,0 +1,4 @@ +namespace Hyperbar; + +public record Changed(TValue? Value = default) : INotification; + diff --git a/Hyperbar/Views/Created.cs b/Hyperbar/Views/Created.cs index 6fa947b..32b0510 100644 --- a/Hyperbar/Views/Created.cs +++ b/Hyperbar/Views/Created.cs @@ -1,3 +1,3 @@ namespace Hyperbar; -public record Created(TValue? Value = default) : INotification; +public record Created(TValue Value) : INotification; \ No newline at end of file diff --git a/Hyperbar/Views/ObservableCollectionViewModel.cs b/Hyperbar/Views/ObservableCollectionViewModel.cs index 6bd8df9..521631b 100644 --- a/Hyperbar/Views/ObservableCollectionViewModel.cs +++ b/Hyperbar/Views/ObservableCollectionViewModel.cs @@ -19,6 +19,7 @@ public partial class ObservableCollectionViewModel : private readonly IDisposer disposer; private readonly IViewModelEnumerator? enumerator; private readonly IServiceFactory serviceFactory; + public ObservableCollectionViewModel(IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer) @@ -138,7 +139,7 @@ public partial class ObservableCollectionViewModel : where T : TItem { T? item = serviceFactory.Create(parameters); - context?.Post(state => Add(item), null); + Add(item); return item; } @@ -155,20 +156,17 @@ public partial class ObservableCollectionViewModel : public void Add(TItem item) { - context?.Post(state => + disposer.Add(this, item); + disposer.Add(item, Disposable.Create(item, args => { - disposer.Add(this, item); - disposer.Add(item, Disposable.Create(item, args => + if (Contains(args)) { - if (Contains(args)) - { - Remove(args); - } - })); + Remove(args); + } + })); - int index = collection.Count; - InsertItem(index, item); - }, null); + int index = collection.Count; + InsertItem(index, item); } int IList.Add(object? value) @@ -281,11 +279,7 @@ public partial class ObservableCollectionViewModel : int index = collection.IndexOf(item); if (index < 0) return false; - context?.Post(state => - { - context?.Post(state => RemoveItem(index), null); - - }, null); + RemoveItem(index); return true; } diff --git a/Hyperbar/Views/WidgetButtonViewModel.cs b/Hyperbar/Views/WidgetButtonViewModel.cs index d8fa8b2..be0fdb3 100644 --- a/Hyperbar/Views/WidgetButtonViewModel.cs +++ b/Hyperbar/Views/WidgetButtonViewModel.cs @@ -8,12 +8,16 @@ public partial class WidgetButtonViewModel(IServiceFactory serviceFactory, IDisposer disposer, ITemplateFactory templateFactory, Guid guid = default, + string? text = null, string? icon = null, RelayCommand? command = null) : WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory, guid) { + [ObservableProperty] + private IRelayCommand? click = command; + [ObservableProperty] private string? icon = icon; [ObservableProperty] - private IRelayCommand? click = command; + private string? text = text; } \ No newline at end of file diff --git a/Hyperbar/Views/WidgetComponentViewModel.cs b/Hyperbar/Views/WidgetComponentViewModel.cs index 8c0481d..651c032 100644 --- a/Hyperbar/Views/WidgetComponentViewModel.cs +++ b/Hyperbar/Views/WidgetComponentViewModel.cs @@ -3,29 +3,32 @@ namespace Hyperbar; public partial class WidgetComponentViewModel : - ObservableViewModel, + ObservableCollectionViewModel, IWidgetComponentViewModel, ITemplatedViewModel { - private readonly IMediator mediator; - private readonly IServiceFactory serviceFactory; - [ObservableProperty] private Guid id; + public WidgetComponentViewModel(IServiceFactory serviceFactory, + IMediator mediator, + IDisposer disposer, + ITemplateFactory templateFactory, + IEnumerable items, + Guid id = default) : base(serviceFactory, mediator, disposer, items) + { + this.id = id; + TemplateFactory = templateFactory; + } + public WidgetComponentViewModel(IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, ITemplateFactory templateFactory, Guid id = default) : base(serviceFactory, mediator, disposer) { - this.serviceFactory = serviceFactory; - this.mediator = mediator; this.id = id; - TemplateFactory = templateFactory; - - mediator.Subscribe(this); } public ITemplateFactory TemplateFactory { get; private set; } diff --git a/Hyperbar/Views/WidgetMenuViewModel.cs b/Hyperbar/Views/WidgetMenuViewModel.cs new file mode 100644 index 0000000..9546347 --- /dev/null +++ b/Hyperbar/Views/WidgetMenuViewModel.cs @@ -0,0 +1,23 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; + +namespace Hyperbar; + +public partial class WidgetMenuViewModel(IServiceFactory serviceFactory, + IMediator mediator, + IDisposer disposer, + ITemplateFactory templateFactory, + Guid guid = default, + string? text = null, + string? icon = null, + RelayCommand? command = null) : WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory, guid) +{ + [ObservableProperty] + private IRelayCommand? click = command; + + [ObservableProperty] + private string? icon = icon; + + [ObservableProperty] + private string? text = text; +} \ No newline at end of file diff --git a/Hyperbar/Views/WidgetSplitButtonViewModel.cs b/Hyperbar/Views/WidgetSplitButtonViewModel.cs new file mode 100644 index 0000000..aaa5f1e --- /dev/null +++ b/Hyperbar/Views/WidgetSplitButtonViewModel.cs @@ -0,0 +1,24 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; + +namespace Hyperbar; + +public partial class WidgetSplitButtonViewModel(IServiceFactory serviceFactory, + IMediator mediator, + IDisposer disposer, + ITemplateFactory templateFactory, + IEnumerable items, + Guid guid = default, + string? text = null, + string? icon = null, + RelayCommand? command = null) : WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory, items, guid) +{ + [ObservableProperty] + private IRelayCommand? click = command; + + [ObservableProperty] + private string? icon = icon; + + [ObservableProperty] + private string? text = text; +} \ No newline at end of file