diff --git a/App1/App.xaml b/App1/App.xaml
new file mode 100644
index 0000000..19bdc24
--- /dev/null
+++ b/App1/App.xaml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/App1/App.xaml.cs b/App1/App.xaml.cs
new file mode 100644
index 0000000..d6c3cb3
--- /dev/null
+++ b/App1/App.xaml.cs
@@ -0,0 +1,50 @@
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Controls.Primitives;
+using Microsoft.UI.Xaml.Data;
+using Microsoft.UI.Xaml.Input;
+using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Navigation;
+using Microsoft.UI.Xaml.Shapes;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace App1
+{
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ public partial class App : Application
+ {
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ }
+
+ ///
+ /// Invoked when the application is launched.
+ ///
+ /// Details about the launch request and process.
+ protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
+ {
+ m_window = new MainWindow();
+ m_window.Activate();
+ }
+
+ private Window m_window;
+ }
+}
diff --git a/App1/App1.csproj b/App1/App1.csproj
new file mode 100644
index 0000000..1f61254
--- /dev/null
+++ b/App1/App1.csproj
@@ -0,0 +1,48 @@
+
+
+ WinExe
+ net6.0-windows10.0.19041.0
+ 10.0.17763.0
+ App1
+ app.manifest
+ x86;x64;ARM64
+ win10-x86;win10-x64;win10-arm64
+ win10-$(Platform).pubxml
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
diff --git a/App1/Assets/LockScreenLogo.scale-200.png b/App1/Assets/LockScreenLogo.scale-200.png
new file mode 100644
index 0000000..7440f0d
Binary files /dev/null and b/App1/Assets/LockScreenLogo.scale-200.png differ
diff --git a/App1/Assets/SplashScreen.scale-200.png b/App1/Assets/SplashScreen.scale-200.png
new file mode 100644
index 0000000..32f486a
Binary files /dev/null and b/App1/Assets/SplashScreen.scale-200.png differ
diff --git a/App1/Assets/Square150x150Logo.scale-200.png b/App1/Assets/Square150x150Logo.scale-200.png
new file mode 100644
index 0000000..53ee377
Binary files /dev/null and b/App1/Assets/Square150x150Logo.scale-200.png differ
diff --git a/App1/Assets/Square44x44Logo.scale-200.png b/App1/Assets/Square44x44Logo.scale-200.png
new file mode 100644
index 0000000..f713bba
Binary files /dev/null and b/App1/Assets/Square44x44Logo.scale-200.png differ
diff --git a/App1/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/App1/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 0000000..dc9f5be
Binary files /dev/null and b/App1/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/App1/Assets/StoreLogo.png b/App1/Assets/StoreLogo.png
new file mode 100644
index 0000000..a4586f2
Binary files /dev/null and b/App1/Assets/StoreLogo.png differ
diff --git a/App1/Assets/Wide310x150Logo.scale-200.png b/App1/Assets/Wide310x150Logo.scale-200.png
new file mode 100644
index 0000000..8b4a5d0
Binary files /dev/null and b/App1/Assets/Wide310x150Logo.scale-200.png differ
diff --git a/App1/MainWindow.xaml b/App1/MainWindow.xaml
new file mode 100644
index 0000000..99d9cf1
--- /dev/null
+++ b/App1/MainWindow.xaml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/App1/MainWindow.xaml.cs b/App1/MainWindow.xaml.cs
new file mode 100644
index 0000000..a934cc2
--- /dev/null
+++ b/App1/MainWindow.xaml.cs
@@ -0,0 +1,31 @@
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Controls.Primitives;
+using Microsoft.UI.Xaml.Data;
+using Microsoft.UI.Xaml.Input;
+using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Navigation;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace App1
+{
+ ///
+ /// An empty window that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ this.InitializeComponent();
+ }
+ }
+}
diff --git a/App1/Package.appxmanifest b/App1/Package.appxmanifest
new file mode 100644
index 0000000..5fb8d1b
--- /dev/null
+++ b/App1/Package.appxmanifest
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+ App1
+ dan_c
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/App1/Properties/launchSettings.json b/App1/Properties/launchSettings.json
new file mode 100644
index 0000000..c7779fb
--- /dev/null
+++ b/App1/Properties/launchSettings.json
@@ -0,0 +1,10 @@
+{
+ "profiles": {
+ "App1 (Package)": {
+ "commandName": "MsixPackage"
+ },
+ "App1 (Unpackaged)": {
+ "commandName": "Project"
+ }
+ }
+}
\ No newline at end of file
diff --git a/App1/app.manifest b/App1/app.manifest
new file mode 100644
index 0000000..a44ef64
--- /dev/null
+++ b/App1/app.manifest
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PerMonitorV2
+
+
+
\ No newline at end of file
diff --git a/Hyperbar.UI.Windows/DataTemplateConverter.cs b/Hyperbar.UI.Windows/DataTemplateConverter.cs
index 7fdc9d2..58e9dd4 100644
--- a/Hyperbar.UI.Windows/DataTemplateConverter.cs
+++ b/Hyperbar.UI.Windows/DataTemplateConverter.cs
@@ -12,4 +12,4 @@ public class DataTemplateConverter :
{
return new TemplateGenerator();
}
-}
+}
\ No newline at end of file
diff --git a/Hyperbar.UI.Windows/StreamToImageSourceConverter.cs b/Hyperbar.UI.Windows/StreamToImageSourceConverter.cs
new file mode 100644
index 0000000..328f470
--- /dev/null
+++ b/Hyperbar.UI.Windows/StreamToImageSourceConverter.cs
@@ -0,0 +1,27 @@
+using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Media.Imaging;
+using Windows.Storage.Streams;
+
+namespace Hyperbar.UI.Windows;
+
+public class StreamToImageSourceConverter :
+ ValueConverter
+{
+ protected override ImageSource? ConvertTo(Stream value,
+ Type? targetType,
+ object? parameter,
+ string? language)
+ {
+ if (value == null)
+ {
+ return default;
+ }
+
+ IRandomAccessStream randomAccessStream =
+ WindowsRuntimeStreamExtensions.AsRandomAccessStream(value);
+
+ BitmapImage bitmapImage = new();
+ bitmapImage.SetSource(randomAccessStream);
+ return bitmapImage;
+ }
+}
\ No newline at end of file
diff --git a/Hyperbar.UI.Windows/TemplateGenerator.cs b/Hyperbar.UI.Windows/TemplateGenerator.cs
index 0a0b865..9ce0596 100644
--- a/Hyperbar.UI.Windows/TemplateGenerator.cs
+++ b/Hyperbar.UI.Windows/TemplateGenerator.cs
@@ -9,9 +9,14 @@ public class TemplateGenerator : DataTemplateSelector
protected override DataTemplate SelectTemplateCore(object item)
{
string xamlString = @"
-
-
+
+
+
+
";
return (DataTemplate)XamlReader.Load(xamlString);
@@ -20,9 +25,14 @@ public class TemplateGenerator : DataTemplateSelector
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
string xamlString = @"
-
-
+
+
+
+
";
return (DataTemplate)XamlReader.Load(xamlString);
diff --git a/Hyperbar.UI.Windows/TemplateGeneratorControl.cs b/Hyperbar.UI.Windows/TemplateGeneratorControl.cs
index a5d3cd0..880c589 100644
--- a/Hyperbar.UI.Windows/TemplateGeneratorControl.cs
+++ b/Hyperbar.UI.Windows/TemplateGeneratorControl.cs
@@ -17,9 +17,5 @@ public class TemplateGeneratorControl :
{
Content = templatedViewModel.TemplateFactory.Create(DataContext.GetType().Name);
}
- else
- {
-
- }
}
}
\ No newline at end of file
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml b/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml
index 585ba8d..3bc7768 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml
+++ b/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml
@@ -4,8 +4,7 @@
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"
- Visibility="{x:Bind ViewModel.Visible, Mode=OneWay}">
+ xmlns:interactivity="using:Microsoft.Xaml.Interactivity">
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs
index 4df17f8..a5e7a18 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs
+++ b/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs
@@ -1,39 +1,43 @@
-using CommunityToolkit.Mvvm.Input;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
namespace Hyperbar.Widget.MediaController.Windows;
-public class MediaButtonViewModel(IServiceFactory serviceFactory,
+[NotificationHandler(nameof(PlaybackButtonType))]
+public partial class MediaButtonViewModel(IServiceFactory serviceFactory,
IMediator mediator,
IDisposer disposer,
ITemplateFactory templateFactory,
- PlaybackButtonType buttonType,
+ PlaybackButtonType playbackButtonType,
Guid guid = default,
string? text = null,
string? icon = null,
RelayCommand? command = null) :
WidgetButtonViewModel(serviceFactory, mediator, disposer, templateFactory, guid, text, icon, command),
- IInitialization,
- INotificationHandler>
+ IInitialization
{
- public Task Handle(Changed notification,
+ [ObservableProperty]
+ private PlaybackButtonType playbackButtonType = playbackButtonType;
+
+ public Task Handle(Changed notification,
CancellationToken cancellationToken)
{
- if (notification.Value is PlaybackInformation information)
+ if (notification.Value is MediaControllerPlaybackStatus information)
{
- switch (buttonType)
- {
- case PlaybackButtonType.Play:
- Visible = information.Status is PlaybackStatus.Paused;
- break;
- case PlaybackButtonType.Pause:
- Visible = information.Status is PlaybackStatus.Playing;
- break;
- }
+ //switch (buttonType)
+ //{
+ // case PlaybackButtonType.Play:
+ // Visible = information.Status is PlaybackStatus.Paused;
+ // break;
+ // case PlaybackButtonType.Pause:
+ // Visible = information.Status is PlaybackStatus.Playing;
+ // break;
+ //}
}
return Task.CompletedTask;
}
- public override async Task InitializeAsync() =>
- await Mediator.PublishAsync>();
+ //public override async Task InitializeAsync() =>
+ // await Mediator.PublishAsync>();
}
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaController.cs b/Hyperbar.Widget.MediaController.Windows/MediaController.cs
index a0ab6f1..ffd1f50 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaController.cs
+++ b/Hyperbar.Widget.MediaController.Windows/MediaController.cs
@@ -1,18 +1,25 @@
-using Windows.Media.Control;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Media.Imaging;
+using Windows.Graphics.Imaging;
+using Windows.Media.Control;
+using Windows.Storage.Streams;
namespace Hyperbar.Widget.MediaController.Windows;
public class MediaController :
INotificationHandler,
INotificationHandler,
- INotificationHandler>,
+ INotificationHandler>,
INotificationHandler>,
IDisposable
{
private readonly AsyncLock asyncLock = new();
private readonly IDisposer disposer;
private readonly IMediator mediator;
- private readonly GlobalSystemMediaTransportControlsSession session;
+ private GlobalSystemMediaTransportControlsSession? session;
+
+ private GlobalSystemMediaTransportControlsSessionPlaybackStatus playbackStatus;
public MediaController(IMediator mediator,
IDisposer disposer,
@@ -31,6 +38,8 @@ public class MediaController :
public void Dispose()
{
+ session = null;
+
GC.SuppressFinalize(this);
disposer.Dispose(this);
}
@@ -49,7 +58,7 @@ public class MediaController :
await UpdateMediaPlaybackPropertiesAsync();
}
- public async Task Handle(Request args,
+ public async Task Handle(Request args,
CancellationToken cancellationToken) => await UpdateMediaPlaybackPropertiesAsync();
public async Task Handle(Request args,
@@ -68,9 +77,14 @@ public class MediaController :
try
{
GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo = session.GetPlaybackInfo();
- await mediator.PublishAsync(new Changed(
- new PlaybackInformation((PlaybackStatus)playbackInfo.PlaybackStatus)));
+ if (playbackInfo.PlaybackStatus != playbackStatus)
+ {
+ playbackStatus = playbackInfo.PlaybackStatus;
+ await mediator.PublishAsync(new Changed(
+ new MediaControllerPlaybackStatus((PlaybackStatus)playbackStatus)));
+
+ }
}
catch
{
@@ -81,20 +95,31 @@ public class MediaController :
private async Task UpdateMediaPropertiesAsync()
{
- using (await asyncLock)
+ if (session is not null)
{
- try
+ using (await asyncLock)
{
- GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties =
- await session.TryGetMediaPropertiesAsync();
+ try
+ {
- await mediator.PublishAsync(new Changed(new MediaInformation(mediaProperties.Title,
- mediaProperties.Artist)));
+ //
- }
- catch
- {
+ //InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
+ //// Copy the image stream to the random access stream
+ //await d.AsStream().CopyToAsync(randomAccessStream.AsStreamForWrite());
+
+ GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties =
+ await session.TryGetMediaPropertiesAsync();
+
+ IRandomAccessStreamWithContentType randomAccessStream = await mediaProperties.Thumbnail.OpenReadAsync();
+ await mediator.PublishAsync(new Changed(new MediaInformation(mediaProperties.Title,
+ mediaProperties.Artist, randomAccessStream.AsStream())));
+ }
+ catch
+ {
+
+ }
}
}
}
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerManager.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerManager.cs
index 9ab9815..b93d06f 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaControllerManager.cs
+++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerManager.cs
@@ -3,11 +3,10 @@
namespace Hyperbar.Widget.MediaController.Windows;
public class MediaControllerManager(IMediator mediator,
- IFactory factory,
- IDispatcher dispatcher,
- IDisposer disposer) :
+ IFactory factory) :
IInitializer
{
+
private readonly AsyncLock asyncLock = new();
private readonly List> cache = [];
private GlobalSystemMediaTransportControlsSessionManager? mediaTransportControlsSessionManager;
@@ -16,7 +15,7 @@ public class MediaControllerManager(IMediator mediator,
{
mediaTransportControlsSessionManager = await GlobalSystemMediaTransportControlsSessionManager.RequestAsync();
mediaTransportControlsSessionManager.SessionsChanged += OnSessionsChanged;
-
+
IReadOnlyList sessions =
mediaTransportControlsSessionManager.GetSessions();
@@ -31,7 +30,8 @@ public class MediaControllerManager(IMediator mediator,
if (factory.Create(session) is MediaController mediaController)
{
await mediator.PublishAsync(new Created(mediaController));
- cache.Add(new KeyValuePair(session, mediaController));
+ cache.Add(new KeyValuePair(session,
+ mediaController));
}
}
diff --git a/Hyperbar.Widget.MediaController.Windows/PlaybackInformation.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerPlaybackStatus.cs
similarity index 51%
rename from Hyperbar.Widget.MediaController.Windows/PlaybackInformation.cs
rename to Hyperbar.Widget.MediaController.Windows/MediaControllerPlaybackStatus.cs
index 2a15c24..2d7b223 100644
--- a/Hyperbar.Widget.MediaController.Windows/PlaybackInformation.cs
+++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerPlaybackStatus.cs
@@ -1,4 +1,4 @@
namespace Hyperbar.Widget.MediaController.Windows;
-public record PlaybackInformation(PlaybackStatus Status) :
+public record MediaControllerPlaybackStatus(PlaybackStatus Status) :
INotification;
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerPlaybackStatusHandler.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerPlaybackStatusHandler.cs
new file mode 100644
index 0000000..7ad160f
--- /dev/null
+++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerPlaybackStatusHandler.cs
@@ -0,0 +1,31 @@
+using CommunityToolkit.Mvvm.Input;
+
+namespace Hyperbar.Widget.MediaController.Windows;
+
+public class MediaControllerPlaybackStatusHandler(IMediator mediator,
+ IServiceFactory factory) :
+ INotificationHandler>
+{
+ public async Task Handle(Changed notification,
+ CancellationToken cancellationToken)
+ {
+ if (notification.Value is MediaControllerPlaybackStatus mediaControllerPlaybackInformation)
+ {
+ if (mediaControllerPlaybackInformation.Status is PlaybackStatus.Playing)
+ {
+ await mediator.PublishAsync(new Replaced(2, factory.Create(
+ PlaybackButtonType.Pause, "Pause", "\uE769",
+ new RelayCommand(async () => await mediator.PublishAsync()))), nameof(MediaControllerViewModel),
+ cancellationToken);
+ }
+
+ if (mediaControllerPlaybackInformation.Status is PlaybackStatus.Paused)
+ {
+ await mediator.PublishAsync(new Replaced(2, factory.Create(
+ PlaybackButtonType.Pause, "Play", "\uE768",
+ new RelayCommand(async () => await mediator.PublishAsync()))), nameof(MediaControllerViewModel),
+ cancellationToken);
+ }
+ }
+ }
+}
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerView.xaml b/Hyperbar.Widget.MediaController.Windows/MediaControllerView.xaml
index 3d233ad..50fe0d0 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaControllerView.xaml
+++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerView.xaml
@@ -3,11 +3,12 @@
x:Class="Hyperbar.Widget.MediaController.Windows.MediaControllerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:ui="using:Hyperbar.UI.Windows">
-
+ xmlns:windows="using:Hyperbar.UI.Windows">
+
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs
index ef7638a..1ad79f9 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs
+++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs
@@ -2,6 +2,7 @@
namespace Hyperbar.Widget.MediaController.Windows;
+[NotificationHandler(nameof(MediaControllerViewModel))]
public class MediaControllerViewModel :
ObservableCollectionViewModel,
ITemplatedViewModel
@@ -15,19 +16,15 @@ public class MediaControllerViewModel :
Add();
- Add(PlaybackButtonType.Previous,
+ Add(PlaybackButtonType.Previous,
"Previous", "\uEB9E",
new RelayCommand(async () => await mediator.PublishAsync()));
- Add(PlaybackButtonType.Play,
- "Play", "\uE768",
- new RelayCommand(async () => await mediator.PublishAsync()));
-
Add(PlaybackButtonType.Pause,
- "Pause", "\uE769",
+ "Pause", "\uE769",
new RelayCommand(async () => await mediator.PublishAsync()));
- Add(PlaybackButtonType.Forward,
+ Add(PlaybackButtonType.Forward,
"Forward", "\uEB9D",
new RelayCommand(async () => await mediator.PublishAsync()));
}
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerWidget.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerWidget.cs
index b5551bb..75e7c4e 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaControllerWidget.cs
+++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerWidget.cs
@@ -1,4 +1,3 @@
-using Hyperbar.Widget;
using Microsoft.Extensions.DependencyInjection;
using Windows.Media.Control;
@@ -22,6 +21,7 @@ public class MediaControllerWidget :
.AddHandler()
.AddTransient, MediaControllerViewModelFactory>()
.AddCache()
+ .AddHandler()
.AddContentTemplate()
.AddContentTemplate()
.AddContentTemplate();
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetView.xaml b/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetView.xaml
index 590060e..fe77d80 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetView.xaml
+++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetView.xaml
@@ -3,11 +3,9 @@
x:Class="Hyperbar.Widget.MediaController.Windows.MediaControllerWidgetView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:ui="using:Hyperbar.UI.Windows">
+ xmlns:windows="using:Hyperbar.UI.Windows">
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaInformation.cs b/Hyperbar.Widget.MediaController.Windows/MediaInformation.cs
index d7f5028..580500e 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaInformation.cs
+++ b/Hyperbar.Widget.MediaController.Windows/MediaInformation.cs
@@ -1,5 +1,7 @@
namespace Hyperbar.Widget.MediaController.Windows;
-public record MediaInformation(string Title, string Description);
+public record MediaInformation(string Title,
+ string Description,
+ Stream ThumbnailSource);
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaInformationView.xaml b/Hyperbar.Widget.MediaController.Windows/MediaInformationView.xaml
index 645841d..2048f11 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaInformationView.xaml
+++ b/Hyperbar.Widget.MediaController.Windows/MediaInformationView.xaml
@@ -4,27 +4,35 @@
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:interactivity="using:Microsoft.Xaml.Interactivity"
+ xmlns:windows="using:Hyperbar.UI.Windows">
+
-
+
+ Height="40">
+
+
-
+
+ Text="{x:Bind ViewModel.Description, Mode=OneWay}"
+ TextTrimming="CharacterEllipsis"
+ TextWrapping="NoWrap" />
-
+
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaInformationView.xaml.cs b/Hyperbar.Widget.MediaController.Windows/MediaInformationView.xaml.cs
index 44ebfe8..dc9484f 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaInformationView.xaml.cs
+++ b/Hyperbar.Widget.MediaController.Windows/MediaInformationView.xaml.cs
@@ -8,4 +8,6 @@ public sealed partial class MediaInformationView :
{
public MediaInformationView() =>
this.InitializeComponent(ref _contentLoaded);
+
+ private MediaInformationViewModel ViewModel => (MediaInformationViewModel)DataContext;
}
diff --git a/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs
index 316b815..1234951 100644
--- a/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs
+++ b/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs
@@ -1,5 +1,5 @@
using CommunityToolkit.Mvvm.ComponentModel;
-using Hyperbar.Widget;
+using Microsoft.UI.Xaml.Media;
namespace Hyperbar.Widget.MediaController.Windows;
@@ -14,6 +14,9 @@ public partial class MediaInformationViewModel(IServiceFactory serviceFactory,
[ObservableProperty]
private string? description;
+ [ObservableProperty]
+ private Stream? thumbnailSource;
+
[ObservableProperty]
private string? title;
@@ -24,6 +27,7 @@ public partial class MediaInformationViewModel(IServiceFactory serviceFactory,
{
Title = value.Title;
Description = value.Description;
+ ThumbnailSource = value.ThumbnailSource;
}
return Task.CompletedTask;
diff --git a/Hyperbar.Widget.Windows/IServiceCollectionExtensions.cs b/Hyperbar.Widget.Windows/IServiceCollectionExtensions.cs
index 49716f1..51e087a 100644
--- a/Hyperbar.Widget.Windows/IServiceCollectionExtensions.cs
+++ b/Hyperbar.Widget.Windows/IServiceCollectionExtensions.cs
@@ -1,6 +1,8 @@
using Hyperbar.Interop.Windows;
using Hyperbar.UI.Windows;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.UI.Xaml.Markup;
+using System.Collections.Generic;
namespace Hyperbar.Widget.Windows;
@@ -16,6 +18,7 @@ public static class IServiceCollectionExtensions
services.AddTransient>(provider =>
new ProxyServiceCollection(services =>
{
+ services.AddSingleton(provider.GetRequiredService>());
services.AddSingleton(provider.GetRequiredService());
services.AddTransient,
WidgetContainerFactory>();
@@ -29,7 +32,8 @@ public static class IServiceCollectionExtensions
services.AddHandler();
services.AddTransient();
- services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
services.AddContentTemplate();
services.AddContentTemplate();
diff --git a/Hyperbar.Widget.Windows/WidgetBarView.xaml b/Hyperbar.Widget.Windows/WidgetBarView.xaml
index 9b65476..157e17f 100644
--- a/Hyperbar.Widget.Windows/WidgetBarView.xaml
+++ b/Hyperbar.Widget.Windows/WidgetBarView.xaml
@@ -3,8 +3,8 @@
x:Class="Hyperbar.Widget.Windows.WidgetBarView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:ui="using:Hyperbar.UI.Windows">
-
+ xmlns:windows="using:Hyperbar.UI.Windows">
+
diff --git a/Hyperbar.Widget.Windows/WidgetResourceInitialization.cs b/Hyperbar.Widget.Windows/WidgetResourceInitializer.cs
similarity index 92%
rename from Hyperbar.Widget.Windows/WidgetResourceInitialization.cs
rename to Hyperbar.Widget.Windows/WidgetResourceInitializer.cs
index 3d8bbaa..c9fb0d3 100644
--- a/Hyperbar.Widget.Windows/WidgetResourceInitialization.cs
+++ b/Hyperbar.Widget.Windows/WidgetResourceInitializer.cs
@@ -3,7 +3,7 @@ using Windows.Storage;
namespace Hyperbar.Widget.Windows;
-internal class WidgetResourceInitialization(IWidgetAssembly widgetAssembly) :
+internal class WidgetResourceInitializer(IWidgetAssembly widgetAssembly) :
IInitializer
{
public async Task InitializeAsync()
diff --git a/Hyperbar.Widget.Windows/WidgetView.xaml b/Hyperbar.Widget.Windows/WidgetView.xaml
index a1874df..6b28c6a 100644
--- a/Hyperbar.Widget.Windows/WidgetView.xaml
+++ b/Hyperbar.Widget.Windows/WidgetView.xaml
@@ -5,9 +5,9 @@
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.UI.Windows">
+ xmlns:windows="using:Hyperbar.UI.Windows">
-
+
diff --git a/Hyperbar.Widget.Windows/WidgetXamlMetadataInitializer.cs b/Hyperbar.Widget.Windows/WidgetXamlMetadataInitializer.cs
new file mode 100644
index 0000000..8869282
--- /dev/null
+++ b/Hyperbar.Widget.Windows/WidgetXamlMetadataInitializer.cs
@@ -0,0 +1,20 @@
+using Microsoft.UI.Xaml.Markup;
+
+namespace Hyperbar.Widget.Windows;
+
+public class WidgetXamlMetadataInitializer(IWidgetAssembly widgetAssembly,
+ IList xamlMetadataProviders) :
+ IInitializer
+{
+ public Task InitializeAsync()
+ {
+ foreach (IXamlMetadataProvider xamlMetadataProvider in widgetAssembly.Assembly.ExportedTypes
+ .Where(type => type.IsAssignableTo(typeof(IXamlMetadataProvider)))
+ .Select(metadataType => (IXamlMetadataProvider)Activator.CreateInstance(metadataType)!))
+ {
+ xamlMetadataProviders.Add(xamlMetadataProvider);
+ }
+
+ return Task.CompletedTask;
+ }
+}
diff --git a/Hyperbar.Windows/App.xaml.cs b/Hyperbar.Windows/App.xaml.cs
index a5fa8d3..f1d04cf 100644
--- a/Hyperbar.Windows/App.xaml.cs
+++ b/Hyperbar.Windows/App.xaml.cs
@@ -1,5 +1,4 @@
-using CustomExtensions.WinUI;
-using Hyperbar.Controls.Windows;
+using Hyperbar.Controls.Windows;
using Hyperbar.UI.Windows;
using Hyperbar.Widget;
using Microsoft.Extensions.Configuration;
@@ -9,17 +8,14 @@ using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using System.Reflection;
using Hyperbar.Widget.Windows;
+using Microsoft.UI.Xaml.Markup;
namespace Hyperbar.Windows;
public partial class App :
Application
{
- public App()
- {
- InitializeComponent();
- ApplicationExtensionHost.Initialize(this);
- }
+ public App() => InitializeComponent();
protected override async void OnLaunched(LaunchActivatedEventArgs args)
{
@@ -37,6 +33,7 @@ public partial class App :
services.AddDefault();
services.AddWidget();
services.AddWidgetWindows();
+ services.AddXamlMetadataProvider();
services.AddHostedService();
diff --git a/Hyperbar.Windows/Lifecycles/IServiceCollectionExtensions.cs b/Hyperbar.Windows/Lifecycles/IServiceCollectionExtensions.cs
new file mode 100644
index 0000000..8d4f59d
--- /dev/null
+++ b/Hyperbar.Windows/Lifecycles/IServiceCollectionExtensions.cs
@@ -0,0 +1,26 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Markup;
+using System.Reflection;
+
+namespace Hyperbar.Widget;
+
+public static class IServiceCollectionExtensions
+{
+ public static IServiceCollection AddXamlMetadataProvider(this IServiceCollection services)
+ {
+ object? appProvider = Application.Current.GetType().GetProperty("_AppProvider", BindingFlags.NonPublic | BindingFlags.Instance)?
+ .GetValue(Application.Current);
+
+ object? provider = appProvider?.GetType().GetProperty("Provider", BindingFlags.NonPublic | BindingFlags.Instance)?
+ .GetValue(appProvider);
+
+ PropertyInfo? othersProviderProperty = provider?.GetType().GetProperty("OtherProviders", BindingFlags.NonPublic | BindingFlags.Instance,
+ null, typeof(List), [], null);
+
+ List xamlMetadataProviders = othersProviderProperty?.GetValue(provider) as List ?? [];
+
+ services.AddSingleton>(xamlMetadataProviders);
+ return services;
+ }
+}
\ No newline at end of file
diff --git a/Hyperbar.sln b/Hyperbar.sln
index 5a714a4..d5f857d 100644
--- a/Hyperbar.sln
+++ b/Hyperbar.sln
@@ -21,7 +21,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hyperbar.Widget.Primary.Win
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hyperbar.Widget.MediaController.Windows", "Hyperbar.Widget.MediaController.Windows\Hyperbar.Widget.MediaController.Windows.csproj", "{ACBB1C58-1DB6-40E1-ABF1-71F2D2F0EC73}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hyperbar.Widget.Windows", "Hyperbar.Widget.Windows\Hyperbar.Widget.Windows.csproj", "{E7322176-B67F-4A22-AFDB-7430A6AD44B6}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hyperbar.Widget.Windows", "Hyperbar.Widget.Windows\Hyperbar.Widget.Windows.csproj", "{E7322176-B67F-4A22-AFDB-7430A6AD44B6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App1", "App1\App1.csproj", "{AB161079-E1AA-4A9B-B64C-D27A68245A2C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -203,6 +205,30 @@ Global
{E7322176-B67F-4A22-AFDB-7430A6AD44B6}.Release|x64.Build.0 = Release|Any CPU
{E7322176-B67F-4A22-AFDB-7430A6AD44B6}.Release|x86.ActiveCfg = Release|Any CPU
{E7322176-B67F-4A22-AFDB-7430A6AD44B6}.Release|x86.Build.0 = Release|Any CPU
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|Any CPU.Build.0 = Debug|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|Any CPU.Deploy.0 = Debug|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|ARM64.Build.0 = Debug|ARM64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|x64.ActiveCfg = Debug|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|x64.Build.0 = Debug|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|x64.Deploy.0 = Debug|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|x86.ActiveCfg = Debug|x86
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|x86.Build.0 = Debug|x86
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Debug|x86.Deploy.0 = Debug|x86
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|Any CPU.ActiveCfg = Release|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|Any CPU.Build.0 = Release|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|Any CPU.Deploy.0 = Release|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|ARM64.ActiveCfg = Release|ARM64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|ARM64.Build.0 = Release|ARM64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|ARM64.Deploy.0 = Release|ARM64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|x64.ActiveCfg = Release|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|x64.Build.0 = Release|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|x64.Deploy.0 = Release|x64
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|x86.ActiveCfg = Release|x86
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|x86.Build.0 = Release|x86
+ {AB161079-E1AA-4A9B-B64C-D27A68245A2C}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs b/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs
index b43e34c..d0129f9 100644
--- a/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs
+++ b/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs
@@ -19,6 +19,7 @@ public partial class ObservableCollectionViewModel :
INotificationHandler>,
INotificationHandler>,
INotificationHandler>,
+ INotificationHandler>,
IDisposable
where TItem :
IDisposable
@@ -250,6 +251,17 @@ public partial class ObservableCollectionViewModel :
return Task.CompletedTask;
}
+ public Task Handle(Replaced notification,
+ CancellationToken cancellationToken)
+ {
+ if (notification.Value is TItem item)
+ {
+ Replace(notification.Index, item);
+ }
+
+ return Task.CompletedTask;
+ }
+
public int IndexOf(TItem item) =>
collection.IndexOf(item);
@@ -272,6 +284,22 @@ public partial class ObservableCollectionViewModel :
}
}
+ public bool Replace(int index, TItem item)
+ {
+ if (index <= Count - 1)
+ {
+ RemoveItem(index);
+ }
+ else
+ {
+ index = Count;
+ }
+
+ Insert(index, item);
+
+ return true;
+ }
+
public bool Move(int index, TItem item)
{
int oldIndex = collection.IndexOf(item);
diff --git a/Hyperbar/Mediators/Created.cs b/Hyperbar/Mediators/Created.cs
index d9c8cd6..9700768 100644
--- a/Hyperbar/Mediators/Created.cs
+++ b/Hyperbar/Mediators/Created.cs
@@ -2,4 +2,4 @@
namespace Hyperbar;
public record Created(TValue Value, object? Target = null) :
- INotification;
+ INotification;
\ No newline at end of file
diff --git a/Hyperbar/Mediators/Replaced.cs b/Hyperbar/Mediators/Replaced.cs
new file mode 100644
index 0000000..db91333
--- /dev/null
+++ b/Hyperbar/Mediators/Replaced.cs
@@ -0,0 +1,6 @@
+
+namespace Hyperbar;
+
+public record Replaced(int Index, TValue Value, object? Target = null) :
+ INotification;
+