From d37d284b58ec2121c1644a8bfe33b7d1f8399a0d Mon Sep 17 00:00:00 2001 From: Miaoyww Date: Sun, 20 Oct 2024 00:49:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=AD=8C=E8=AF=8D=E5=9F=BA=E7=A1=80=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=8A=9F=E8=83=BD=20#66?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NonsPlayer.Core/AMLL/Models/LyricLine.cs | 2 +- .../ViewModels/LyricCardViewModel.cs | 32 ++- .../AMLL/Components/Views/LyricCard.xaml | 11 +- NonsPlayer/AMLL/Helpers/LyricHelper.cs | 21 ++ NonsPlayer/AMLL/ViewModels/AMLLViewModel.cs | 2 +- NonsPlayer/AMLL/Views/AMLL.xaml.cs | 18 -- .../AMLL/Views/{AMLL.xaml => AMLLCard.xaml} | 20 +- NonsPlayer/AMLL/Views/AMLLCard.xaml.cs | 114 +++++++++ NonsPlayer/App.xaml.cs | 40 ++- NonsPlayer/Components/Views/PlayBar.xaml.cs | 10 +- NonsPlayer/Helpers/UiHelper.cs | 21 +- NonsPlayer/Helpers/WindowUtility.cs | 132 ++++++++++ NonsPlayer/MainWindow.xaml | 2 + NonsPlayer/MainWindow.xaml.cs | 1 + NonsPlayer/NativeMethods.txt | 1 - NonsPlayer/NonsPlayer.csproj | 229 ++++++++++-------- NonsPlayer/Services/ActivationService.cs | 1 + NonsPlayer/Services/NavigationService.cs | 19 ++ NonsPlayer/Styles/Thickness.xaml | 1 + NonsPlayer/ViewModels/Pages/LyricViewModel.cs | 99 +++++++- NonsPlayer/ViewModels/ShellViewModel.cs | 2 +- NonsPlayer/Views/Pages/LyricPage.xaml | 166 ++++++++++++- NonsPlayer/Views/Pages/LyricPage.xaml.cs | 220 +++++------------ NonsPlayer/Views/ShellPage.xaml | 36 +-- NonsPlayer/Views/ShellPage.xaml.cs | 44 ++-- global.json | 3 +- 26 files changed, 874 insertions(+), 373 deletions(-) create mode 100644 NonsPlayer/AMLL/Helpers/LyricHelper.cs delete mode 100644 NonsPlayer/AMLL/Views/AMLL.xaml.cs rename NonsPlayer/AMLL/Views/{AMLL.xaml => AMLLCard.xaml} (74%) create mode 100644 NonsPlayer/AMLL/Views/AMLLCard.xaml.cs create mode 100644 NonsPlayer/Helpers/WindowUtility.cs delete mode 100644 NonsPlayer/NativeMethods.txt diff --git a/NonsPlayer.Core/AMLL/Models/LyricLine.cs b/NonsPlayer.Core/AMLL/Models/LyricLine.cs index fb2cf26..a280ab3 100644 --- a/NonsPlayer.Core/AMLL/Models/LyricLine.cs +++ b/NonsPlayer.Core/AMLL/Models/LyricLine.cs @@ -11,7 +11,7 @@ public class LyricLine public string? Pure { get; set; } public string? Translation { get; set; } - public bool HaveTranslation => !string.IsNullOrEmpty(Translation); + public bool HasTranslation => !string.IsNullOrEmpty(Translation); /// /// 是否为纯音乐 diff --git a/NonsPlayer/AMLL/Components/ViewModels/LyricCardViewModel.cs b/NonsPlayer/AMLL/Components/ViewModels/LyricCardViewModel.cs index 27b5d9a..fdf735b 100644 --- a/NonsPlayer/AMLL/Components/ViewModels/LyricCardViewModel.cs +++ b/NonsPlayer/AMLL/Components/ViewModels/LyricCardViewModel.cs @@ -2,8 +2,12 @@ using Microsoft.UI; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Media; +using NonsPlayer.AMLL.Components.Views; +using NonsPlayer.AMLL.Helpers; using NonsPlayer.AMLL.Models; using NonsPlayer.Core.AMLL.Models; +using NonsPlayer.Helpers; +using Windows.UI; namespace NonsPlayer.AMLL.Components.ViewModels; @@ -18,23 +22,33 @@ public sealed partial class LyricCardViewModel : ObservableObject [ObservableProperty] public Visibility transVisibility; + public LyricCardViewModel() + { + Foreground = new SolidColorBrush(Color.FromArgb(255, 240, 240, 240)); + LyricHelper.Instance.LyricChanged += OnLyricChanged; + } + partial void OnLyricModelChanged(LyricItemModel value) { - TransVisibility = value.Lyric.HaveTranslation ? Visibility.Visible : Visibility.Collapsed; + TransVisibility = value.Lyric.HasTranslation ? Visibility.Visible : Visibility.Collapsed; } - private void OnLyricChanged(int i) + private void OnLyricChanged(LyricLine lyric) { try { - if (i - 1 == Index) - { - Foreground = new SolidColorBrush(Colors.White); - } - else + if (LyricModel == null) return; + ServiceHelper.DispatcherQueue.TryEnqueue(() => { - Foreground = Application.Current.Resources["TextFillColorTertiaryBrush"] as SolidColorBrush; - } + if (lyric.Equals(LyricModel.Lyric)) + { + Foreground = new SolidColorBrush(Colors.White); + } + else + { + Foreground = Application.Current.Resources["TextFillColorTertiaryBrush"] as SolidColorBrush; + } + }); } catch { diff --git a/NonsPlayer/AMLL/Components/Views/LyricCard.xaml b/NonsPlayer/AMLL/Components/Views/LyricCard.xaml index ea5644a..29157f3 100644 --- a/NonsPlayer/AMLL/Components/Views/LyricCard.xaml +++ b/NonsPlayer/AMLL/Components/Views/LyricCard.xaml @@ -5,9 +5,6 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Background="{ThemeResource SolidBackgroundFillColorBaseBrush}" - xmlns:media="using:CommunityToolkit.WinUI.Media" - xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls" - xmlns:models="using:NonsPlayer.AMLL.Models" mc:Ignorable="d"> @@ -17,17 +14,17 @@ + FontWeight="Bold" FontSize="40" /> + FontWeight="Bold" /> \ No newline at end of file diff --git a/NonsPlayer/AMLL/Helpers/LyricHelper.cs b/NonsPlayer/AMLL/Helpers/LyricHelper.cs new file mode 100644 index 0000000..d149dfb --- /dev/null +++ b/NonsPlayer/AMLL/Helpers/LyricHelper.cs @@ -0,0 +1,21 @@ +using NonsPlayer.AMLL.Models; +using NonsPlayer.Core.AMLL.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static NonsPlayer.Core.Nons.Player.Player; + +namespace NonsPlayer.AMLL.Helpers; + +public class LyricHelper +{ + public static LyricHelper Instance { get; } = new(); + + public int LyricPosition; + + public delegate void LyricChangedHandler(LyricLine time); + + public LyricChangedHandler? LyricChanged; +} \ No newline at end of file diff --git a/NonsPlayer/AMLL/ViewModels/AMLLViewModel.cs b/NonsPlayer/AMLL/ViewModels/AMLLViewModel.cs index 566aef9..2d44227 100644 --- a/NonsPlayer/AMLL/ViewModels/AMLLViewModel.cs +++ b/NonsPlayer/AMLL/ViewModels/AMLLViewModel.cs @@ -14,7 +14,6 @@ public partial class AMLLViewModel : ObservableRecipient { public ObservableCollection LyricItems = new(); [ObservableProperty] private IMusic currentMusic; - public int LyricPosition; #region 命令 @@ -39,6 +38,7 @@ public AMLLViewModel() private async void OnMusicChanged(IMusic value) { LyricItems.Clear(); + if (value.Lyric == null) { LyricItems.Add(new LyricCombiner diff --git a/NonsPlayer/AMLL/Views/AMLL.xaml.cs b/NonsPlayer/AMLL/Views/AMLL.xaml.cs deleted file mode 100644 index a7c6eea..0000000 --- a/NonsPlayer/AMLL/Views/AMLL.xaml.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using NonsPlayer.AMLL.ViewModels; - -namespace NonsPlayer.AMLL.Views; - -public sealed partial class AMLL : UserControl -{ - public AMLLViewModel ViewModel - { - get; - } - - public AMLL() - { - ViewModel = App.GetService(); - InitializeComponent(); - } -} \ No newline at end of file diff --git a/NonsPlayer/AMLL/Views/AMLL.xaml b/NonsPlayer/AMLL/Views/AMLLCard.xaml similarity index 74% rename from NonsPlayer/AMLL/Views/AMLL.xaml rename to NonsPlayer/AMLL/Views/AMLLCard.xaml index 552ecdf..4a54b84 100644 --- a/NonsPlayer/AMLL/Views/AMLL.xaml +++ b/NonsPlayer/AMLL/Views/AMLLCard.xaml @@ -1,5 +1,5 @@  - + - - - - - + + - + - - + + diff --git a/NonsPlayer/AMLL/Views/AMLLCard.xaml.cs b/NonsPlayer/AMLL/Views/AMLLCard.xaml.cs new file mode 100644 index 0000000..f562755 --- /dev/null +++ b/NonsPlayer/AMLL/Views/AMLLCard.xaml.cs @@ -0,0 +1,114 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using NonsPlayer.AMLL.Helpers; +using NonsPlayer.AMLL.ViewModels; +using NonsPlayer.Core.Contracts.Models.Music; +using NonsPlayer.Core.Nons.Player; +using NonsPlayer.Helpers; + +namespace NonsPlayer.AMLL.Views; + +public sealed partial class AMLLCard : UserControl +{ + public AMLLViewModel ViewModel + { + get; + } + + public AMLLCard() + { + ViewModel = App.GetService(); + InitializeComponent(); + Player.Instance.PositionChanged += OnPositionChanged; + Player.Instance.MusicChanged += MusicChanged; + } + + private void MusicChanged(IMusic currentmusic) + { + LyricHelper.Instance.LyricPosition = 0; + } + + private void OnPositionChanged(TimeSpan time) + { + // 判断是否需要滚动歌词 + if (ViewModel.LyricItems.Count == 0) return; + + var lyric = ViewModel.LyricItems[LyricHelper.Instance.LyricPosition]; + // 控制ListView滚动 + if (lyric.LyricItemModel.Lyric.StartTime <= time) + { + if (LyricHelper.Instance.LyricPosition < ViewModel.LyricItems.Count - 1) + { + LyricHelper.Instance.LyricPosition++; + LyricHelper.Instance.LyricChanged.Invoke(lyric.LyricItemModel.Lyric); + DispatcherQueue.TryEnqueue(() => + { + ScrollLyric(); + }); + } + } + } + + private void ScrollLyric() + { + try + { + try + { + if (LyricHelper.Instance.LyricPosition == -1) + { + LyricBoxContainer.ChangeView(null, 0, null, false); + return; + } + + var item = LyricBox.Items[LyricHelper.Instance.LyricPosition]; + DispatcherQueue.TryEnqueue(() => + { + LyricBox.ScrollIntoView(item); + }); + } + catch (Exception ex) + { + // Log the error if needed + } + + // var item = ViewModel.LyricItems[ViewModel.LyricPosition]; + // var k = LyricBox.ItemsSourceView.IndexOf(item); + // UIElement actualElement; + // bool isNewLoaded = false; + // if (LyricBox.TryGetElement(k) is { } ele) + // { + // actualElement = ele; + // } + // else + // { + // actualElement = LyricBox.GetOrCreateElement(k) as Border; + // isNewLoaded = true; + // } + // + // if (actualElement != null && item != null && + // !string.IsNullOrEmpty(item.LyricItemModel.Lyric.Pure)) + // { + // actualElement.UpdateLayout(); + // actualElement.StartBringIntoView(); + // + // if (!isNewLoaded) + // { + // var transform = actualElement?.TransformToVisual((UIElement)LyricBoxContainer.ContentTemplateRoot); + // var position = transform?.TransformPoint(new Windows.Foundation.Point(0, 0)); + // LyricBoxContainer.ChangeView(0, + // (position?.Y + LyricHost.Margin.Top - MainGrid.ActualHeight / 4) - 200, 1, + // false); + // } + // else + // { + // // actualElement.StartBringIntoView(NoAnimationBringIntoViewOptions); + // } + // } + } + catch + { + // igrone pls + } + } +} \ No newline at end of file diff --git a/NonsPlayer/App.xaml.cs b/NonsPlayer/App.xaml.cs index a5c6563..f874e29 100644 --- a/NonsPlayer/App.xaml.cs +++ b/NonsPlayer/App.xaml.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.UI; using Microsoft.UI.Dispatching; using Microsoft.UI.Xaml; using NonsPlayer.Activation; @@ -26,12 +27,16 @@ using Windows.Graphics.Display; using UnhandledExceptionEventArgs = Microsoft.UI.Xaml.UnhandledExceptionEventArgs; using WinRT; +using LyricViewModel = NonsPlayer.AMLL.ViewModels.AMLLViewModel; +using NonsPlayer.AMLL.Views; namespace NonsPlayer; // To learn more about WinUI 3, see https://docs.microsoft.com/windows/apps/winui/winui3/. public partial class App : Application -{ +{ + public static IntPtr WindowHandle { get; set; } + public App() { InitializeComponent(); @@ -91,8 +96,8 @@ public App() services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -140,13 +145,14 @@ public App() #endregion - // AMLL - services.AddTransient(); + // Lyric + services.AddTransient(); services.AddTransient(); }).Build(); GetService().Initialize(); UnhandledException += App_UnhandledException; + #region Config @@ -185,6 +191,7 @@ public App() GetService().LoadFromFile(); #endregion + #region Counter Log.Information($"Start loading player counter"); @@ -199,7 +206,7 @@ public App() GetService().Init(); #endregion - + } private void OnLocalLoadFailed(string param) @@ -243,12 +250,21 @@ public static T GetService() private void App_UnhandledException(object sender, UnhandledExceptionEventArgs e) { - Log.Error($"App Version:{GetService().CurrentVersion}\n" + - $"Current Music:{MusicStateModel.Instance.CurrentMusic.Name}\n" + - $"Position: {MusicStateModel.Instance.Position} / {MusicStateModel.Instance.Duration.TotalMilliseconds} \n" + - $"MixMode: {Player.Instance.IsMixed} \n" + - $"Adapter: {MusicStateModel.Instance.CurrentMusic.Adapter} \n" + - $"Unhandled exception threw: {e.Exception}"); + if (MusicStateModel.Instance.CurrentMusic != null) + { + Log.Error($"App Version:{GetService().CurrentVersion}\n" + + $"Current Music:{MusicStateModel.Instance.CurrentMusic.Name}\n" + + $"Position: {MusicStateModel.Instance.Position} / {MusicStateModel.Instance.Duration.TotalMilliseconds} \n" + + $"MixMode: {Player.Instance.IsMixed} \n" + + $"Adapter: {MusicStateModel.Instance.CurrentMusic.Adapter} \n" + + $"Unhandled exception threw: {e.Exception}"); + } + else + { + Log.Error($"App Version:{GetService().CurrentVersion}\n" + + $"Unhandled exception threw: {e.Exception}"); + } + ExceptionService.Instance.Throw(e.Exception); } diff --git a/NonsPlayer/Components/Views/PlayBar.xaml.cs b/NonsPlayer/Components/Views/PlayBar.xaml.cs index eeecea5..09088a5 100644 --- a/NonsPlayer/Components/Views/PlayBar.xaml.cs +++ b/NonsPlayer/Components/Views/PlayBar.xaml.cs @@ -26,7 +26,7 @@ public PlayBar() private ManipulationStartedRoutedEventArgs? _slidingEventArgs = null; private TimeSpan StartingTimeSpan = TimeSpan.Zero; private bool _isSliding = false; - + public PlayerBarViewModel ViewModel { get; } public event EventHandler OnPlayQueueBarOpenHandler; @@ -34,12 +34,8 @@ public PlayBar() [RelayCommand] public void OpenLyric() { - // if (ServiceHelper.NavigationService.Frame.Content.GetType().ToString() == typeof(LyricPage)?.FullName) - // { - // ServiceHelper.NavigationService.NavigateTo(ServiceHelper.NavigationService.LastPage, isBack: true); - // return; - // } ServiceHelper.NavigationService.NavigateTo(typeof(LyricViewModel)?.FullName); + UiHelper.Instance.LyricShow = Visibility.Visible; } [RelayCommand] @@ -66,7 +62,7 @@ private async Task LikeMusic() var state = await accountAdapter.IsLikedSong(MusicStateModel.Instance.CurrentMusic.Id); MusicStateModel.Instance.CurrentMusic.IsLiked = state; MusicStateModel.Instance.CurrentSongLiked = state; - + // // var dialog = new ContentDialog // { diff --git a/NonsPlayer/Helpers/UiHelper.cs b/NonsPlayer/Helpers/UiHelper.cs index f1ee935..4b66569 100644 --- a/NonsPlayer/Helpers/UiHelper.cs +++ b/NonsPlayer/Helpers/UiHelper.cs @@ -1,4 +1,5 @@ -using System.Numerics; +using CommunityToolkit.Mvvm.ComponentModel; +using System.Numerics; using System.Runtime.InteropServices; using Microsoft.UI; using Microsoft.UI.Composition; @@ -130,7 +131,7 @@ public static void UpdateTitleBar(ElementTheme theme) } } -public class UiHelper +public partial class UiHelper : ObservableObject { public static UiHelper Instance { get; } = new(); @@ -138,4 +139,20 @@ public class UiHelper public delegate void LyricChangedHandler(int index); public LyricChangedHandler LyricChanged; + + [ObservableProperty] private Visibility lyricShow = Visibility.Collapsed; + [ObservableProperty] private Visibility playBarShow = Visibility.Visible; + + partial void OnLyricShowChanged(Visibility value) + { + switch (value) + { + case Visibility.Collapsed: + PlayBarShow = Visibility.Visible; + break; + case Visibility.Visible: + PlayBarShow = Visibility.Collapsed; + break; + } + } } \ No newline at end of file diff --git a/NonsPlayer/Helpers/WindowUtility.cs b/NonsPlayer/Helpers/WindowUtility.cs new file mode 100644 index 0000000..d797e06 --- /dev/null +++ b/NonsPlayer/Helpers/WindowUtility.cs @@ -0,0 +1,132 @@ +using Microsoft.Extensions.Logging; +using Microsoft.UI; +using Microsoft.UI.Input; +using Microsoft.UI.Windowing; +using Microsoft.UI.Xaml; +using Vanara.PInvoke; +using Windows.Graphics; +using Windows.Win32; + +namespace NonsPlayer.Helpers; + +public static class WindowUtility +{ + private static readonly ILogger logger = App.GetLogger(); + + public static WindowId? CurrentWindowId; + + public static DisplayArea? CurrentWindowDisplayArea + { + get + { + if (!CurrentWindowId.HasValue) + { + return null; + } + + return DisplayArea.GetFromWindowId(CurrentWindowId.Value, DisplayAreaFallback.Primary); + } + } + + internal static double CurrentWindowMonitorScaleFactor + // Deliberate loss of precision + // ReSharper disable once PossibleLossOfFraction + => (CurrentWindowMonitorDpi * 100 + (96 >> 1)) / 96 / 100.0; + + public static nint CurrentWindowMonitorPtr + { + get + { + DisplayArea? displayArea = CurrentWindowDisplayArea; + if (displayArea == null) + { + return nint.Zero; + } + + nint monitorPtr = Win32Interop.GetMonitorFromDisplayId(displayArea.DisplayId); + return monitorPtr; + } + } + + public static uint CurrentWindowMonitorDpi + { + get + { + const uint DefaultDpiValue = 96; + nint monitorPtr = CurrentWindowMonitorPtr; + if (monitorPtr == nint.Zero) + { + return DefaultDpiValue; + } + + var dpi = User32.GetDpiForWindow(App.WindowHandle); + if (dpi == 0) + { + return dpi; + } + + logger.LogError( + $"[WindowUtility::CurrentWindowMonitorDpi] Could not get DPI for the current monitor at 0x{monitorPtr:x8}"); + return DefaultDpiValue; + } + } + + public static double UiScale => User32.GetDpiForWindow(new HWND(App.WindowHandle)) / 96d; + + public delegate int SetTitleBarDragRegionDelegate(InputNonClientPointerSource source, SizeInt32 size, + double scaleFactor, Func getScaledRect); + + /// + /// Informs the bearer to refresh the drag region. + /// will not set, , when titleBarHeight less than 0 + /// + /// + /// + /// + public static void RaiseSetTitleBarDragRegion(this Window window, + SetTitleBarDragRegionDelegate setTitleBarDragRegion) + { + if (!window.AppWindow.IsVisible) + return; + // UIElement.RasterizationScale is always 1 + var source = InputNonClientPointerSource.GetForWindowId(window.AppWindow.Id); + var uiElement = window.Content; + var xamlRoot = uiElement?.XamlRoot; + + if (xamlRoot is null) + return; + + var scaleFactor = xamlRoot.RasterizationScale; + var size = window.AppWindow.Size; + // If the number of regions is 0 or 1, AppWindow will automatically reset to the default region next time, but if it is >=2, it will not and need to be manually cleared + source.ClearRegionRects(NonClientRegionKind.Passthrough); + var titleBarHeight = setTitleBarDragRegion(source, size, scaleFactor, GetScaledRect); + if (titleBarHeight >= 0) + { + // region under the buttons + const int borderThickness = 5; + source.SetRegionRects(NonClientRegionKind.LeftBorder, + [GetScaledRect(uiElement, new(0, 0, borderThickness, titleBarHeight))]); + source.SetRegionRects(NonClientRegionKind.RightBorder, + [GetScaledRect(uiElement, new(size.Width, 0, borderThickness, titleBarHeight))]); + source.SetRegionRects(NonClientRegionKind.Caption, + [GetScaledRect(uiElement, new(0, 0, size.Width, titleBarHeight))]); + } + } + + private static RectInt32 GetScaledRect(this UIElement uiElement, RectInt32? r = null) + { + if (r is { } rect) + { + var scaleFactor = uiElement.XamlRoot.RasterizationScale; + return new((int)(rect.X * scaleFactor), (int)(rect.Y * scaleFactor), (int)(rect.Width * scaleFactor), + (int)(rect.Height * scaleFactor)); + } + else + { + var pos = uiElement.TransformToVisual(null).TransformPoint(new(0, 0)); + rect = new RectInt32((int)pos.X, (int)pos.Y, (int)uiElement.ActualSize.X, (int)uiElement.ActualSize.Y); + return GetScaledRect(uiElement, rect); + } + } +} \ No newline at end of file diff --git a/NonsPlayer/MainWindow.xaml b/NonsPlayer/MainWindow.xaml index c8160a0..bff7537 100644 --- a/NonsPlayer/MainWindow.xaml +++ b/NonsPlayer/MainWindow.xaml @@ -5,6 +5,8 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:windowex="using:WinUIEx" + xmlns:views="using:NonsPlayer.Views" + xmlns:pages="using:NonsPlayer.Views.Pages" MinHeight="780" MinWidth="1400" PersistenceId="MainWindow" diff --git a/NonsPlayer/MainWindow.xaml.cs b/NonsPlayer/MainWindow.xaml.cs index 045b154..a08e1dc 100644 --- a/NonsPlayer/MainWindow.xaml.cs +++ b/NonsPlayer/MainWindow.xaml.cs @@ -5,6 +5,7 @@ namespace NonsPlayer; public sealed partial class MainWindow : WindowEx { + public UiHelper UiHelper = UiHelper.Instance; public MainWindow() { InitializeComponent(); diff --git a/NonsPlayer/NativeMethods.txt b/NonsPlayer/NativeMethods.txt deleted file mode 100644 index 9ea1935..0000000 --- a/NonsPlayer/NativeMethods.txt +++ /dev/null @@ -1 +0,0 @@ -GetDpiForWindow \ No newline at end of file diff --git a/NonsPlayer/NonsPlayer.csproj b/NonsPlayer/NonsPlayer.csproj index d04f9d4..b0d37a5 100644 --- a/NonsPlayer/NonsPlayer.csproj +++ b/NonsPlayer/NonsPlayer.csproj @@ -4,10 +4,10 @@ net8.0-windows10.0.22621.0 10.0.17763.0 NonsPlayer - x86;x64;ARM64 - win10-x86;win10-x64;win10-arm64 - win10-$(Platform).pubxml - enable + x86;x64;ARM64 + win10-x86;win10-x64;win10-arm64 + win10-$(Platform).pubxml + enable enable true true @@ -25,31 +25,46 @@ true app.manifest - + - - - + + + - - runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + + + + + + + + + + + + + + + + + + + - - - - @@ -65,109 +80,109 @@ - - - - + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - $(DefaultXamlRuntime) - Designer - - - $(DefaultXamlRuntime) - Designer - - - $(DefaultXamlRuntime) - Designer - - - $(DefaultXamlRuntime) - - - $(DefaultXamlRuntime) - Designer - - - $(DefaultXamlRuntime) - - - MSBuild:Compile - + + $(DefaultXamlRuntime) + Designer + + + $(DefaultXamlRuntime) + Designer + + + $(DefaultXamlRuntime) + Designer + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + Designer + + + $(DefaultXamlRuntime) + + + MSBuild:Compile + - - $(DefaultXamlRuntime) - - - $(DefaultXamlRuntime) - Designer - - - $(DefaultXamlRuntime) - - - $(DefaultXamlRuntime) - Designer - MSBuild:Compile - + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + Designer + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + Designer + MSBuild:Compile + - - MSBuild:Compile - + + MSBuild:Compile + - + - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + diff --git a/NonsPlayer/Services/ActivationService.cs b/NonsPlayer/Services/ActivationService.cs index 458fccc..2ddc7e9 100644 --- a/NonsPlayer/Services/ActivationService.cs +++ b/NonsPlayer/Services/ActivationService.cs @@ -3,6 +3,7 @@ using NonsPlayer.Activation; using NonsPlayer.Contracts.Services; using NonsPlayer.Core.Services; +using NonsPlayer.Helpers; using NonsPlayer.Views; using NonsPlayer.Views.Pages; diff --git a/NonsPlayer/Services/NavigationService.cs b/NonsPlayer/Services/NavigationService.cs index 47321fa..25c25e8 100644 --- a/NonsPlayer/Services/NavigationService.cs +++ b/NonsPlayer/Services/NavigationService.cs @@ -1,10 +1,12 @@ using Microsoft.Extensions.Logging; +using Microsoft.UI.Xaml; using System.Diagnostics.CodeAnalysis; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using NonsPlayer.Contracts.Services; using NonsPlayer.Contracts.ViewModels; using NonsPlayer.Helpers; +using NonsPlayer.Views.Pages; namespace NonsPlayer.Services; @@ -51,13 +53,28 @@ public Frame? Frame [MemberNotNullWhen(true, nameof(Frame), nameof(_frame))] public bool CanGoBack => Frame != null && Frame.CanGoBack; + private void CheckLyricPage(object type) + { + if (type is LyricPage) + { + UiHelper.Instance.LyricShow = Visibility.Visible; + } + else + { + UiHelper.Instance.LyricShow = Visibility.Collapsed; + } + } public bool GoBack() { if (CanGoBack) { var vmBeforeNavigation = _frame.GetPageViewModel(); + + _frame.GoBack(); if (vmBeforeNavigation is INavigationAware navigationAware) navigationAware.OnNavigatedFrom(); + + CheckLyricPage(_frame.Content); logger.LogInformation("Page goes back"); return true; } @@ -82,6 +99,8 @@ public bool NavigateTo(string pageKey, object? parameter = null, bool clearNavig } logger.LogInformation("Navigate to {pageKey}", pageKey); + + CheckLyricPage(pageType); return navigated; } diff --git a/NonsPlayer/Styles/Thickness.xaml b/NonsPlayer/Styles/Thickness.xaml index 8f7a1c8..9d5c6ef 100644 --- a/NonsPlayer/Styles/Thickness.xaml +++ b/NonsPlayer/Styles/Thickness.xaml @@ -5,6 +5,7 @@ 20 0,54,0,0 60,20,60,0 + 0,0,0,0 0,0,0,100 45,80,45,100 diff --git a/NonsPlayer/ViewModels/Pages/LyricViewModel.cs b/NonsPlayer/ViewModels/Pages/LyricViewModel.cs index ab8e039..db05204 100644 --- a/NonsPlayer/ViewModels/Pages/LyricViewModel.cs +++ b/NonsPlayer/ViewModels/Pages/LyricViewModel.cs @@ -4,15 +4,112 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Media; using NonsPlayer.Components.Models; +using NonsPlayer.Core.AMLL.Models; +using NonsPlayer.Core.Contracts.Models.Music; using NonsPlayer.Core.Models; using NonsPlayer.Core.Nons.Player; using NonsPlayer.Helpers; using NonsPlayer.Services; using NonsPlayer.Views.Pages; +using static Vanara.PInvoke.Ole32.PROPERTYKEY.System; namespace NonsPlayer.ViewModels; public partial class LyricViewModel : ObservableRecipient { - + public ObservableCollection LyricItems = new(); + [ObservableProperty] private IMusic currentMusic; + public static int LyricPosition; + + public PlayerService PlayerService => PlayerService.Instance; + public MusicStateModel MusicStateModel => MusicStateModel.Instance; + [ObservableProperty] private ImageBrush cover; + public LyricViewModel() + { + Player.Instance.PositionChanged += LyricChanger; + Player.Instance.MusicChanged += OnMusicChanged; + LyricPosition = 0; + if (Player.Instance.CurrentMusic == null) + { + return; + } + + OnMusicChanged(Player.Instance.CurrentMusic); + } + + [RelayCommand] + public void SwitchPlayMode() + { + PlayQueue.Instance.SwitchPlayMode(); + } + + [RelayCommand] + public void SwitchShuffle() + { + PlayQueue.Instance.SwitchShuffle(); + } + + // public Visibility TransVisibility => TranLyric.Equals(string.Empty) ? Visibility.Collapsed : Visibility.Visible; + private void OnMusicChanged(IMusic music) + { + CurrentMusic = music; + LyricItems.Clear(); + + foreach (var line in music.Lyric.LyricLines) + { + LyricItems.Add(line); + } + + LyricPosition = 0; + Cover = CacheHelper.GetImageBrush(CurrentMusic.CacheAvatarId, CurrentMusic.GetCoverUrl("?param=500x500")); + } + + private void LyricChanger(TimeSpan time) + { + // if (LyricItems.Count == 0) return; + // if (LyricPosition >= LyricItems.Count || LyricPosition < 0) LyricPosition = 0; + // var changed = false; + // var realPos = Player.Instance.Position; + + // if (LyricItems[LyricPosition].LyricLine.StartTime > realPos) //当感知到进度回溯时执行 + // { + // LyricPosition = LyricItems.ToList().FindLastIndex(t => t.LyricLine.StartTime <= realPos) - 1; + // if (LyricPosition == -2) LyricPosition = -1; + // changed = true; + // } + // + // try + // { + // if (LyricPosition == 0 && LyricItems.Count != 1) changed = false; + // while (LyricItems.Count > LyricPosition + 1 && + // LyricItems[LyricPosition + 1].LyricLine.StartTime <= realPos) //正常的滚歌词 + // { + // LyricPosition++; + // changed = true; + // } + // } + // catch + // { + // // ignored + // } + + + // if (changed) + // { + // OnLyricChanged(); + // } + } + + private void OnLyricChanged() + { + if (LyricPosition == -1) return; + if (LyricItems.Count <= LyricPosition) return; + ChangeLyric(); + } + + private void ChangeLyric() + { + // LyricText = HyPlayList.Lyrics[HyPlayList.LyricPos].LyricLine.CurrentLyric; + // LyricControl.Lyric = HyPlayList.Lyrics[HyPlayList.LyricPos]; + } } \ No newline at end of file diff --git a/NonsPlayer/ViewModels/ShellViewModel.cs b/NonsPlayer/ViewModels/ShellViewModel.cs index 99d3760..0924ce4 100644 --- a/NonsPlayer/ViewModels/ShellViewModel.cs +++ b/NonsPlayer/ViewModels/ShellViewModel.cs @@ -1,6 +1,7 @@ using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using NonsPlayer.Components.Models; @@ -17,7 +18,6 @@ public partial class ShellViewModel : ObservableRecipient { public static INavigationService OutNavigationService; private bool _isBackEnabled; - public ShellViewModel(INavigationService navigationService) { NavigationService = navigationService; diff --git a/NonsPlayer/Views/Pages/LyricPage.xaml b/NonsPlayer/Views/Pages/LyricPage.xaml index 4593897..40c7576 100644 --- a/NonsPlayer/Views/Pages/LyricPage.xaml +++ b/NonsPlayer/Views/Pages/LyricPage.xaml @@ -21,7 +21,7 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NonsPlayer/Views/Pages/LyricPage.xaml.cs b/NonsPlayer/Views/Pages/LyricPage.xaml.cs index 12fb21c..da53407 100644 --- a/NonsPlayer/Views/Pages/LyricPage.xaml.cs +++ b/NonsPlayer/Views/Pages/LyricPage.xaml.cs @@ -1,25 +1,15 @@ -using System.Drawing; -using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; -using NonsPlayer.Core.Models; using NonsPlayer.Core.Nons.Player; using NonsPlayer.Services; using NonsPlayer.ViewModels; -using static NonsPlayer.Core.Services.ControlFactory; -using System.Text; -using Windows.Graphics.Imaging; using ColorThiefDotNet; using Color = Windows.UI.Color; using NonsPlayer.Helpers; using Microsoft.UI.Xaml; -using Windows.Storage.Streams; -using Buffer = Windows.Storage.Streams.Buffer; -using System.Runtime.InteropServices.WindowsRuntime; using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.WinUI.Animations; +using CommunityToolkit.Mvvm.Input; using Microsoft.UI.Xaml.Media; -using CommunityToolkit.WinUI.Media; -using NonsPlayer.Core.Contracts.Models; using NonsPlayer.Core.Contracts.Models.Music; namespace NonsPlayer.Views.Pages; @@ -27,39 +17,11 @@ namespace NonsPlayer.Views.Pages; [INotifyPropertyChanged] public sealed partial class LyricPage : Page { - private Guid GetPictureCodecFromBuffer(Buffer buffer) - { - if (buffer.Length < 10) throw new ArgumentOutOfRangeException(); - var byteArray = buffer.ToArray(); - if (byteArray[0] == 0x89 && byteArray[1] == 0x50 && byteArray[2] == 0x4e && - byteArray[3] == 0x47) - { - // PNG - return BitmapDecoder.PngDecoderId; - } - - if (byteArray[6] == 0x4a && byteArray[7] == 0x46 && byteArray[8] == 0x49 && - byteArray[9] == 0x46) - { - // JPEG - return BitmapDecoder.JpegDecoderId; - } - - if (byteArray[0] == 0x52 && byteArray[1] == 0x49 && byteArray[2] == 0x46 && - byteArray[3] == 0x46 && byteArray[8] == 0x57) - { - // WEBP - return BitmapDecoder.WebpDecoderId; - } - - throw new ArgumentOutOfRangeException(); - } - public LyricPage() { ViewModel = App.GetService(); InitializeComponent(); - // Player.Instance.PositionChangedHandler += OnPositionChanged; + Player.Instance.PositionChanged += OnPositionChanged; Player.Instance.MusicChanged += OnMusicChanged; } @@ -73,7 +35,7 @@ public LyricPage() [ObservableProperty] private SolidColorBrush foregroundAccentTextBrush = Application.Current.Resources["SystemControlPageTextBaseHighBrush"] as SolidColorBrush; - [ObservableProperty] private SolidColorBrush foregroundIdleTextBrush = + [ObservableProperty] private SolidColorBrush textForeground = Application.Current.Resources["TextFillColorTertiaryBrush"] as SolidColorBrush; @@ -87,7 +49,7 @@ public async void OnMusicChanged(IMusic value) imageBrush.Stretch = Stretch.UniformToFill; AcrylicCover.Fill = imageBrush; // double brightness = (0.299 * color.Color.A + 0.587 * color.Color.G + 0.114 * color.Color.B) / 255; - ForegroundAccentTextBrush = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 240, 240, 240)); + TextForeground = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 240, 240, 240)); // if (brightness < 0.68) // { // ForegroundAccentTextBrush = @@ -104,126 +66,62 @@ public async void OnMusicChanged(IMusic value) // LyricBoxContainer.ChangeView(null, 0, null, false); } - // public void OnPositionChanged(TimeSpan position) - // { - // try - // { - // if (Player.Instance.CurrentMusic.IsEmpty) return; - // if (!_isSliding) - // { - // DispatcherQueue.TryEnqueue(() => - // { - // MusicStateModel.Instance.Position = - // Player.Instance.NPMediaFoundationReader.CurrentTime.TotalSeconds; - // CurrentTimeSlider.Value = Player.Instance.NPMediaFoundationReader.CurrentTime.TotalSeconds; - // }); - // } - // - // // 判断是否需要滚动歌词 - // if (ViewModel.LyricItems.Count == 0) return; - // var lyric = ViewModel.LyricItems[ViewModel.LyricPosition]; - // // 控制ListView滚动 - // if (lyric.SongLyric.PureLine.StartTime <= position) - // { - // if (ViewModel.LyricPosition < ViewModel.LyricItems.Count - 1) - // { - // ViewModel.LyricPosition++; - // DispatcherQueue.TryEnqueue(() => - // { - // ScrollLyric(); - // UiHelper.Instance.LyricChanged?.Invoke(ViewModel.LyricPosition); - // }); - // } - // } - // } - // catch - // { - // // ignore - // } - // } - // - // private readonly BringIntoViewOptions NoAnimationBringIntoViewOptions = - // new BringIntoViewOptions() - // { - // VerticalAlignmentRatio = 0.5, - // AnimationDesired = false, - // }; - // - // private void ScrollLyric() - // { - // try - // { - // if (ViewModel.LyricPosition == -1) - // { - // LyricBoxContainer.ChangeView(null, 0, null, false); - // return; - // } - // - // var item = ViewModel.LyricItems[ViewModel.LyricPosition]; - // var k = LyricBox.ItemsSourceView.IndexOf(item); - // UIElement actualElement; - // bool isNewLoaded = false; - // if (LyricBox.TryGetElement(k) is { } ele) - // { - // actualElement = ele; - // } - // else - // { - // actualElement = LyricBox.GetOrCreateElement(k) as Border; - // isNewLoaded = true; - // } - // - // if (actualElement != null && item != null && - // !string.IsNullOrEmpty(item.SongLyric.PureLine.CurrentLyric)) - // { - // actualElement.UpdateLayout(); - // - // if (!isNewLoaded) - // { - // var transform = actualElement?.TransformToVisual((UIElement)LyricBoxContainer.ContentTemplateRoot); - // var position = transform?.TransformPoint(new Windows.Foundation.Point(0, 0)); - // LyricBoxContainer.ChangeView(0, - // (position?.Y + LyricHost.Margin.Top - MainGrid.ActualHeight / 4) - 200, 1, - // false); - // } - // else - // { - // // actualElement.StartBringIntoView(NoAnimationBringIntoViewOptions); - // } - // } - // } - // catch - // { - // // igrone pls - // } - // } - // - // private void CurrentTimeSlider_OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) - // { - // _slidingEventArgs = null; - // var value = TimeSpan.FromSeconds(CurrentTimeSlider.Value); - // if (Math.Abs((value - StartingTimeSpan).TotalMilliseconds) > 250d) - // { - // PlayerService.Seek(value); - // } - // - // _isSliding = false; - // } - // - // private void CurrentTimeSlider_OnManipulationStarting(object sender, ManipulationStartingRoutedEventArgs e) - // { - // var value = TimeSpan.FromSeconds(CurrentTimeSlider.Value); - // StartingTimeSpan = value; - // PlayerService.Seek(value); - // } - // - // private void CurrentTimeSlider_OnManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e) - // { - // _isSliding = true; - // _slidingEventArgs = e; - // } + public void OnPositionChanged(TimeSpan position) + { + try + { + if (Player.Instance.CurrentMusic.IsEmpty) return; + if (!_isSliding) + { + DispatcherQueue.TryEnqueue(() => + { + CurrentTimeSlider.Value = Player.Instance.Position.TotalSeconds; + }); + } + } + catch + { + // ignore + } + } + + + + + + private void CurrentTimeSlider_OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) + { + _slidingEventArgs = null; + var value = TimeSpan.FromSeconds(CurrentTimeSlider.Value); + if (Math.Abs((value - StartingTimeSpan).TotalMilliseconds) > 250d) + { + PlayerService.Seek(value); + } + + _isSliding = false; + } + + private void CurrentTimeSlider_OnManipulationStarting(object sender, ManipulationStartingRoutedEventArgs e) + { + var value = TimeSpan.FromSeconds(CurrentTimeSlider.Value); + StartingTimeSpan = value; + PlayerService.Seek(value); + } + + private void CurrentTimeSlider_OnManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e) + { + _isSliding = true; + _slidingEventArgs = e; + } private void LyricPage_OnLoaded(object sender, RoutedEventArgs e) { } + + [RelayCommand] + public void UnExpand() + { + ServiceHelper.NavigationService.GoBack(); + + } } \ No newline at end of file diff --git a/NonsPlayer/Views/ShellPage.xaml b/NonsPlayer/Views/ShellPage.xaml index e2ad699..31b0a63 100644 --- a/NonsPlayer/Views/ShellPage.xaml +++ b/NonsPlayer/Views/ShellPage.xaml @@ -8,13 +8,14 @@ xmlns:models="using:NonsPlayer.Components.Models" Loaded="OnLoaded" Unloaded="OnUnloaded" + SizeChanged="ShellPage_OnSizeChanged" mc:Ignorable="d"> - - - - + @@ -24,7 +25,8 @@ - + @@ -41,21 +43,23 @@ VerticalAlignment="Center" HorizontalAlignment="Center" /> - + - - - + - - -