diff --git a/Harmonia.WinUI/App.xaml b/Harmonia.WinUI/App.xaml
index 7eeb327..ff8b1e2 100644
--- a/Harmonia.WinUI/App.xaml
+++ b/Harmonia.WinUI/App.xaml
@@ -9,6 +9,10 @@
+
+
+
+
diff --git a/Harmonia.WinUI/App.xaml.cs b/Harmonia.WinUI/App.xaml.cs
index d6b7a73..f7819d9 100644
--- a/Harmonia.WinUI/App.xaml.cs
+++ b/Harmonia.WinUI/App.xaml.cs
@@ -1,50 +1,46 @@
-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 Harmonia.Core.Extensions;
+using Harmonia.WinUI.Caching;
+using Harmonia.WinUI.Storage;
+using Harmonia.WinUI.ViewModels;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.UI.Xaml;
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 Harmonia.WinUI;
-namespace Harmonia.WinUI
+public partial class App : Application
{
- ///
- /// Provides application-specific behavior to supplement the default Application class.
- ///
- public partial class App : Application
+ private Window? _mainWindow;
+
+ public static IServiceProvider ServiceProvider { get; private set; }
+
+ static App()
{
- ///
- /// 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();
- }
+ ServiceCollection services = new();
- ///
- /// 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();
- }
+ services.AddSingleton();
- private Window? m_window;
+ //services.AddSingleton();
+ services.AddSingleton();
+ //services.AddSingleton();
+ services.AddSingleton();
+
+ services.AddSingleton();
+ services.AddSingleton();
+
+ services.AddHarmonia();
+
+ ServiceProvider = services.BuildServiceProvider();
}
-}
+
+ public App()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnLaunched(LaunchActivatedEventArgs args)
+ {
+ _mainWindow = ServiceProvider.GetRequiredService();
+ _mainWindow.Activate();
+ }
+}
\ No newline at end of file
diff --git a/Harmonia.WinUI/Converters/DoubleToPercentConverter.cs b/Harmonia.WinUI/Converters/DoubleToPercentConverter.cs
new file mode 100644
index 0000000..943d764
--- /dev/null
+++ b/Harmonia.WinUI/Converters/DoubleToPercentConverter.cs
@@ -0,0 +1,25 @@
+using Microsoft.UI.Xaml.Data;
+using System;
+
+namespace Harmonia.WinUI.Converters;
+
+public sealed partial class DoubleToPercentConverter : IValueConverter
+{
+ public DoubleToPercentConverter()
+ {
+
+ }
+
+ public object? Convert(object value, Type targetType, object parameter, string language)
+ {
+ if (value is not double doubleValue)
+ return null;
+
+ return Math.Round(doubleValue * 100) + "%";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Harmonia.WinUI/Harmonia.WinUI.csproj b/Harmonia.WinUI/Harmonia.WinUI.csproj
index cafa830..a426bfa 100644
--- a/Harmonia.WinUI/Harmonia.WinUI.csproj
+++ b/Harmonia.WinUI/Harmonia.WinUI.csproj
@@ -14,6 +14,10 @@
true
enable
+
+
+
+
@@ -46,7 +50,23 @@
-
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ MSBuild:Compile
+
+
+
+
+ MSBuild:Compile
+
+
+
+
+
+
+
+
+
+
diff --git a/Harmonia.WinUI/MainWindow.xaml.cs b/Harmonia.WinUI/MainWindow.xaml.cs
index a0ddcf0..bca50a0 100644
--- a/Harmonia.WinUI/MainWindow.xaml.cs
+++ b/Harmonia.WinUI/MainWindow.xaml.cs
@@ -30,7 +30,7 @@ namespace Harmonia.WinUI
private void myButton_Click(object sender, RoutedEventArgs e)
{
- myButton.Content = "Clicked";
+ //myButton.Content = "Clicked";
}
}
}
diff --git a/Harmonia.WinUI/Resources/Converters.xaml b/Harmonia.WinUI/Resources/Converters.xaml
new file mode 100644
index 0000000..cfbe23c
--- /dev/null
+++ b/Harmonia.WinUI/Resources/Converters.xaml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Harmonia.WinUI/Resources/Geometry.xaml b/Harmonia.WinUI/Resources/Geometry.xaml
new file mode 100644
index 0000000..78f6bb3
--- /dev/null
+++ b/Harmonia.WinUI/Resources/Geometry.xaml
@@ -0,0 +1,125 @@
+
+
+
+
+ M10.804 8 5 4.633v6.734zm.792-.696a.802.802 0 0 1 0 1.392l-6.363 3.692C4.713 12.69 4 12.345 4 11.692V4.308c0-.653.713-.998 1.233-.696z
+
+
+
+ m11.596 8.697-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.39
+
+
+
+ M3.5 5A1.5 1.5 0 0 1 5 3.5h6A1.5 1.5 0 0 1 12.5 5v6a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 11zM5 4.5a.5.5 0 0 0-.5.5v6a.5.5 0 0 0 .5.5h6a.5.5 0 0 0 .5-.5V5a.5.5 0 0 0-.5-.5z
+
+
+
+ M5 3.5h6A1.5 1.5 0 0 1 12.5 5v6a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 11V5A1.5 1.5 0 0 1 5 3.5
+
+
+
+ M6 3.5a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-1 0V4a.5.5 0 0 1 .5-.5m4 0a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-1 0V4a.5.5 0 0 1 .5-.5
+
+
+
+ M5.5 3.5A1.5 1.5 0 0 1 7 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5m5 0A1.5 1.5 0 0 1 12 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5
+
+
+
+ M4 4a.5.5 0 0 1 1 0v3.248l6.267-3.636c.52-.302 1.233.043 1.233.696v7.384c0 .653-.713.998-1.233.696L5 8.752V12a.5.5 0 0 1-1 0zm7.5.633L5.696 8l5.804 3.367z
+
+
+
+ M4 4a.5.5 0 0 1 1 0v3.248l6.267-3.636c.54-.313 1.232.066 1.232.696v7.384c0 .63-.692 1.01-1.232.697L5 8.753V12a.5.5 0 0 1-1 0z
+
+
+
+ M12.5 4a.5.5 0 0 0-1 0v3.248L5.233 3.612C4.713 3.31 4 3.655 4 4.308v7.384c0 .653.713.998 1.233.696L11.5 8.752V12a.5.5 0 0 0 1 0zM5 4.633 10.804 8 5 11.367z
+
+
+
+ M12.5 4a.5.5 0 0 0-1 0v3.248L5.233 3.612C4.693 3.3 4 3.678 4 4.308v7.384c0 .63.692 1.01 1.233.697L11.5 8.753V12a.5.5 0 0 0 1 0z
+
+
+
+ M6.717 3.55A.5.5 0 0 1 7 4v8a.5.5 0 0 1-.812.39L3.825 10.5H1.5A.5.5 0 0 1 1 10V6a.5.5 0 0 1 .5-.5h2.325l2.363-1.89a.5.5 0 0 1 .529-.06
+ M13.854 5.646a.5.5 0 0 1 0 .708L12.207 8l1.647 1.646a.5.5 0 0 1-.708.708L11.5 8.707l-1.646 1.647a.5.5 0 0 1-.708-.708L10.793 8 9.146 6.354a.5.5 0 1 1 .708-.708L11.5 7.293l1.646-1.647a.5.5 0 0 1 .708 0
+
+
+
+ M8.707 11.182A4.5 4.5 0 0 0 10.025 8a4.5 4.5 0 0 0-1.318-3.182L8 5.525A3.5 3.5 0 0 1 9.025 8 3.5 3.5 0 0 1 8 10.475z
+ M6.717 3.55A.5.5 0 0 1 7 4v8a.5.5 0 0 1-.812.39L3.825 10.5H1.5A.5.5 0 0 1 1 10V6a.5.5 0 0 1 .5-.5h2.325l2.363-1.89a.5.5 0 0 1 .529-.06
+
+
+
+ M8.707 11.182A4.5 4.5 0 0 0 10.025 8a4.5 4.5 0 0 0-1.318-3.182L8 5.525A3.5 3.5 0 0 1 9.025 8 3.5 3.5 0 0 1 8 10.475z
+ M6.717 3.55A.5.5 0 0 1 7 4v8a.5.5 0 0 1-.812.39L3.825 10.5H1.5A.5.5 0 0 1 1 10V6a.5.5 0 0 1 .5-.5h2.325l2.363-1.89a.5.5 0 0 1 .529-.06
+
+
+
+ M10.121 12.596A6.48 6.48 0 0 0 12.025 8a6.48 6.48 0 0 0-1.904-4.596l-.707.707A5.48 5.48 0 0 1 11.025 8a5.48 5.48 0 0 1-1.61 3.89z
+ M8.707 11.182A4.5 4.5 0 0 0 10.025 8a4.5 4.5 0 0 0-1.318-3.182L8 5.525A3.5 3.5 0 0 1 9.025 8 3.5 3.5 0 0 1 8 10.475z
+ M6.717 3.55A.5.5 0 0 1 7 4v8a.5.5 0 0 1-.812.39L3.825 10.5H1.5A.5.5 0 0 1 1 10V6a.5.5 0 0 1 .5-.5h2.325l2.363-1.89a.5.5 0 0 1 .529-.06
+
+
+
+ M11.536 14.01A8.47 8.47 0 0 0 14.026 8a8.47 8.47 0 0 0-2.49-6.01l-.708.707A7.48 7.48 0 0 1 13.025 8c0 2.071-.84 3.946-2.197 5.303z
+ M10.121 12.596A6.48 6.48 0 0 0 12.025 8a6.48 6.48 0 0 0-1.904-4.596l-.707.707A5.48 5.48 0 0 1 11.025 8a5.48 5.48 0 0 1-1.61 3.89z
+ M8.707 11.182A4.5 4.5 0 0 0 10.025 8a4.5 4.5 0 0 0-1.318-3.182L8 5.525A3.5 3.5 0 0 1 9.025 8 3.5 3.5 0 0 1 8 10.475z
+ M6.717 3.55A.5.5 0 0 1 7 4v8a.5.5 0 0 1-.812.39L3.825 10.5H1.5A.5.5 0 0 1 1 10V6a.5.5 0 0 1 .5-.5h2.325l2.363-1.89a.5.5 0 0 1 .529-.06
+
+
+
+ M0 3.5A.5.5 0 0 1 .5 3H1c2.202 0 3.827 1.24 4.874 2.418.49.552.865 1.102 1.126 1.532.26-.43.636-.98 1.126-1.532C9.173 4.24 10.798 3 13 3v1c-1.798 0-3.173 1.01-4.126 2.082A9.6 9.6 0 0 0 7.556 8a9.6 9.6 0 0 0 1.317 1.918C9.828 10.99 11.204 12 13 12v1c-2.202 0-3.827-1.24-4.874-2.418A10.6 10.6 0 0 1 7 9.05c-.26.43-.636.98-1.126 1.532C4.827 11.76 3.202 13 1 13H.5a.5.5 0 0 1 0-1H1c1.798 0 3.173-1.01 4.126-2.082A9.6 9.6 0 0 0 6.444 8a9.6 9.6 0 0 0-1.317-1.918C4.172 5.01 2.796 4 1 4H.5a.5.5 0 0 1-.5-.5
+ M13 5.466V1.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384l-2.36 1.966a.25.25 0 0 1-.41-.192
+ M13 14.466v-3.932a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384l-2.36 1.966a.25.25 0 0 1-.41-.192
+
+
+
+ M11 5.466V4H5a4 4 0 0 0-3.584 5.777.5.5 0 1 1-.896.446A5 5 0 0 1 5 3h6V1.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384l-2.36 1.966a.25.25 0 0 1-.41-.192m3.81.086a.5.5 0 0 1 .67.225A5 5 0 0 1 11 13H5v1.466a.25.25 0 0 1-.41.192l-2.36-1.966a.25.25 0 0 1 0-.384l2.36-1.966a.25.25 0 0 1 .41.192V12h6a4 4 0 0 0 3.585-5.777.5.5 0 0 1 .225-.67Z
+
+
+
+ M11 4v1.466a.25.25 0 0 0 .41.192l2.36-1.966a.25.25 0 0 0 0-.384l-2.36-1.966a.25.25 0 0 0-.41.192V3H5a5 5 0 0 0-4.48 7.223.5.5 0 0 0 .896-.446A4 4 0 0 1 5 4zm4.48 1.777a.5.5 0 0 0-.896.446A4 4 0 0 1 11 12H5.001v-1.466a.25.25 0 0 0-.41-.192l-2.36 1.966a.25.25 0 0 0 0 .384l2.36 1.966a.25.25 0 0 0 .41-.192V13h6a5 5 0 0 0 4.48-7.223Z
+ M9 5.5a.5.5 0 0 0-.854-.354l-1.75 1.75a.5.5 0 1 0 .708.708L8 6.707V10.5a.5.5 0 0 0 1 0z
+
+
+
+ M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z
+ M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z
+
+
+
+ M3.5 3.5c-.614-.884-.074-1.962.858-2.5L8 7.226 11.642 1c.932.538 1.472 1.616.858 2.5L8.81 8.61l1.556 2.661a2.5 2.5 0 1 1-.794.637L8 9.73l-1.572 2.177a2.5 2.5 0 1 1-.794-.637L7.19 8.61zm2.5 10a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0m7 0a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0
+
+
+
+ M4 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1zM2 5a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1h1v1a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h1v1z
+
+
+
+ M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1z
+ M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0z
+
+
+
+ M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2z
+ M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466
+
+
+
+ M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492M5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0
+ M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115z
+
+
+
+ M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2m3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2M5 8h6a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1
+
+
+
+ M11 1a2 2 0 0 0-2 2v4a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h5V3a3 3 0 0 1 6 0v4a.5.5 0 0 1-1 0V3a2 2 0 0 0-2-2M3 8a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1z
+
+
+
diff --git a/Harmonia.WinUI/Resources/Styles.xaml b/Harmonia.WinUI/Resources/Styles.xaml
new file mode 100644
index 0000000..afea6c8
--- /dev/null
+++ b/Harmonia.WinUI/Resources/Styles.xaml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Harmonia.WinUI/Resources/ViewModels.xaml b/Harmonia.WinUI/Resources/ViewModels.xaml
new file mode 100644
index 0000000..4d78336
--- /dev/null
+++ b/Harmonia.WinUI/Resources/ViewModels.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/Harmonia.WinUI/ViewModels/PlaylistViewModel.cs b/Harmonia.WinUI/ViewModels/PlaylistViewModel.cs
index 00e4e5f..e3d61ba 100644
--- a/Harmonia.WinUI/ViewModels/PlaylistViewModel.cs
+++ b/Harmonia.WinUI/ViewModels/PlaylistViewModel.cs
@@ -9,7 +9,6 @@ using Harmonia.WinUI.Storage;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml.Media.Imaging;
using System;
-using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
@@ -21,7 +20,6 @@ using System.Threading.Tasks;
using System.Timers;
using System.Windows.Input;
using Windows.ApplicationModel.DataTransfer;
-using Windows.Storage;
using Timer = System.Timers.Timer;
namespace Harmonia.WinUI.ViewModels;
@@ -116,6 +114,8 @@ public partial class PlaylistViewModel : ViewModelBase
public ICommand RemoveMissingSongsCommand => new RelayCommand(RemoveMissingSongs);
public ICommand RemoveDuplicateSongsCommand => new RelayCommand(RemoveDuplicateSongs);
+ public bool IsUserUpdating { get; set; }
+
public PlaylistViewModel(
IAudioPlayer audioPlayer,
IAudioBitmapImageCache audioBitmapImageCache,
@@ -155,6 +155,9 @@ public partial class PlaylistViewModel : ViewModelBase
private void OnPlaylistUpdated(object? sender, PlaylistUpdatedEventArgs e)
{
+ if (IsUserUpdating)
+ return;
+
switch (e.Action)
{
case PlaylistUpdateAction.Add:
@@ -191,7 +194,6 @@ public partial class PlaylistViewModel : ViewModelBase
private void OnPlayingSongChanged(object? sender, EventArgs e)
{
- //OnPropertyChanged(nameof(PlayingSong));
PlayingSong = _audioPlayer.PlayingSong;
}
diff --git a/Harmonia.WinUI/ViewModels/ViewModelLocator.cs b/Harmonia.WinUI/ViewModels/ViewModelLocator.cs
new file mode 100644
index 0000000..aa8cde5
--- /dev/null
+++ b/Harmonia.WinUI/ViewModels/ViewModelLocator.cs
@@ -0,0 +1,18 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Harmonia.WinUI.ViewModels;
+
+public class ViewModelLocator
+{
+ //public static MainViewModel MainViewModel
+ // => App.ServiceProvider.GetRequiredService();
+
+ public static PlayerViewModel PlayerViewModel
+ => App.ServiceProvider.GetRequiredService();
+
+ //public static PlayingSongInfoViewModel PlayingSongInfoViewModel
+ // => App.ServiceProvider.GetRequiredService();
+
+ public static PlaylistViewModel PlaylistViewModel
+ => App.ServiceProvider.GetRequiredService();
+}
\ No newline at end of file
diff --git a/Harmonia.WinUI/Views/PlayerView.xaml b/Harmonia.WinUI/Views/PlayerView.xaml
new file mode 100644
index 0000000..36ab7db
--- /dev/null
+++ b/Harmonia.WinUI/Views/PlayerView.xaml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Harmonia.WinUI/Views/PlayerView.xaml.cs b/Harmonia.WinUI/Views/PlayerView.xaml.cs
new file mode 100644
index 0000000..9d4a515
--- /dev/null
+++ b/Harmonia.WinUI/Views/PlayerView.xaml.cs
@@ -0,0 +1,68 @@
+using Harmonia.WinUI.ViewModels;
+using Microsoft.UI.Input;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Input;
+
+namespace Harmonia.WinUI.Views;
+
+public sealed partial class PlayerView : UserControl
+{
+ private readonly PlayerViewModel _viewModel;
+
+ public PlayerView()
+ {
+ InitializeComponent();
+ _viewModel = (PlayerViewModel)DataContext;
+ }
+
+ private void PositionSlider_Loaded(object? sender, RoutedEventArgs e)
+ {
+ if (sender is not Slider slider)
+ return;
+
+ PointerEventHandler pointerPressedHandler = new(OnSliderPointerPressed);
+ slider.AddHandler(PointerPressedEvent, pointerPressedHandler, true);
+
+ PointerEventHandler pointerReleasedHandler = new(OnSliderPointerReleased);
+ slider.AddHandler(PointerReleasedEvent, pointerReleasedHandler, true);
+ }
+
+ private void OnSliderPointerPressed(object? sender, PointerRoutedEventArgs e)
+ {
+ if (sender is not Slider slider)
+ return;
+
+ PointerPointProperties pointerProperties = e.GetCurrentPoint(slider).Properties;
+
+ if (pointerProperties.IsLeftButtonPressed == false)
+ return;
+
+ _viewModel.IsPositionChangeInProgress = true;
+ }
+
+ private void OnSliderPointerReleased(object? sender, PointerRoutedEventArgs e)
+ {
+ if (sender is not Slider slider)
+ return;
+
+ _viewModel.CurrentPosition = slider.Value;
+ _viewModel.IsPositionChangeInProgress = false;
+ }
+
+ private void VolumeSlider_PointerWheelChanged(object? sender, PointerRoutedEventArgs e)
+ {
+ if (sender is not Slider slider)
+ return;
+
+ var pointerProperties = e.GetCurrentPoint(slider).Properties;
+ var mouseWheelDelta = pointerProperties.MouseWheelDelta;
+
+ if (mouseWheelDelta == 0)
+ return;
+
+ double delta = mouseWheelDelta > 0 ? .02 : -.02;
+
+ _viewModel.Volume += delta;
+ }
+}
\ No newline at end of file