diff --git a/Hyperbar.Windows.MediaController/Hyperbar.Windows.MediaController.csproj b/Hyperbar.Windows.MediaController/Hyperbar.Windows.MediaController.csproj
index e9aa82a..229b8f3 100644
--- a/Hyperbar.Windows.MediaController/Hyperbar.Windows.MediaController.csproj
+++ b/Hyperbar.Windows.MediaController/Hyperbar.Windows.MediaController.csproj
@@ -8,19 +8,13 @@
enable
enable
-
-
-
-
-
-
-
+
diff --git a/Hyperbar.Windows.MediaController/FowardRequest.cs b/Hyperbar.Windows.MediaController/Lifecycles/Backward.cs
similarity index 51%
rename from Hyperbar.Windows.MediaController/FowardRequest.cs
rename to Hyperbar.Windows.MediaController/Lifecycles/Backward.cs
index 3cfae01..d7bcf7c 100644
--- a/Hyperbar.Windows.MediaController/FowardRequest.cs
+++ b/Hyperbar.Windows.MediaController/Lifecycles/Backward.cs
@@ -1,3 +1,3 @@
namespace Hyperbar.Windows.MediaController;
-public record FowardRequest : INotification;
+public record Backward : INotification;
diff --git a/Hyperbar.Windows.MediaController/Play.cs b/Hyperbar.Windows.MediaController/Lifecycles/Foward.cs
similarity index 55%
rename from Hyperbar.Windows.MediaController/Play.cs
rename to Hyperbar.Windows.MediaController/Lifecycles/Foward.cs
index 41ee48a..4db2cbc 100644
--- a/Hyperbar.Windows.MediaController/Play.cs
+++ b/Hyperbar.Windows.MediaController/Lifecycles/Foward.cs
@@ -1,3 +1,3 @@
namespace Hyperbar.Windows.MediaController;
-public record Play : INotification;
+public record Foward : INotification;
diff --git a/Hyperbar.Windows.MediaController/Lifecycles/MediaController.cs b/Hyperbar.Windows.MediaController/Lifecycles/MediaController.cs
new file mode 100644
index 0000000..0c73287
--- /dev/null
+++ b/Hyperbar.Windows.MediaController/Lifecycles/MediaController.cs
@@ -0,0 +1,92 @@
+using Windows.Media.Control;
+
+namespace Hyperbar.Windows.MediaController;
+
+public class MediaController :
+ INotificationHandler,
+ INotificationHandler,
+ INotificationHandler>,
+ INotificationHandler>,
+ IDisposable
+{
+ private readonly IMediator mediator;
+ private readonly IDisposer disposer;
+ private readonly GlobalSystemMediaTransportControlsSession session;
+ private readonly AsyncLock asyncLock = new();
+
+ public MediaController(IMediator mediator,
+ IDisposer disposer,
+ GlobalSystemMediaTransportControlsSession session)
+ {
+ this.mediator = mediator;
+ this.disposer = disposer;
+ this.session = session;
+
+ disposer.Add(this);
+ mediator.Subscribe(this);
+
+ session.MediaPropertiesChanged += OnMediaPropertiesChanged;
+ session.PlaybackInfoChanged += OnPlaybackInfoChanged;
+ }
+
+ public void Dispose()
+ {
+ disposer.Dispose(this);
+ }
+
+ public async ValueTask Handle(Play notification,
+ CancellationToken cancellationToken) =>
+ await session.TryPlayAsync();
+
+ public async ValueTask Handle(Pause notification,
+ CancellationToken cancellationToken) =>
+ await session.TryPauseAsync();
+
+ public async ValueTask Handle(Request notification,
+ CancellationToken cancellationToken)
+ {
+ await mediator.PublishAsync(new Changed(), cancellationToken);
+ }
+
+ public async ValueTask Handle(Request _,
+ CancellationToken cancellationToken)
+ {
+ using (await asyncLock)
+ {
+ try
+ {
+ GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties = await session.TryGetMediaPropertiesAsync();
+ await mediator.PublishAsync(new Changed(new MediaInformation(mediaProperties.Title,
+ mediaProperties.Subtitle)), cancellationToken);
+ }
+ catch
+ {
+
+ }
+ }
+ }
+
+ private async void OnMediaPropertiesChanged(GlobalSystemMediaTransportControlsSession sender,
+ MediaPropertiesChangedEventArgs args)
+ {
+ using (await asyncLock)
+ {
+ try
+ {
+ GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties = await session.TryGetMediaPropertiesAsync();
+ await mediator.PublishAsync(new Changed(new MediaInformation(mediaProperties.Title,
+ mediaProperties.Artist)));
+ }
+ catch
+ {
+
+ }
+ }
+ }
+
+ private async void OnPlaybackInfoChanged(GlobalSystemMediaTransportControlsSession sender,
+ PlaybackInfoChangedEventArgs args)
+ {
+ await mediator.PublishAsync(new Changed());
+ }
+}
\ No newline at end of file
diff --git a/Hyperbar.Windows.MediaController/MediaControllerFactory.cs b/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerFactory.cs
similarity index 100%
rename from Hyperbar.Windows.MediaController/MediaControllerFactory.cs
rename to Hyperbar.Windows.MediaController/Lifecycles/MediaControllerFactory.cs
diff --git a/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerHandler.cs b/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerHandler.cs
new file mode 100644
index 0000000..0fcf96e
--- /dev/null
+++ b/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerHandler.cs
@@ -0,0 +1,34 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Hyperbar.Windows.MediaController;
+
+public class MediaControllerHandler(IMediator mediator,
+ IServiceScopeProvider scopeProvider,
+ ICache cache) :
+ INotificationHandler>
+{
+ public async ValueTask Handle(Created notification,
+ CancellationToken cancellationToken)
+ {
+ if (notification.Value is MediaController mediaController)
+ {
+ if (scopeProvider.TryGet(mediaController, out IServiceScope? serviceScope))
+ {
+ if (serviceScope is not null)
+ {
+ if (serviceScope.ServiceProvider.GetService>()
+ is IFactory factory)
+ {
+ if (factory.Create(mediaController) is MediaControllerViewModel mediaControllerViewModel)
+ {
+ cache.Add(mediaController, mediaControllerViewModel);
+ await mediator.PublishAsync(new Created(mediaControllerViewModel),
+ cancellationToken);
+ }
+ }
+ }
+ }
+ }
+
+ }
+}
diff --git a/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerManager.cs b/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerManager.cs
new file mode 100644
index 0000000..e7b6a45
--- /dev/null
+++ b/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerManager.cs
@@ -0,0 +1,70 @@
+using System.Diagnostics;
+using Windows.Media.Control;
+
+namespace Hyperbar.Windows.MediaController;
+public class MediaControllerManager(IMediator mediator,
+ IFactory factory,
+ IDispatcher dispatcher,
+ IDisposer disposer) :
+ IInitializer
+{
+ private readonly AsyncLock asyncLock = new();
+ private readonly List> cache = [];
+ private GlobalSystemMediaTransportControlsSessionManager? mediaTransportControlsSessionManager;
+
+ public async Task InitializeAsync()
+ {
+ mediaTransportControlsSessionManager = await GlobalSystemMediaTransportControlsSessionManager.RequestAsync();
+ mediaTransportControlsSessionManager.SessionsChanged += OnSessionsChanged;
+
+ IReadOnlyList sessions =
+ mediaTransportControlsSessionManager.GetSessions();
+
+ foreach (GlobalSystemMediaTransportControlsSession session in sessions)
+ {
+ await InitializeSessionAsync(session);
+ }
+ }
+
+ private async Task InitializeSessionAsync(GlobalSystemMediaTransportControlsSession session)
+ {
+ if (factory.Create(session) is MediaController mediaController)
+ {
+ await mediator.PublishAsync(new Created(mediaController));
+ Debug.WriteLine("Added " + session.SourceAppUserModelId + " " + session);
+
+ cache.Add(new KeyValuePair(session, mediaController));
+ }
+ }
+
+ private async void OnSessionsChanged(GlobalSystemMediaTransportControlsSessionManager sender,
+ SessionsChangedEventArgs args)
+ {
+ IReadOnlyList sessions =
+ sender.GetSessions();
+
+ using (await asyncLock)
+ {
+ foreach (KeyValuePair session in
+ cache.ToList())
+ {
+ if (!sessions.Any(x => x.SourceAppUserModelId == session.Key.SourceAppUserModelId))
+ {
+ await dispatcher.InvokeAsync(() => disposer.Dispose(session.Value));
+ cache.Remove(session);
+ }
+ }
+ }
+
+ using (await asyncLock)
+ {
+ foreach (GlobalSystemMediaTransportControlsSession session in sessions)
+ {
+ if (!cache.Any(x => x.Key.SourceAppUserModelId == session.SourceAppUserModelId))
+ {
+ await InitializeSessionAsync(session);
+ }
+ }
+ }
+ }
+}
diff --git a/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerViewModelFactory.cs b/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerViewModelFactory.cs
new file mode 100644
index 0000000..7d6ab3c
--- /dev/null
+++ b/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerViewModelFactory.cs
@@ -0,0 +1,16 @@
+namespace Hyperbar.Windows.MediaController;
+
+public class MediaControllerViewModelFactory(IServiceFactory service) :
+ IFactory
+{
+ public MediaControllerViewModel? Create(MediaController value)
+ {
+ if (service.Create()
+ is MediaControllerViewModel widgetComponentViewModel)
+ {
+ return widgetComponentViewModel;
+ }
+
+ return default;
+ }
+}
diff --git a/Hyperbar.Windows.MediaController/MediaControllerWidgetProvider.cs b/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerWidgetProvider.cs
similarity index 78%
rename from Hyperbar.Windows.MediaController/MediaControllerWidgetProvider.cs
rename to Hyperbar.Windows.MediaController/Lifecycles/MediaControllerWidgetProvider.cs
index 0634958..d0055ba 100644
--- a/Hyperbar.Windows.MediaController/MediaControllerWidgetProvider.cs
+++ b/Hyperbar.Windows.MediaController/Lifecycles/MediaControllerWidgetProvider.cs
@@ -1,6 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-using System.Collections.Concurrent;
using Windows.Media.Control;
namespace Hyperbar.Windows.MediaController;
@@ -16,8 +15,9 @@ public class MediaControllerWidgetProvider :
.AddCache()
.AddTransient, MediaControllerFactory>()
.AddHandler()
- .AddTransient, MediaControllerViewModelFactory>()
- .AddCache()
+ .AddTransient, MediaControllerViewModelFactory>()
+ .AddCache()
.AddContentTemplate()
- .AddContentTemplate();
+ .AddContentTemplate()
+ .AddContentTemplate();
}
\ No newline at end of file
diff --git a/Hyperbar.Windows.MediaController/Lifecycles/MediaInformation.cs b/Hyperbar.Windows.MediaController/Lifecycles/MediaInformation.cs
new file mode 100644
index 0000000..d033acf
--- /dev/null
+++ b/Hyperbar.Windows.MediaController/Lifecycles/MediaInformation.cs
@@ -0,0 +1,5 @@
+namespace Hyperbar.Windows.MediaController;
+
+public record MediaInformation(string Title, string Description);
+
+
diff --git a/Hyperbar.Windows.MediaController/Pause.cs b/Hyperbar.Windows.MediaController/Lifecycles/Pause.cs
similarity index 100%
rename from Hyperbar.Windows.MediaController/Pause.cs
rename to Hyperbar.Windows.MediaController/Lifecycles/Pause.cs
diff --git a/Hyperbar.Windows.MediaController/Media.cs b/Hyperbar.Windows.MediaController/Lifecycles/Play.cs
similarity index 57%
rename from Hyperbar.Windows.MediaController/Media.cs
rename to Hyperbar.Windows.MediaController/Lifecycles/Play.cs
index ebd483e..6b86f2d 100644
--- a/Hyperbar.Windows.MediaController/Media.cs
+++ b/Hyperbar.Windows.MediaController/Lifecycles/Play.cs
@@ -1,5 +1,3 @@
namespace Hyperbar.Windows.MediaController;
-public record Media;
-
-
+public record Play : INotification;
\ No newline at end of file
diff --git a/Hyperbar.Windows.MediaController/BackwardRequest.cs b/Hyperbar.Windows.MediaController/Lifecycles/Playback.cs
similarity index 50%
rename from Hyperbar.Windows.MediaController/BackwardRequest.cs
rename to Hyperbar.Windows.MediaController/Lifecycles/Playback.cs
index bad2f0a..3ed1095 100644
--- a/Hyperbar.Windows.MediaController/BackwardRequest.cs
+++ b/Hyperbar.Windows.MediaController/Lifecycles/Playback.cs
@@ -1,3 +1,3 @@
namespace Hyperbar.Windows.MediaController;
-public record BackwardRequest : INotification;
+public record Playback : INotification;
diff --git a/Hyperbar.Windows.MediaController/MediaController.cs b/Hyperbar.Windows.MediaController/MediaController.cs
deleted file mode 100644
index 9987288..0000000
--- a/Hyperbar.Windows.MediaController/MediaController.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using Windows.Media.Control;
-
-namespace Hyperbar.Windows.MediaController;
-
-public class MediaController :
- INotificationHandler,
- INotificationHandler
-{
- private readonly IMediator mediator;
- private readonly GlobalSystemMediaTransportControlsSession session;
-
- public MediaController(IMediator mediator,
- GlobalSystemMediaTransportControlsSession session)
- {
- this.mediator = mediator;
- this.session = session;
-
- mediator.Subscribe(this);
-
- session.MediaPropertiesChanged += OnMediaPropertiesChanged;
- }
-
- 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/MediaControllerHandler.cs b/Hyperbar.Windows.MediaController/MediaControllerHandler.cs
deleted file mode 100644
index bfc9eab..0000000
--- a/Hyperbar.Windows.MediaController/MediaControllerHandler.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-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
deleted file mode 100644
index 70571b1..0000000
--- a/Hyperbar.Windows.MediaController/MediaControllerManager.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using System.Collections.Concurrent;
-using Windows.Media.Control;
-
-namespace Hyperbar.Windows.MediaController;
-public class MediaControllerManager(IMediator mediator,
- IFactory factory) :
- IInitializer
-{
- private readonly List> cachedSessions = [];
-
- public async Task InitializeAsync()
- {
- GlobalSystemMediaTransportControlsSessionManager mediaTransportControlsSessionManager =
- await GlobalSystemMediaTransportControlsSessionManager.RequestAsync();
- mediaTransportControlsSessionManager.SessionsChanged += OnSessionsChanged;
-
- IReadOnlyList sessions =
- mediaTransportControlsSessionManager.GetSessions();
-
- foreach (GlobalSystemMediaTransportControlsSession session in sessions)
- {
- await InitializeSessionAsync(session);
- }
- }
-
- private async Task InitializeSessionAsync(GlobalSystemMediaTransportControlsSession session)
- {
- if (factory.Create(session) is MediaController mediaController)
- {
- await mediator.PublishAsync(new Created(mediaController));
- cachedSessions.Add(new KeyValuePair(session, mediaController));
- }
- }
-
- private async void OnSessionsChanged(GlobalSystemMediaTransportControlsSessionManager sender,
- SessionsChangedEventArgs args)
- {
- IReadOnlyList sessions =
- sender.GetSessions();
-
- foreach (KeyValuePair session in
- cachedSessions.ToList())
- {
- if (!sessions.Any(x => x.SourceAppUserModelId == session.Key.SourceAppUserModelId))
- {
- cachedSessions.Remove(session);
- }
- }
-
- foreach (GlobalSystemMediaTransportControlsSession session in sessions)
- {
- if (!cachedSessions.Any(x => x.Key.SourceAppUserModelId == session.SourceAppUserModelId))
- {
- await InitializeSessionAsync(session);
- }
- }
- }
-}
diff --git a/Hyperbar.Windows.MediaController/MediaControllerViewModelFactory.cs b/Hyperbar.Windows.MediaController/MediaControllerViewModelFactory.cs
deleted file mode 100644
index 4973c47..0000000
--- a/Hyperbar.Windows.MediaController/MediaControllerViewModelFactory.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace Hyperbar.Windows.MediaController;
-
-public class MediaControllerViewModelFactory(IServiceFactory service, ICache cache) :
- IFactory
-{
- public MediaControllerViewModel? Create()
- {
- if (service.Create() is MediaControllerViewModel widgetComponentViewModel)
- {
- cache.Add(widgetComponentViewModel);
- return widgetComponentViewModel;
- }
-
- return default;
- }
-}
diff --git a/Hyperbar.Windows.MediaController/MediaInformationViewModel.cs b/Hyperbar.Windows.MediaController/MediaInformationViewModel.cs
deleted file mode 100644
index b127c1c..0000000
--- a/Hyperbar.Windows.MediaController/MediaInformationViewModel.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using CommunityToolkit.Mvvm.ComponentModel;
-
-namespace Hyperbar.Windows.MediaController;
-
-public partial class MediaInformationViewModel :
- WidgetComponentViewModel
-{
- [ObservableProperty]
- private string title = "this is a test";
-
- [ObservableProperty]
- private string description = "this is a test description";
-
- public MediaInformationViewModel(IServiceFactory serviceFactory,
- IMediator mediator,
- IDisposer disposer,
- ITemplateFactory templateFactory) : base(serviceFactory, mediator, disposer, templateFactory)
- {
- }
-}
diff --git a/Hyperbar.Windows.MediaController/Views/MediaButtonView.xaml b/Hyperbar.Windows.MediaController/Views/MediaButtonView.xaml
new file mode 100644
index 0000000..25f0f53
--- /dev/null
+++ b/Hyperbar.Windows.MediaController/Views/MediaButtonView.xaml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+ 0
+ 40
+ 40
+
+
+
diff --git a/Hyperbar.Windows.MediaController/Views/MediaButtonView.xaml.cs b/Hyperbar.Windows.MediaController/Views/MediaButtonView.xaml.cs
new file mode 100644
index 0000000..7785dfd
--- /dev/null
+++ b/Hyperbar.Windows.MediaController/Views/MediaButtonView.xaml.cs
@@ -0,0 +1,9 @@
+using Microsoft.UI.Xaml.Controls;
+
+namespace Hyperbar.Windows.MediaController;
+
+public sealed partial class MediaButtonView :
+ UserControl
+{
+ public MediaButtonView() => InitializeComponent();
+}
diff --git a/Hyperbar.Windows.MediaController/Views/MediaButtonViewModel.cs b/Hyperbar.Windows.MediaController/Views/MediaButtonViewModel.cs
new file mode 100644
index 0000000..96c1f1f
--- /dev/null
+++ b/Hyperbar.Windows.MediaController/Views/MediaButtonViewModel.cs
@@ -0,0 +1,20 @@
+using CommunityToolkit.Mvvm.Input;
+using System.Windows.Input;
+
+namespace Hyperbar.Windows.MediaController;
+
+public class MediaButtonViewModel(IServiceFactory serviceFactory,
+ IMediator mediator,
+ IDisposer disposer,
+ ITemplateFactory templateFactory,
+ Guid guid = default,
+ string? text = null,
+ string? icon = null,
+ RelayCommand? command = null) :
+ WidgetButtonViewModel(serviceFactory, mediator, disposer, templateFactory, guid, text, icon, command),
+ IViewModelInitialization
+{
+ public ICommand Initialize => new AsyncRelayCommand(InitializeAsync);
+
+ public async Task InitializeAsync() => await Mediator.PublishAsync>();
+}
diff --git a/Hyperbar.Windows.MediaController/MediaControllerView.xaml b/Hyperbar.Windows.MediaController/Views/MediaControllerView.xaml
similarity index 94%
rename from Hyperbar.Windows.MediaController/MediaControllerView.xaml
rename to Hyperbar.Windows.MediaController/Views/MediaControllerView.xaml
index d62effb..3747274 100644
--- a/Hyperbar.Windows.MediaController/MediaControllerView.xaml
+++ b/Hyperbar.Windows.MediaController/Views/MediaControllerView.xaml
@@ -4,7 +4,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="using:Hyperbar.Windows.UI">
-
+
();
- 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");
+ Add("Backward", "\uEB9E");
+ Add("Play", "\uE768", new RelayCommand(async () => await mediator.PublishAsync()));
+ Add("Pause", "\uE769", new RelayCommand(async () => await mediator.PublishAsync()));
+ Add("Forward", "\uEB9D");
}
public ITemplateFactory TemplateFactory { get; set; }
diff --git a/Hyperbar.Windows.MediaController/MediaControllerWidgetView.xaml b/Hyperbar.Windows.MediaController/Views/MediaControllerWidgetView.xaml
similarity index 100%
rename from Hyperbar.Windows.MediaController/MediaControllerWidgetView.xaml
rename to Hyperbar.Windows.MediaController/Views/MediaControllerWidgetView.xaml
diff --git a/Hyperbar.Windows.MediaController/MediaControllerWidgetView.xaml.cs b/Hyperbar.Windows.MediaController/Views/MediaControllerWidgetView.xaml.cs
similarity index 100%
rename from Hyperbar.Windows.MediaController/MediaControllerWidgetView.xaml.cs
rename to Hyperbar.Windows.MediaController/Views/MediaControllerWidgetView.xaml.cs
diff --git a/Hyperbar.Windows.MediaController/MediaControllerWidgetViewModel.cs b/Hyperbar.Windows.MediaController/Views/MediaControllerWidgetViewModel.cs
similarity index 100%
rename from Hyperbar.Windows.MediaController/MediaControllerWidgetViewModel.cs
rename to Hyperbar.Windows.MediaController/Views/MediaControllerWidgetViewModel.cs
diff --git a/Hyperbar.Windows.MediaController/MediaInformationView.xaml b/Hyperbar.Windows.MediaController/Views/MediaInformationView.xaml
similarity index 63%
rename from Hyperbar.Windows.MediaController/MediaInformationView.xaml
rename to Hyperbar.Windows.MediaController/Views/MediaInformationView.xaml
index 597b3ce..f139106 100644
--- a/Hyperbar.Windows.MediaController/MediaInformationView.xaml
+++ b/Hyperbar.Windows.MediaController/Views/MediaInformationView.xaml
@@ -2,7 +2,9 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
+ xmlns:interactivity="using:Microsoft.Xaml.Interactivity">
@@ -20,6 +22,11 @@
Opacity="0.7"
Style="{ThemeResource CaptionTextBlockStyle}"
Text="{Binding Description}" />
+
+
+
+
+
diff --git a/Hyperbar.Windows.MediaController/MediaInformationView.xaml.cs b/Hyperbar.Windows.MediaController/Views/MediaInformationView.xaml.cs
similarity index 100%
rename from Hyperbar.Windows.MediaController/MediaInformationView.xaml.cs
rename to Hyperbar.Windows.MediaController/Views/MediaInformationView.xaml.cs
diff --git a/Hyperbar.Windows.MediaController/Views/MediaInformationViewModel.cs b/Hyperbar.Windows.MediaController/Views/MediaInformationViewModel.cs
new file mode 100644
index 0000000..3f6035a
--- /dev/null
+++ b/Hyperbar.Windows.MediaController/Views/MediaInformationViewModel.cs
@@ -0,0 +1,38 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System.Windows.Input;
+
+namespace Hyperbar.Windows.MediaController;
+
+public partial class MediaInformationViewModel(IServiceFactory serviceFactory,
+ IMediator mediator,
+ IDisposer disposer,
+ ITemplateFactory templateFactory) :
+ WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory),
+ IViewModelInitialization,
+ INotificationHandler>
+{
+ [ObservableProperty]
+ private string? description;
+
+ [ObservableProperty]
+ private string? title;
+
+ public ICommand Initialize =>
+ new AsyncRelayCommand(InitializeAsync);
+
+ public ValueTask Handle(Changed notification,
+ CancellationToken cancellationToken)
+ {
+ if (notification.Value is MediaInformation value)
+ {
+ Title = value.Title;
+ Description = value.Description;
+ }
+
+ return ValueTask.CompletedTask;
+ }
+
+ public async Task InitializeAsync() =>
+ await Mediator.PublishAsync>();
+}
diff --git a/Hyperbar.Windows/Views/WidgetView.xaml b/Hyperbar.Windows/Views/WidgetView.xaml
index 95b55fa..a1d793c 100644
--- a/Hyperbar.Windows/Views/WidgetView.xaml
+++ b/Hyperbar.Windows/Views/WidgetView.xaml
@@ -3,8 +3,6 @@
x:Class="Hyperbar.Windows.WidgetView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
- xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:ui="using:Hyperbar.Windows.UI">
@@ -12,10 +10,5 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/Hyperbar/Extensions/IServiceCollectionExtensions.cs b/Hyperbar/Extensions/IServiceCollectionExtensions.cs
index e5f41f3..e57af4d 100644
--- a/Hyperbar/Extensions/IServiceCollectionExtensions.cs
+++ b/Hyperbar/Extensions/IServiceCollectionExtensions.cs
@@ -13,7 +13,7 @@ public static class IServiceCollectionExtensions
where TKey :
notnull
{
- services.AddSingleton, Cache>();
+ services.AddScoped, Cache>();
services.AddTransient(provider => provider.GetService>()!.Select(x => x.Value));
return services;
diff --git a/Hyperbar/Lifecycles/Cache.cs b/Hyperbar/Lifecycles/Cache.cs
index c9015fb..e75b3a9 100644
--- a/Hyperbar/Lifecycles/Cache.cs
+++ b/Hyperbar/Lifecycles/Cache.cs
@@ -31,18 +31,20 @@ public class Cache(IDisposer disposer) :
public class Cache(IDisposer disposer) :
ICache
where TKey : notnull
+ where TValue : notnull
{
private readonly ConcurrentDictionary cache = new();
public void Add(TKey key,
TValue value)
{
- disposer.Add(value!, Disposable.Create(() =>
+ cache.TryAdd(key, value);
+
+ disposer.Add(key, Disposable.Create(() =>
{
+ disposer.Dispose(value);
Remove(key);
}));
-
- cache.TryAdd(key, value);
}
public void Clear() => cache.Clear();
diff --git a/Hyperbar/Lifecycles/Disposer.cs b/Hyperbar/Lifecycles/Disposer.cs
index 6759ba0..d223980 100644
--- a/Hyperbar/Lifecycles/Disposer.cs
+++ b/Hyperbar/Lifecycles/Disposer.cs
@@ -1,18 +1,39 @@
using System.Runtime.CompilerServices;
using System.Reactive.Disposables;
using System.Collections;
+using System.Collections.Concurrent;
namespace Hyperbar;
+public class AsyncLock(int initial = 1,
+ int maximum = 1) : IDisposable
+{
+ private readonly SemaphoreSlim semaphore = new(initial, maximum);
+
+ public void Dispose()
+ {
+ semaphore.Release();
+ }
+
+ public TaskAwaiter GetAwaiter() => LockAsync().GetAwaiter();
+
+ private async Task LockAsync()
+ {
+ await semaphore.WaitAsync();
+ return this;
+ }
+}
+
+
public class Disposer :
IDisposer
{
- private readonly ConditionalWeakTable