From d4a924accfe5d595239a2247573ff94caac5f5eb Mon Sep 17 00:00:00 2001 From: Zhe Fang Date: Fri, 7 Nov 2025 15:51:21 -0500 Subject: [PATCH] feat: support presistent play queue and index, add settings item: auto open music gallery and auto play music; fix: auto scroll to playing track in play queue; --- .../BetterLyrics.WinUI3/App.xaml | 1 + .../BetterLyrics.WinUI3/App.xaml.cs | 6 ++ .../Controls/AppSettingsControl.xaml | 28 +++++---- .../Converter/IndexToDisplayConverter.cs | 27 +++++++++ .../BetterLyrics.WinUI3/Helper/FileHelper.cs | 4 +- .../BetterLyrics.WinUI3/Helper/PathHelper.cs | 6 +- .../Models/Settings/MusicGallerySettings.cs | 5 ++ .../SettingsService/SettingsService.cs | 2 + .../Strings/en-US/Resources.resw | 6 ++ .../Strings/ja-JP/Resources.resw | 6 ++ .../Strings/ko-KR/Resources.resw | 6 ++ .../Strings/zh-CN/Resources.resw | 6 ++ .../Strings/zh-TW/Resources.resw | 6 ++ .../ViewModels/MusicGalleryViewModel.cs | 58 ++++++++----------- .../Views/MusicGalleryPage.xaml | 12 ++-- .../Views/MusicGalleryPage.xaml.cs | 51 +++++++++++----- 16 files changed, 162 insertions(+), 68 deletions(-) create mode 100644 BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/IndexToDisplayConverter.cs diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml index e66994f..e85d901 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml @@ -68,6 +68,7 @@ + diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs index c24b383..9bec3a3 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs @@ -37,6 +37,7 @@ namespace BetterLyrics.WinUI3 { private readonly ILogger _logger; + private readonly ISettingsService _settingsService; public static new App Current => (App)Application.Current; @@ -53,6 +54,7 @@ namespace BetterLyrics.WinUI3 ConfigureServices(); _logger = Ioc.Default.GetRequiredService>(); + _settingsService = Ioc.Default.GetRequiredService(); UnhandledException += App_UnhandledException; AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; @@ -74,6 +76,10 @@ namespace BetterLyrics.WinUI3 protected override void OnLaunched(LaunchActivatedEventArgs args) { WindowHelper.OpenOrShowWindow(); + if (_settingsService.AppSettings.MusicGallerySettings.AutoOpen) + { + WindowHelper.OpenOrShowWindow(); + } } private static void ConfigureServices() diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AppSettingsControl.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AppSettingsControl.xaml index 9a1be26..0bf0d2e 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AppSettingsControl.xaml +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AppSettingsControl.xaml @@ -48,34 +48,42 @@ - + - + + + + + + + + + - + - + - + - + - + @@ -83,15 +91,15 @@ - + - + - + diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/IndexToDisplayConverter.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/IndexToDisplayConverter.cs new file mode 100644 index 0000000..07432f8 --- /dev/null +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/IndexToDisplayConverter.cs @@ -0,0 +1,27 @@ +using Microsoft.UI.Xaml.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BetterLyrics.WinUI3.Converter +{ + public partial class IndexToDisplayConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + int display = 0; + if (value is int index) + { + display = index + 1; + } + return display.ToString(); + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs index 0bd5469..c1796b2 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs @@ -1,6 +1,8 @@ // 2025/6/23 by Zhe Fang +using ATL; using BetterLyrics.WinUI3.Enums; +using BetterLyrics.WinUI3.Models; using System; using System.Collections.Generic; using System.IO; @@ -86,7 +88,5 @@ namespace BetterLyrics.WinUI3.Helper ".wav", ".aiff", ".aif", ".pcm", ".cda", ".dsf", ".dff", ".au", ".snd", ".mid", ".midi", ".mod", ".xm", ".it", ".s3m" }; - - public static string MusicSearchPattern => string.Join("|", MusicExtensions.Select(x => $"*{x}")); } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs index 7acc429..fbf0661 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs @@ -38,14 +38,12 @@ namespace BetterLyrics.WinUI3.Helper public static string SaltPlayerForWindowsLogoPath => Path.Combine(AssetsFolder, "SaltPlayerForWindows.png"); public static string MoeKoeMusicLogoPath => Path.Combine(AssetsFolder, "MoeKoeMusic.png"); public static string Listen1LogoPath => Path.Combine(AssetsFolder, "Listen1.png"); - public static string UnknownPlayerLogoPath => Path.Combine(AssetsFolder, "Question.png"); public static string LogDirectory => Path.Combine(CacheFolder, "logs"); public static string LogFilePattern => Path.Combine(LogDirectory, "log-.txt"); public static string LyricsCacheDirectory => Path.Combine(CacheFolder, "lyrics"); - public static string LrcLibLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "lrclib"); public static string NeteaseLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "netease"); public static string QQLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "qq"); @@ -56,15 +54,15 @@ namespace BetterLyrics.WinUI3.Helper public static string AmllTtmlDbLastUpdatedPath => Path.Combine(LyricsCacheDirectory, "amll-ttml-db-last-updated.txt"); public static string TranslationCacheDirectory => Path.Combine(CacheFolder, "translations"); - public static string QQTranslationCacheDirectory => Path.Combine(TranslationCacheDirectory, "qq"); public static string NeteaseTranslationCacheDirectory => Path.Combine(TranslationCacheDirectory, "netease"); public static string KugouTranslationCacheDirectory => Path.Combine(TranslationCacheDirectory, "kugou"); public static string AlbumArtCacheDirectory => Path.Combine(CacheFolder, "album-art"); - public static string iTunesAlbumArtCacheDirectory => Path.Combine(AlbumArtCacheDirectory, "itunes"); + public static string PlayQueuePath => Path.Combine(CacheFolder, "play-queue.m3u"); + public static void EnsureDirectories() { Directory.CreateDirectory(SettingsDirectory); diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/MusicGallerySettings.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/MusicGallerySettings.cs index e817304..2d5cd33 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/MusicGallerySettings.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/MusicGallerySettings.cs @@ -2,6 +2,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -11,6 +12,10 @@ namespace BetterLyrics.WinUI3.Models.Settings public partial class MusicGallerySettings : ObservableRecipient { [ObservableProperty][NotifyPropertyChangedRecipients] public partial PlaybackOrder PlaybackOrder { get; set; } = PlaybackOrder.RepeatAll; + [ObservableProperty][NotifyPropertyChangedRecipients] public partial ObservableCollection PlayQueuePaths { get; set; } = []; + [ObservableProperty][NotifyPropertyChangedRecipients] public partial int PlayQueueIndex { get; set; } = -1; + [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool AutoOpen { get; set; } = false; + [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool AutoPlay { get; set; } = false; public MusicGallerySettings() { } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/SettingsService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/SettingsService.cs index 60067d8..d79e365 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/SettingsService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/SettingsService.cs @@ -51,6 +51,8 @@ namespace BetterLyrics.WinUI3.Services.SettingsService AppSettings.StarredPlaylists.CollectionChanged += AppSettings_CollectionChanged; AppSettings.StarredPlaylists.ItemPropertyChanged += AppSettings_ItemPropertyChanged; + AppSettings.MusicGallerySettings.PlayQueuePaths.CollectionChanged += AppSettings_CollectionChanged; + AppSettings.Version = MetadataHelper.AppVersion; EnsureMediaSourceProvidersInfo(); diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw index 7947a05..11d656d 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw @@ -574,6 +574,12 @@ If you encounter any problems, please go to the Settings page, About tab, and vi Automatic adjustment + + Open the music library window when the app starts + + + Automatically continue playing when the music library window is opened + Automatic startup diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw index 5358555..60a0691 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw @@ -574,6 +574,12 @@ 自動調整 + + アプリが起動したら、音楽ライブラリウィンドウを開きます + + + 音楽ライブラリウィンドウを開くと、自動的に再生が続行されます + 自動起動 diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw index 1780fab..a35d311 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw @@ -574,6 +574,12 @@ 자동 조정 + + 앱이 시작되면 음악 라이브러리 창을 여세요 + + + 음악 라이브러리 창이 열리면 자동으로 계속 재생됩니다 + 자동 시작 diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw index 70fa4e6..f73d282 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw @@ -574,6 +574,12 @@ 自动调整 + + 应用程序启动时打开音乐库窗口 + + + 打开音乐库窗口时自动继续播放 + 自动启动 diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw index 27f30b9..33ee66c 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw @@ -574,6 +574,12 @@ 自動調整 + + 應用程式啟動時開啟音樂庫視窗 + + + 打開音樂庫視窗時自動繼續播放 + 自動啟動 diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryViewModel.cs index 1c23afb..7cb266b 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryViewModel.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryViewModel.cs @@ -71,12 +71,9 @@ namespace BetterLyrics.WinUI3.ViewModels public partial int SelectedTracksTotalDuration { get; set; } = 0; [ObservableProperty] - public partial ObservableCollection TrackPlayingQueue { get; set; } = []; + public partial ObservableCollection TrackPlayingQueue { get; set; } - public PlayQueueItem? PlayingQueueItem => TrackPlayingQueue.ElementAtOrDefault(PlayingSongIndex); - - [ObservableProperty] - public partial PlaybackOrder PlaybackOrder { get; set; } + public PlayQueueItem? PlayingQueueItem => TrackPlayingQueue.ElementAtOrDefault(AppSettings.MusicGallerySettings.PlayQueueIndex); [ObservableProperty] public partial CommonSongProperty SongOrderType { get; set; } = CommonSongProperty.Title; @@ -95,12 +92,6 @@ namespace BetterLyrics.WinUI3.ViewModels [ObservableProperty] public partial Track TrackRightTapped { get; set; } = new(); - [ObservableProperty] - public partial int PlayingSongIndex { get; set; } = -1; - - [ObservableProperty] - public partial int DisplayedPlayingSongIndex { get; set; } = 0; - [ObservableProperty] public partial string SongSearchQuery { get; set; } = string.Empty; @@ -112,6 +103,9 @@ namespace BetterLyrics.WinUI3.ViewModels _resourceService = resourceService; AppSettings = _settingsService.AppSettings; + TrackPlayingQueue = [.. AppSettings.MusicGallerySettings.PlayQueuePaths.Select(x => new PlayQueueItem(new Track(x)))]; + TrackPlayingQueue.CollectionChanged += TrackPlayingQueue_CollectionChanged; + SongsTabInfoList.Add(new SongsTabInfo(_resourceService.GetLocalizedString("MusicGalleryPageAllSongs"), "\uE8A9", false, false, CommonSongProperty.Title, string.Empty)); RefreshSongs(); @@ -119,8 +113,6 @@ namespace BetterLyrics.WinUI3.ViewModels _settingsService.AppSettings.LocalMediaFolders.CollectionChanged += LocalMediaFolders_CollectionChanged; _settingsService.AppSettings.LocalMediaFolders.ItemPropertyChanged += LocalMediaFolders_ItemPropertyChanged; - PlaybackOrder = _settingsService.AppSettings.MusicGallerySettings.PlaybackOrder; - _mediaPlayer.MediaOpened += MediaPlayer_MediaOpened; _mediaPlayer.MediaEnded += MediaPlayer_MediaEnded; _timelineController = _mediaPlayer.TimelineController = new(); @@ -136,6 +128,16 @@ namespace BetterLyrics.WinUI3.ViewModels _libWatcherService = libWatcherService; _libWatcherService.MusicLibraryFilesChanged += LibWatcherService_MusicLibraryFilesChanged; + + if (AppSettings.MusicGallerySettings.AutoPlay) + { + PlayTrackAt(AppSettings.MusicGallerySettings.PlayQueueIndex); + } + } + + private void TrackPlayingQueue_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + AppSettings.MusicGallerySettings.PlayQueuePaths = [.. TrackPlayingQueue.Select(x => x.Track.Path)]; } private void LocalMediaFolders_ItemPropertyChanged(object? sender, ItemPropertyChangedEventArgs e) @@ -155,18 +157,18 @@ namespace BetterLyrics.WinUI3.ViewModels public void PlayNextTrack() { - switch (PlaybackOrder) + switch (AppSettings.MusicGallerySettings.PlaybackOrder) { case PlaybackOrder.RepeatAll: _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () => { - if (PlayingSongIndex < TrackPlayingQueue.Count - 1) + if (AppSettings.MusicGallerySettings.PlayQueueIndex < TrackPlayingQueue.Count - 1) { - PlayingSongIndex++; + AppSettings.MusicGallerySettings.PlayQueueIndex++; } else { - PlayingSongIndex = 0; + AppSettings.MusicGallerySettings.PlayQueueIndex = 0; } PlayTrack(PlayingQueueItem); }); @@ -179,7 +181,7 @@ namespace BetterLyrics.WinUI3.ViewModels { if (TrackPlayingQueue.Count > 0) { - PlayingSongIndex = new Random().Next(0, TrackPlayingQueue.Count); + AppSettings.MusicGallerySettings.PlayQueueIndex = new Random().Next(0, TrackPlayingQueue.Count); } PlayTrack(PlayingQueueItem); }); @@ -191,18 +193,18 @@ namespace BetterLyrics.WinUI3.ViewModels private void PlayPreviousTrack() { - switch (PlaybackOrder) + switch (AppSettings.MusicGallerySettings.PlaybackOrder) { case PlaybackOrder.RepeatAll: _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () => { - if (PlayingSongIndex > 0) + if (AppSettings.MusicGallerySettings.PlayQueueIndex > 0) { - PlayingSongIndex--; + AppSettings.MusicGallerySettings.PlayQueueIndex--; } else { - PlayingSongIndex = TrackPlayingQueue.Count - 1; + AppSettings.MusicGallerySettings.PlayQueueIndex = TrackPlayingQueue.Count - 1; } PlayTrack(PlayingQueueItem); }); @@ -215,7 +217,7 @@ namespace BetterLyrics.WinUI3.ViewModels { if (TrackPlayingQueue.Count > 0) { - PlayingSongIndex = new Random().Next(0, TrackPlayingQueue.Count); + AppSettings.MusicGallerySettings.PlayQueueIndex = new Random().Next(0, TrackPlayingQueue.Count); } PlayTrack(PlayingQueueItem); }); @@ -474,16 +476,6 @@ namespace BetterLyrics.WinUI3.ViewModels ApplySongOrderType(); } - partial void OnPlayingSongIndexChanged(int value) - { - DisplayedPlayingSongIndex = value + 1; - } - - partial void OnPlaybackOrderChanged(PlaybackOrder value) - { - _settingsService.AppSettings.MusicGallerySettings.PlaybackOrder = value; - } - private void AddFileToStarredPlaylists(StorageFile file) { AppSettings.StarredPlaylists.Add(new SongsTabInfo diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml index 382b3e7..597f27f 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml @@ -15,6 +15,7 @@ xmlns:models="using:BetterLyrics.WinUI3.Models" xmlns:muxm="using:Microsoft.UI.Xaml.Media" xmlns:ui="using:CommunityToolkit.WinUI" + Loaded="Page_Loaded" Unloaded="Page_Unloaded" mc:Ignorable="d"> @@ -450,7 +451,10 @@ - + @@ -585,7 +589,7 @@ - + @@ -594,7 +598,7 @@