diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
index 6cdc1d4..7477edd 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
@@ -12,7 +12,7 @@
+ Version="1.0.59.0" />
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
index bbed9d9..ea0a51b 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
@@ -51,10 +51,13 @@
+
+
+
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs
index 974faab..2bbff02 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs
@@ -118,6 +118,7 @@ namespace BetterLyrics.WinUI3
.AddSingleton()
.AddSingleton()
.AddSingleton()
+ .AddSingleton()
.AddSingleton()
.AddSingleton()
.AddSingleton()
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Empty.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Empty.png
new file mode 100644
index 0000000..c756f7b
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Empty.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Page.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Page.png
new file mode 100644
index 0000000..9902ef7
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Page.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj
index 4b4ea25..fba170a 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj
@@ -26,6 +26,7 @@
+
@@ -117,6 +118,9 @@
Always
+
+ Always
+
Always
@@ -156,6 +160,9 @@
Always
+
+ Always
+
Always
@@ -181,6 +188,11 @@
Always
+
+
+ MSBuild:Compile
+
+
MSBuild:Compile
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsSearchControl.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsSearchControl.xaml
new file mode 100644
index 0000000..4b5a4f3
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsSearchControl.xaml
@@ -0,0 +1,271 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsSearchControl.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsSearchControl.xaml.cs
new file mode 100644
index 0000000..1ea13a8
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsSearchControl.xaml.cs
@@ -0,0 +1,35 @@
+using BetterLyrics.WinUI3.Models;
+using BetterLyrics.WinUI3.ViewModels;
+using CommunityToolkit.Mvvm.DependencyInjection;
+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 Ude.Core;
+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 BetterLyrics.WinUI3.Controls
+{
+ public sealed partial class LyricsSearchControl : UserControl
+ {
+ public LyricsSearchControlViewModel ViewModel => (LyricsSearchControlViewModel)DataContext;
+
+ public LyricsSearchControl()
+ {
+ InitializeComponent();
+ DataContext = Ioc.Default.GetRequiredService();
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml
index 5dc9400..02558a0 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml
@@ -31,16 +31,20 @@
-
-
-
+
+
+
+
+
+
+
+
".*",
};
}
+
+ public static LyricsSearchProvider? ToLyricsSearchProvider(this LyricsFormat format)
+ {
+ return format switch
+ {
+ LyricsFormat.Lrc => LyricsSearchProvider.LocalLrcFile,
+ LyricsFormat.Eslrc => LyricsSearchProvider.LocalEslrcFile,
+ LyricsFormat.Ttml => LyricsSearchProvider.LocalTtmlFile,
+ _ => null,
+ };
+ }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsSearchResult.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsSearchResult.cs
new file mode 100644
index 0000000..811a716
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsSearchResult.cs
@@ -0,0 +1,20 @@
+using BetterLyrics.WinUI3.Enums;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Models
+{
+ public class LyricsSearchResult
+ {
+ public bool IsFound => !string.IsNullOrEmpty(Raw);
+ public LyricsSearchProvider? Provider { get; set; }
+
+ public string? Raw { get; set; }
+
+ public string? Title { get; set; }
+ public string? Artist { get; set; }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MappedSongSearchQuery.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MappedSongSearchQuery.cs
new file mode 100644
index 0000000..0c82a89
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MappedSongSearchQuery.cs
@@ -0,0 +1,36 @@
+using BetterLyrics.WinUI3.Enums;
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Models
+{
+ public partial class MappedSongSearchQuery : ObservableRecipient
+ {
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial string OriginalTitle { get; set; } = string.Empty;
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial string OriginalArtist { get; set; } = string.Empty;
+
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial string MappedTitle { get; set; } = string.Empty;
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial string MappedArtist { get; set; } = string.Empty;
+
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsMarkedAsPureMusic { get; set; } = false;
+
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsSearchProvider? LyricsSearchProvider { get; set; }
+
+ public MappedSongSearchQuery Clone()
+ {
+ return new MappedSongSearchQuery
+ {
+ OriginalTitle = this.OriginalTitle,
+ OriginalArtist = this.OriginalArtist,
+ MappedTitle = this.MappedTitle,
+ MappedArtist = this.MappedArtist,
+ IsMarkedAsPureMusic = this.IsMarkedAsPureMusic,
+ LyricsSearchProvider = this.LyricsSearchProvider
+ };
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs
index 83188f9..62dfc69 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs
@@ -12,23 +12,29 @@ namespace BetterLyrics.WinUI3.Models
{
public partial class MediaSourceProviderInfo : ObservableRecipient
{
- [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsEnabled { get; set; }
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsEnabled { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string Provider { get; set; }
- [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLastFMTrackEnabled { get; set; }
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLastFMTrackEnabled { get; set; } = false;
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsTimelineSyncEnabled { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int TimelineSyncThreshold { get; set; }
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int PositionOffset { get; set; }
- [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ResetPositionOffsetOnSongChanged { get; set; }
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ResetPositionOffsetOnSongChanged { get; set; } = false;
- [ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection LyricsSearchProvidersInfo { get; set; }
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection LyricsSearchProvidersInfo { get; set; } = [.. Enum.GetValues().Select(p => new LyricsSearchProviderInfo(p, true))];
- [ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection AlbumArtSearchProvidersInfo { get; set; }
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection AlbumArtSearchProvidersInfo { get; set; } = [.. Enum.GetValues().Select(p => new AlbumArtSearchProviderInfo(p, true))];
- public MediaSourceProviderInfo() { }
+ public MediaSourceProviderInfo()
+ {
+ Provider = string.Empty;
+ TimelineSyncThreshold = 0;
+ PositionOffset = 0;
+ }
public MediaSourceProviderInfo(string provider) : base()
{
@@ -47,11 +53,6 @@ namespace BetterLyrics.WinUI3.Models
}
Provider = provider;
- IsEnabled = true;
- IsLastFMTrackEnabled = false;
- ResetPositionOffsetOnSongChanged = false;
- LyricsSearchProvidersInfo = [.. Enum.GetValues().Select(p => new LyricsSearchProviderInfo(p, true))];
- AlbumArtSearchProvidersInfo = [.. Enum.GetValues().Select(p => new AlbumArtSearchProviderInfo(p, true))];
}
partial void OnAlbumArtSearchProvidersInfoChanged(FullyObservableCollection oldValue, FullyObservableCollection newValue)
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/AppSettings.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/AppSettings.cs
index 53a3b1f..a6753de 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/AppSettings.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/AppSettings.cs
@@ -35,6 +35,8 @@ namespace BetterLyrics.WinUI3.Models.Settings
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection LocalMediaFolders { get; set; } = [];
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection MediaSourceProvidersInfo { get; set; } = [];
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection MappedSongSearchQueries { get; set; } = [];
+
public AppSettings() { }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/AlbumArtSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/AlbumArtSearchService.cs
index f03f231..1ac9a89 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/AlbumArtSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/AlbumArtSearchService.cs
@@ -12,6 +12,7 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
@@ -30,12 +31,7 @@ namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
_iTunesHttpClinet = new();
}
- public async Task SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null)
- {
- return await Task.Run(async () => await SearchAsyncCore(mediaSessionId, title, artist, album, bytesFromSMTC));
- }
-
- public async Task SearchAsyncCore(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null)
+ public async Task SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC, CancellationToken token)
{
byte[]? result = null;
@@ -60,6 +56,7 @@ namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
foreach (string countryCode in new List() { "us", "cn", "jp", "kr" })
{
result = await SearchiTunesAsync(artist, album, title, countryCode);
+ if (token.IsCancellationRequested) return result;
if (result != null) break;
}
break;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/IAlbumArtSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/IAlbumArtSearchService.cs
index d2a40b8..faee086 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/IAlbumArtSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/IAlbumArtSearchService.cs
@@ -2,12 +2,13 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
{
public interface IAlbumArtSearchService
{
- Task SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null);
+ Task SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC, CancellationToken token);
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/ILyricsSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/ILyricsSearchService.cs
index 107b5ac..73a967e 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/ILyricsSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/ILyricsSearchService.cs
@@ -1,14 +1,18 @@
// 2025/6/23 by Zhe Fang
+using BetterLyrics.WinUI3.Enums;
+using BetterLyrics.WinUI3.Models;
+using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using BetterLyrics.WinUI3.Enums;
namespace BetterLyrics.WinUI3.Services.LyricsSearchService
{
public interface ILyricsSearchService
{
- Task<(string?, LyricsSearchProvider?)> SearchAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token);
+ Task SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token);
+
+ Task> SearchAllAsync(string title, string artist, string album, double durationMs, CancellationToken token);
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/LyricsSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/LyricsSearchService.cs
index 06377e8..63b88f3 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/LyricsSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/LyricsSearchService.cs
@@ -4,6 +4,7 @@ using ATL;
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
+using BetterLyrics.WinUI3.Models;
using BetterLyrics.WinUI3.Services.SettingsService;
using CommunityToolkit.Mvvm.DependencyInjection;
using Lyricify.Lyrics.Providers.Web.Kugou;
@@ -11,6 +12,7 @@ using Lyricify.Lyrics.Searchers;
using Microsoft.Extensions.Logging;
using NTextCat.Commons;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
@@ -87,94 +89,158 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
}
}
- public async Task<(string?, LyricsSearchProvider?)> SearchAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
+ public async Task SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
{
- return await Task.Run(async () => await SearchAsyncCore(mediaSessionId, title, artist, album, durationMs, token), token);
+ var lyricsSearchResult = new LyricsSearchResult();
+
+ string overridenTitle = title;
+ string overridenArtist = artist;
+
+ _logger.LogInformation("Searching img for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
+
+ var found = _settingsService.AppSettings.MappedSongSearchQueries
+ .Where(x => x.OriginalTitle == title && x.OriginalArtist == artist)
+ .FirstOrDefault();
+
+ if (found != null)
+ {
+ overridenTitle = found.MappedTitle;
+ overridenArtist = found.MappedArtist;
+
+ _logger.LogInformation("Found mapped song search query: {MappedSongSearchQuery}", found);
+
+ var pureMusic = found.IsMarkedAsPureMusic;
+ if (pureMusic)
+ {
+ lyricsSearchResult.Title = overridenTitle;
+ lyricsSearchResult.Artist = overridenArtist;
+ lyricsSearchResult.Raw = "[99:00.000]🎶🎶🎶";
+ return lyricsSearchResult;
+ }
+
+ var targetProvider = found.LyricsSearchProvider;
+ if (targetProvider != null)
+ {
+ return await SearchSingleAsync(targetProvider.Value, overridenTitle, overridenArtist, album, durationMs, token);
+ }
+ }
+
+ foreach (var provider in _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == mediaSessionId).FirstOrDefault()?.LyricsSearchProvidersInfo ?? [])
+ {
+ if (!provider.IsEnabled)
+ {
+ continue;
+ }
+
+ lyricsSearchResult = await SearchSingleAsync(provider.Provider, overridenTitle, overridenArtist, album, durationMs, token);
+
+ if (lyricsSearchResult.IsFound)
+ {
+ return lyricsSearchResult;
+ }
+ }
+
+ return lyricsSearchResult;
}
- private async Task<(string?, LyricsSearchProvider?)> SearchAsyncCore(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
+ public async Task> SearchAllAsync(string title, string artist, string album, double durationMs, CancellationToken token)
{
- _logger.LogInformation("Searching img for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
+ _logger.LogInformation("Searching all lyrics for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
+ var results = new List();
+ foreach (var provider in Enum.GetValues())
+ {
+ var searchResult = await SearchSingleAsync(provider, title, artist, album, durationMs, token);
+ results.Add(searchResult);
+ }
+ return results;
+ }
+
+ private async Task SearchSingleAsync(LyricsSearchProvider provider, string title, string artist, string album, double durationMs, CancellationToken token)
+ {
+ var lyricsSearchResult = new LyricsSearchResult
+ {
+ Provider = provider,
+ };
try
{
- foreach (var provider in _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == mediaSessionId).FirstOrDefault()?.LyricsSearchProvidersInfo ?? [])
+ LyricsFormat lyricsFormat = provider.GetLyricsFormat();
+
+ // Check cache first
+ if (provider.IsRemote())
{
- if (!provider.IsEnabled)
+ var cachedLyrics = FileHelper.ReadLyricsCache(title, artist, lyricsFormat, provider.GetCacheDirectory());
+ if (!string.IsNullOrWhiteSpace(cachedLyrics))
{
- continue;
+ lyricsSearchResult.Raw = cachedLyrics;
+ lyricsSearchResult.Title = title;
+ lyricsSearchResult.Artist = artist;
+ return lyricsSearchResult;
}
+ }
- string? cachedLyrics;
- LyricsFormat lyricsFormat = provider.Provider.GetLyricsFormat();
-
- // Check cache first
- if (provider.Provider.IsRemote())
+ if (provider.IsLocal())
+ {
+ if (provider == LyricsSearchProvider.LocalMusicFile)
{
- cachedLyrics = FileHelper.ReadLyricsCache(title, artist, lyricsFormat, provider.Provider.GetCacheDirectory());
- if (!string.IsNullOrWhiteSpace(cachedLyrics))
- {
- return (cachedLyrics, provider.Provider);
- }
- }
-
- string? searchedLyrics = null;
-
- if (provider.Provider.IsLocal())
- {
- if (provider.Provider == LyricsSearchProvider.LocalMusicFile)
- {
- searchedLyrics = SearchEmbedded(title, artist);
- }
- else
- {
- searchedLyrics = await SearchFile(title, artist, lyricsFormat);
- }
+ lyricsSearchResult = SearchEmbedded(title, artist);
}
else
{
- switch (provider.Provider)
- {
- case LyricsSearchProvider.LrcLib:
- searchedLyrics = await SearchLrcLibAsync(title, artist, album, (int)(durationMs / 1000));
- break;
- case LyricsSearchProvider.QQ:
- searchedLyrics = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.QQMusic);
- break;
- case LyricsSearchProvider.Kugou:
- searchedLyrics = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Kugou);
- break;
- case LyricsSearchProvider.Netease:
- searchedLyrics = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Netease);
- break;
- case LyricsSearchProvider.AmllTtmlDb:
- searchedLyrics = await SearchAmllTtmlDbAsync(title, artist);
- break;
- default:
- break;
- }
+ lyricsSearchResult = await SearchFile(title, artist, lyricsFormat);
}
-
- token.ThrowIfCancellationRequested();
-
- if (!string.IsNullOrWhiteSpace(searchedLyrics))
+ }
+ else
+ {
+ switch (provider)
{
- if (provider.Provider.IsRemote())
- {
- FileHelper.WriteLyricsCache(title, artist, searchedLyrics, lyricsFormat, provider.Provider.GetCacheDirectory());
- }
+ case LyricsSearchProvider.LrcLib:
+ lyricsSearchResult = await SearchLrcLibAsync(title, artist, album, (int)(durationMs / 1000));
+ break;
+ case LyricsSearchProvider.QQ:
+ lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.QQMusic);
+ break;
+ case LyricsSearchProvider.Kugou:
+ lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Kugou);
+ break;
+ case LyricsSearchProvider.Netease:
+ lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Netease);
+ break;
+ case LyricsSearchProvider.AmllTtmlDb:
+ lyricsSearchResult = await SearchAmllTtmlDbAsync(title, artist);
+ break;
+ default:
+ break;
+ }
+ }
- return (searchedLyrics, provider.Provider);
+ if (token.IsCancellationRequested)
+ {
+ return lyricsSearchResult;
+ }
+
+ if (lyricsSearchResult.IsFound)
+ {
+ if (provider.IsRemote())
+ {
+ FileHelper.WriteLyricsCache(title, artist, lyricsSearchResult.Raw!, lyricsFormat, provider.GetCacheDirectory());
}
}
}
- catch (Exception) { }
+ catch (Exception)
+ {
+ }
- return (null, null);
+ return lyricsSearchResult;
}
- private async Task SearchFile(string title, string artist, LyricsFormat format)
+ private async Task SearchFile(string title, string artist, LyricsFormat format)
{
+ var lyricsSearchResult = new LyricsSearchResult
+ {
+ Provider = format.ToLyricsSearchProvider(),
+ };
+
foreach (var folder in _settingsService.AppSettings.LocalMediaFolders)
{
if (Directory.Exists(folder.Path) && folder.IsEnabled)
@@ -188,7 +254,9 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
string? raw = await File.ReadAllTextAsync(file, FileHelper.GetEncoding(file));
if (raw != null)
{
- return raw;
+ lyricsSearchResult.Raw = raw;
+ lyricsSearchResult.Title = title;
+ lyricsSearchResult.Artist = artist;
}
}
}
@@ -198,11 +266,16 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
}
}
}
- return null;
+ return lyricsSearchResult;
}
- private string? SearchEmbedded(string title, string artist)
+ private LyricsSearchResult SearchEmbedded(string title, string artist)
{
+ var lyricsSearchResult = new LyricsSearchResult
+ {
+ Provider = LyricsSearchProvider.LocalMusicFile,
+ };
+
foreach (var folder in _settingsService.AppSettings.LocalMediaFolders)
{
if (Directory.Exists(folder.Path) && folder.IsEnabled)
@@ -217,23 +290,32 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
var plain = TagLib.File.Create(file).Tag.Lyrics;
if (!plain.IsNullOrEmpty())
{
- return plain;
+ lyricsSearchResult.Raw = plain;
+ lyricsSearchResult.Title = track.Title;
+ lyricsSearchResult.Artist = artist;
}
}
}
}
}
}
- return null;
+ return lyricsSearchResult;
}
- private async Task SearchAmllTtmlDbAsync(string title, string artist)
+ private async Task SearchAmllTtmlDbAsync(string title, string artist)
{
+ var lyricsSearchResult = new LyricsSearchResult
+ {
+ Provider = LyricsSearchProvider.AmllTtmlDb,
+ };
+
if (IsAmllTtmlDbIndexInvalid())
{
var downloadOk = await DownloadAmllTtmlDbIndexAsync();
if (!downloadOk)
- return null;
+ {
+ return lyricsSearchResult;
+ }
}
string? rawLyricFile = null;
@@ -276,7 +358,9 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
}
if (string.IsNullOrWhiteSpace(rawLyricFile))
- return null;
+ {
+ return lyricsSearchResult;
+ }
// 下载歌词内容
var url = $"{Constants.AmllTTmlDB.QueryPrefix}{rawLyricFile}";
@@ -284,17 +368,29 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
{
using var response = await _amllTtmlDbHttpClient.GetAsync(url);
if (!response.IsSuccessStatusCode)
- return null;
- return await response.Content.ReadAsStringAsync();
+ {
+ return lyricsSearchResult;
+ }
+ string lyrics = await response.Content.ReadAsStringAsync();
+
+ lyricsSearchResult.Raw = lyrics;
+ lyricsSearchResult.Title = title;
+ lyricsSearchResult.Artist = artist;
}
catch
{
- return null;
}
+
+ return lyricsSearchResult;
}
- private async Task SearchLrcLibAsync(string title, string artist, string album, int duration)
+ private async Task SearchLrcLibAsync(string title, string artist, string album, int duration)
{
+ var lyricsSearchResult = new LyricsSearchResult
+ {
+ Provider = LyricsSearchProvider.LrcLib,
+ };
+
// Build API query URL
var url =
$"https://lrclib.net/api/search?" +
@@ -305,7 +401,9 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
using var response = await _lrcLibHttpClient.GetAsync(url);
if (!response.IsSuccessStatusCode)
- return null;
+ {
+ return lyricsSearchResult;
+ }
var json = await response.Content.ReadAsStringAsync();
@@ -313,22 +411,47 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
json,
Serialization.SourceGenerationContext.Default.JsonElement
);
+
+ string? original = null;
+ string? searchedTitle = null;
+ string? searchedArtist = null;
+
if (jArr.ValueKind == JsonValueKind.Array && jArr.GetArrayLength() > 0)
{
var first = jArr[0];
- var syncedLyrics = first.GetProperty("syncedLyrics").GetString();
- var result = string.IsNullOrWhiteSpace(syncedLyrics) ? null : syncedLyrics;
- if (!string.IsNullOrWhiteSpace(result))
- {
- return result;
- }
+ original = first.GetProperty("syncedLyrics").GetString();
+ searchedTitle = first.GetProperty("trackName").GetString();
+ searchedArtist = first.GetProperty("artistName").GetString();
}
- return null;
+ lyricsSearchResult.Raw = original;
+ lyricsSearchResult.Title = searchedTitle;
+ lyricsSearchResult.Artist = searchedArtist;
+
+ return lyricsSearchResult;
}
- private static async Task SearchQQNeteaseKugouAsync(string title, string artist, string album, int durationMs, Searchers searchers)
+ private static async Task SearchQQNeteaseKugouAsync(string title, string artist, string album, int durationMs, Searchers searchers)
{
+ var lyricsSearchResult = new LyricsSearchResult();
+
+ switch (searchers)
+ {
+ case Searchers.QQMusic:
+ lyricsSearchResult.Provider = LyricsSearchProvider.QQ;
+ break;
+ case Searchers.Netease:
+ lyricsSearchResult.Provider = LyricsSearchProvider.Netease;
+ break;
+ case Searchers.Kugou:
+ lyricsSearchResult.Provider = LyricsSearchProvider.Kugou;
+ break;
+ case Searchers.Musixmatch:
+ break;
+ default:
+ break;
+ }
+
var result = await SearchersHelper.GetSearcher(searchers).SearchForResult(
new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
{
@@ -354,11 +477,15 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
PathHelper.QQTranslationCacheDirectory
);
}
- return original;
+
+ lyricsSearchResult.Raw = original;
+ lyricsSearchResult.Title = qqResult.Title;
+ lyricsSearchResult.Artist = qqResult.Artists.Join(" | ");
}
else if (result is NeteaseSearchResult neteaseResult)
{
var response = await Lyricify.Lyrics.Helpers.ProviderHelper.NeteaseApi.GetLyric(neteaseResult.Id);
+ var original = response?.Lrc?.Lyric;
var translated = response?.Tlyric?.Lyric;
if (!string.IsNullOrEmpty(translated))
{
@@ -370,21 +497,26 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
PathHelper.NeteaseTranslationCacheDirectory
);
}
- return response?.Lrc.Lyric;
+
+ lyricsSearchResult.Raw = original;
+ lyricsSearchResult.Title = neteaseResult.Title;
+ lyricsSearchResult.Artist = neteaseResult.Artists.Join(" | ");
}
else if (result is KugouSearchResult kugouResult)
{
var response = await Lyricify.Lyrics.Helpers.ProviderHelper.KugouApi.GetSearchLyrics(hash: kugouResult.Hash);
+ string? original = null;
if (response?.Candidates.FirstOrDefault() is SearchLyricsResponse.Candidate candidate)
{
- return Lyricify.Lyrics.Decrypter.Krc.Helper.GetLyrics(
- candidate.Id,
- candidate.AccessKey
- );
+ original = Lyricify.Lyrics.Decrypter.Krc.Helper.GetLyrics(candidate.Id, candidate.AccessKey);
}
+
+ lyricsSearchResult.Raw = original;
+ lyricsSearchResult.Title = kugouResult.Title;
+ lyricsSearchResult.Artist = kugouResult.Artists.Join(" | ");
}
- return null;
+ return lyricsSearchResult;
}
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.AlbumArtUpdater.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.AlbumArtUpdater.cs
index d4016c3..25e8487 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.AlbumArtUpdater.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.AlbumArtUpdater.cs
@@ -33,14 +33,15 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
return;
}
- byte[]? bytes = await _albumArtSearchService.SearchAsync(
+ byte[]? bytes = await Task.Run(async () => await _albumArtSearchService.SearchAsync(
SongInfo?.SourceAppUserModelId ?? "",
_cachedSongInfo.Title,
_cachedSongInfo.Artist,
_cachedSongInfo?.Album ?? string.Empty,
- _SMTCAlbumArtBytes
- );
- token.ThrowIfCancellationRequested();
+ _SMTCAlbumArtBytes,
+ token
+ ), token);
+ if (token.IsCancellationRequested) return;
if (bytes == null)
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.LyricsUpdater.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.LyricsUpdater.cs
index c18cf9b..df84eb7 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.LyricsUpdater.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.LyricsUpdater.cs
@@ -42,9 +42,11 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
if (_settingsService.AppSettings.TranslationSettings.IsTranslationEnabled)
{
await SetDisplayedAlongWithTranslationsAsync(token);
+ if (token.IsCancellationRequested) return;
}
else
{
+ _logger.LogInformation("Translation is disabled, showing original lyrics only.");
_lyricsDataArr.ElementAtOrDefault(0)?.SetDisplayedTextInOriginalText();
_langIndex = 0;
}
@@ -128,27 +130,25 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
LyricsChanged?.Invoke(this, new LyricsChangedEventArgs(CurrentLyricsData));
- string? lyricsRaw = null;
- LyricsSearchProvider? lyricsSearchProvider = null;
- LyricsSearchProvider = lyricsSearchProvider;
-
if (SongInfo != null)
{
_logger.LogInformation("Searching lyrics for: Title={Title}, Artist={Artist}, Album={Album}, DurationMs={DurationMs}",
SongInfo.Title, SongInfo.Artist, SongInfo.Album, SongInfo.DurationMs);
- (lyricsRaw, lyricsSearchProvider) = await _lyrcsSearchService.SearchAsync(
+
+ var lyricsSearchResult = await Task.Run(async () => await _lyrcsSearchService.SearchSmartlyAsync(
SongInfo.SourceAppUserModelId ?? "",
SongInfo.Title,
SongInfo.Artist,
SongInfo.Album ?? "",
SongInfo.DurationMs ?? 0,
token
- );
- LyricsSearchProvider = lyricsSearchProvider;
- _logger.LogInformation("Lyrics was found? {Found}, Provider: {LyricsSearchProvider}", lyricsRaw != null, LyricsSearchProvider?.ToString() ?? "null");
- token.ThrowIfCancellationRequested();
+ ), token);
+ if (token.IsCancellationRequested) return;
+ LyricsSearchProvider = lyricsSearchResult?.Provider;
+
+ _logger.LogInformation("Lyrics was found? {Found}, Provider: {LyricsSearchProvider}", lyricsSearchResult?.IsFound, LyricsSearchProvider?.ToString() ?? "null");
- _lyricsDataArr = new LyricsParser().Parse(lyricsRaw, (int?)SongInfo?.DurationMs);
+ _lyricsDataArr = new LyricsParser().Parse(lyricsSearchResult?.Raw, (int?)SongInfo?.DurationMs);
FillTranslationFromCache(LyricsSearchProvider);
}
else
@@ -171,12 +171,12 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
switch (provider)
{
case Enums.LyricsSearchProvider.QQ:
- translationRaw = Helper.FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, Helper.PathHelper.QQTranslationCacheDirectory);
+ translationRaw = FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, PathHelper.QQTranslationCacheDirectory);
break;
case Enums.LyricsSearchProvider.Kugou:
break;
case Enums.LyricsSearchProvider.Netease:
- translationRaw = Helper.FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, Helper.PathHelper.NeteaseTranslationCacheDirectory);
+ translationRaw = FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, PathHelper.NeteaseTranslationCacheDirectory);
break;
case Enums.LyricsSearchProvider.LrcLib:
break;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.cs
index 324ccea..db8c758 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.cs
@@ -43,6 +43,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
IRecipient>,
IRecipient>,
IRecipient>,
+ IRecipient>,
IRecipient>>
{
private readonly IAlbumArtSearchService _albumArtSearchService;
@@ -92,15 +93,29 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
_logger = Ioc.Default.GetRequiredService>();
_settingsService.AppSettings.MediaSourceProvidersInfo.ItemPropertyChanged += MediaSourceProvidersInfo_ItemPropertyChanged;
+
_settingsService.AppSettings.LocalMediaFolders.CollectionChanged += LocalMediaFolders_CollectionChanged;
_settingsService.AppSettings.LocalMediaFolders.ItemPropertyChanged += LocalMediaFolders_ItemPropertyChanged;
+ _settingsService.AppSettings.MappedSongSearchQueries.CollectionChanged += MappedSongSearchQueries_CollectionChanged;
+ _settingsService.AppSettings.MappedSongSearchQueries.ItemPropertyChanged += MappedSongSearchQueries_ItemPropertyChanged;
+
_libWatcherService.MusicLibraryFilesChanged += LibWatcherService_MusicLibraryFilesChanged;
InitMediaManager();
InitPlaybackShortcuts();
}
+ private void MappedSongSearchQueries_ItemPropertyChanged(object? sender, ItemPropertyChangedEventArgs e)
+ {
+ UpdateLyrics();
+ }
+
+ private void MappedSongSearchQueries_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+ {
+ UpdateLyrics();
+ }
+
private void InitPlaybackShortcuts()
{
UpdatePlayOrPauseSongShortcut();
@@ -172,11 +187,22 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
UpdateLyrics();
}
+ public MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo()
+ {
+ var desiredSession = GetCurrentSession();
+ return _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(x => x.Provider == desiredSession?.Id);
+ }
+
private bool IsMediaSourceEnabled(string id)
{
return _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(s => s.Provider == id)?.IsEnabled ?? true;
}
+ private bool IsMediaSourceTimelineSyncEnabled(string id)
+ {
+ return _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(s => s.Provider == id)?.IsTimelineSyncEnabled ?? true;
+ }
+
private void InitMediaManager()
{
_mediaManager.OnAnySessionOpened += MediaManager_OnAnySessionOpened;
@@ -204,9 +230,9 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
if (!_mediaManager.IsStarted) return;
if (mediaSession == null) return;
- var focusedSession = _mediaManager.GetFocusedSession();
+ var desiredSession = GetCurrentSession();
- if (mediaSession != focusedSession) return;
+ if (mediaSession != desiredSession) return;
if (!IsMediaSourceEnabled(mediaSession.Id))
{
@@ -218,11 +244,14 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
}
else
{
- _cachedPosition = timelineProperties.Position;
- _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
+ if (IsMediaSourceTimelineSyncEnabled(mediaSession.Id))
{
- TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, timelineProperties.EndTime));
- });
+ _cachedPosition = timelineProperties.Position;
+ _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
+ {
+ TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, timelineProperties.EndTime));
+ });
+ }
}
}
@@ -233,10 +262,10 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
if (!_mediaManager.IsStarted) return;
if (mediaSession == null) return;
- var focusedSession = _mediaManager.GetFocusedSession();
+ var desiredSession = GetCurrentSession();
//RecordMediaSourceProviderInfo(mediaSession);
- if (mediaSession != focusedSession) return;
+ if (mediaSession != desiredSession) return;
if (!IsMediaSourceEnabled(mediaSession.Id))
{
@@ -264,10 +293,10 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
string id = mediaSession.Id;
- var focusedSession = _mediaManager.GetFocusedSession();
+ var desiredSession = GetCurrentSession();
//RecordMediaSourceProviderInfo(mediaSession);
- if (mediaSession != focusedSession) return;
+ if (mediaSession != desiredSession) return;
if (!IsMediaSourceEnabled(id))
{
@@ -350,6 +379,30 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
SendFocusedMessagesAsync().ConfigureAwait(false);
}
+ private MediaManager.MediaSession? GetCurrentSession()
+ {
+ var focusedSession = _mediaManager.GetFocusedSession();
+ if (focusedSession == null)
+ {
+ return null;
+ }
+ if (IsMediaSourceEnabled(focusedSession.Id))
+ {
+ return focusedSession;
+ }
+ else
+ {
+ foreach (var session in _mediaManager.CurrentMediaSessions.Values)
+ {
+ if (IsMediaSourceEnabled(session.Id))
+ {
+ return session;
+ }
+ }
+ }
+ return null;
+ }
+
private void RecordMediaSourceProviderInfo(MediaManager.MediaSession mediaSession)
{
if (!_mediaManager.IsStarted) return;
@@ -382,13 +435,14 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
private async Task SendFocusedMessagesAsync()
{
- var focusedSession = _mediaManager.GetFocusedSession();
- if (focusedSession == null || focusedSession.ControlSession == null) return;
+ var desiredSession = GetCurrentSession();
+ if (desiredSession == null || desiredSession.ControlSession == null) return;
- var mediaProps = await focusedSession.ControlSession.TryGetMediaPropertiesAsync();
- MediaManager_OnAnyTimelinePropertyChanged(focusedSession, focusedSession.ControlSession.GetTimelineProperties());
- MediaManager_OnAnyMediaPropertyChanged(focusedSession, mediaProps);
- MediaManager_OnAnyPlaybackStateChanged(focusedSession, focusedSession.ControlSession.GetPlaybackInfo());
+ var mediaProps = await desiredSession.ControlSession.TryGetMediaPropertiesAsync();
+ if (desiredSession == null || desiredSession.ControlSession == null) return;
+ MediaManager_OnAnyTimelinePropertyChanged(desiredSession, desiredSession.ControlSession.GetTimelineProperties());
+ MediaManager_OnAnyMediaPropertyChanged(desiredSession, mediaProps);
+ MediaManager_OnAnyPlaybackStateChanged(desiredSession, desiredSession.ControlSession.GetPlaybackInfo());
}
private void StartSSE()
@@ -448,7 +502,10 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
_lxMusicDurationSeconds = data.GetDouble();
}
- TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(TimeSpan.FromSeconds(_lxMusicPositionSeconds), TimeSpan.FromSeconds(_lxMusicDurationSeconds)));
+ if (IsMediaSourceTimelineSyncEnabled(Constants.PlayerID.LXMusic))
+ {
+ TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(TimeSpan.FromSeconds(_lxMusicPositionSeconds), TimeSpan.FromSeconds(_lxMusicDurationSeconds)));
+ }
}
}
});
@@ -456,54 +513,49 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
public async Task PlayAsync()
{
- var focusedSession = _mediaManager.GetFocusedSession();
- if (focusedSession != null)
+ var desiredSession = GetCurrentSession();
+ if (desiredSession != null)
{
- await focusedSession.ControlSession?.TryPlayAsync();
+ await desiredSession.ControlSession?.TryPlayAsync();
}
}
public async Task PauseAsync()
{
- var focusedSession = _mediaManager.GetFocusedSession();
- if (focusedSession != null)
+ var desiredSession = GetCurrentSession();
+ if (desiredSession != null)
{
- await focusedSession.ControlSession?.TryPauseAsync();
+ await desiredSession.ControlSession?.TryPauseAsync();
}
}
public async Task PreviousAsync()
{
- var focusedSession = _mediaManager.GetFocusedSession();
- if (focusedSession != null)
+ var desiredSession = GetCurrentSession();
+ if (desiredSession != null)
{
- await focusedSession.ControlSession?.TrySkipPreviousAsync();
+ await desiredSession.ControlSession?.TrySkipPreviousAsync();
}
}
public async Task NextAsync()
{
- var focusedSession = _mediaManager.GetFocusedSession();
- if (focusedSession != null)
+ var desiredSession = GetCurrentSession();
+ if (desiredSession != null)
{
- await focusedSession.ControlSession?.TrySkipNextAsync();
+ await desiredSession.ControlSession?.TrySkipNextAsync();
}
}
public async Task ChangePosition(double seconds)
{
- var focusedSession = _mediaManager.GetFocusedSession();
- if (focusedSession != null)
+ var desiredSession = GetCurrentSession();
+ if (desiredSession != null)
{
- await focusedSession.ControlSession?.TryChangePlaybackPositionAsync(TimeSpan.FromSeconds(seconds).Ticks);
+ await desiredSession.ControlSession?.TryChangePlaybackPositionAsync(TimeSpan.FromSeconds(seconds).Ticks);
}
}
- public MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo()
- {
- return _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == _cachedSongInfo?.SourceAppUserModelId)?.FirstOrDefault();
- }
-
public void Receive(PropertyChangedMessage message)
{
if (message.Sender is MediaSourceProviderInfo)
@@ -571,5 +623,16 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
}
}
}
+
+ public void Receive(PropertyChangedMessage message)
+ {
+ if (message.Sender is LiveStates)
+ {
+ if (message.PropertyName == nameof(LiveStates.CurrentLyricsWindowMode))
+ {
+ UpdateTranslations();
+ }
+ }
+ }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/SettingsService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/SettingsService.cs
index abf1236..88dd932 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/SettingsService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/SettingsService.cs
@@ -57,6 +57,9 @@ namespace BetterLyrics.WinUI3.Services.SettingsService
AppSettings.LocalMediaFolders.CollectionChanged += AppSettings_CollectionChanged;
AppSettings.LocalMediaFolders.ItemPropertyChanged += AppSettings_ItemPropertyChanged;
+ AppSettings.MappedSongSearchQueries.CollectionChanged += AppSettings_CollectionChanged;
+ AppSettings.MappedSongSearchQueries.ItemPropertyChanged += AppSettings_ItemPropertyChanged;
+
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 6be162a..a8f921a 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw
@@ -219,6 +219,9 @@
Lyrics provider
+
+ Manually search lyrics
+
Lyrics style and effect quick settings
@@ -249,6 +252,42 @@
Translation provider
+
+ Artist
+
+
+ * Save changes take effect immediately, after which the track lyrics will be retrieved with mapping information and target lyrics; marking as pure music will directly return to pure music placeholder lyrics. Reset to retrieve by original data.
+
+
+ Lyrics preview
+
+
+ mapped as
+
+
+ Mark as pure music
+
+
+ Not found
+
+
+ Reset
+
+
+ Save changes
+
+
+ Search
+
+
+ Song info mapping
+
+
+ Target lyrics search provider
+
+
+ Title
+
Local .ESLRC files
@@ -485,7 +524,7 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
Lyrics backdrop
- Album Background Acrylic Effect Strength!
+ Album Background Acrylic Effect Strength
Lyrics background
@@ -695,13 +734,13 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
Lyrics background
- Album background layer ambiguity!
+ Album background layer ambiguity
- Album background layer opacity!
+ Album background layer opacity
- Album Background Layer Motion Rate!
+ Album Background Layer Motion Rate
Font color (Non-current playback area)
@@ -838,6 +877,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
Thin
+
+ Lyrics timeline sync
+
If the lyrics progress is jittery, try increasing this threshold; changing this value can cause lyrics synchronization to deviate
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
index 5c854a2..dbc4655 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
@@ -196,7 +196,7 @@
ブラウザの承認を完了してください
- BetterLyricsにLast.fmアカウントへのアクセスを許可してください!
+ BetterLyricsにLast.fmアカウントへのアクセスを許可してください
認可をキャンセルしました
@@ -205,7 +205,7 @@
ブラウザでキャンセル操作を完了してください
- Last.fmアカウントへのBetterLyricsアクセスを取り消します!
+ Last.fmアカウントへのBetterLyricsアクセスを取り消します
リブレットランスレートからの翻訳のリクエストが失敗しました。設定またはネイティブリブレットランレート構成を確認してください
@@ -219,6 +219,9 @@
歌詞プロバイダー
+
+ 手動で歌詞を検索します
+
歌詞スタイルと効果クイック設定
@@ -249,6 +252,42 @@
翻訳プロバイダー
+
+ アーティスト
+
+
+ *保存変更はすぐに有効になります。その後、トラックの歌詞がマッピング情報とターゲット歌詞で取得されます。純粋な音楽としてのマーキングは、純粋な音楽プレースホルダーの歌詞に直接戻ります。元のデータで取得するためにリセット。
+
+
+ 歌詞プレビュー
+
+
+ としてマッピングされました
+
+
+ 純粋な音楽としてマークしてください
+
+
+ 見つかりませんでした
+
+
+ リセット
+
+
+ 変更を保存
+
+
+ 検索する
+
+
+ 曲情報マッピング
+
+
+ ターゲット歌詞検索プロバイダー
+
+
+ タイトル
+
ローカル.ESLRCファイル
@@ -485,7 +524,7 @@
歌詞の背景素材
- アルバムの背景アクリル効果の強さ!
+ アルバムの背景アクリル効果の強さ
歌詞の背景
@@ -695,13 +734,13 @@
歌詞の背景
- アルバムの背景レイヤーの曖昧さ!
+ アルバムの背景レイヤーの曖昧さ
- アルバムの背景レイヤーの不透明度!
+ アルバムの背景レイヤーの不透明度
- アルバムの背景レイヤーのモーションレート!
+ アルバムの背景レイヤーのモーションレート
フォントカラー(非電流再生エリア)
@@ -844,6 +883,9 @@
歌詞タイムライン同期しきい値
+
+ 歌詞のタイムラインを同期
+
翻訳ハイライト
@@ -1058,6 +1100,6 @@
翻訳サーバーは設定されていません。最初に設定で構成してください
- BetterLyrics はすでに実行されています!
+ BetterLyrics はすでに実行されています
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
index 9a8c59e..51cb1a4 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
@@ -196,7 +196,7 @@
브라우저에서 승인을 완료하십시오
- Last.fm 계정에 BetterLyrics 액세스 권한을 부여하세요!
+ Last.fm 계정에 BetterLyrics 액세스 권한을 부여하세요
내 승인을 취소했습니다
@@ -205,7 +205,7 @@
브라우저에서 취소 작업을 완료하십시오
- Last.fm 계정에 대한 BetterLyrics 액세스를 취소하십시오!
+ Last.fm 계정에 대한 BetterLyrics 액세스를 취소하십시오
LibreTranslate에서 번역 요청 실패, 설정 또는 기본 LibreTranslate 구성을 확인하십시오.
@@ -219,6 +219,9 @@
가사 제공자
+
+ 가사를 수동으로 검색합니다
+
가사 스타일과 효과 빠른 설정
@@ -249,6 +252,42 @@
번역 제공자
+
+ 아티스트
+
+
+ * 변경 사항 저장 변경은 즉시 적용되며, 그 후 트랙 가사는 맵핑 정보와 대상 가사로 검색됩니다. 순수한 음악으로 표시하면 순수한 음악 자리 표시 자 가사로 직접 돌아갑니다. 원래 데이터로 검색하도록 재설정하십시오.
+
+
+ 가사 미리보기
+
+
+ 로 매핑됨
+
+
+ 순수한 음악으로 표시하세요
+
+
+ 찾을 수 없음
+
+
+ 재설정
+
+
+ 변경 사항 저장
+
+
+ 검색
+
+
+ 노래 정보 매핑
+
+
+ 가사 검색 공급자를 타겟팅하십시오
+
+
+ 제목
+
로컬 .ESLRC 파일
@@ -485,7 +524,7 @@
가사 배경 자료
- 앨범 배경 아크릴 효과 강도!
+ 앨범 배경 아크릴 효과 강도
가사 배경
@@ -695,13 +734,13 @@
가사 배경
- 앨범 배경 레이어 모호성!
+ 앨범 배경 레이어 모호성
- 앨범 배경 레이어 불투명도!
+ 앨범 배경 레이어 불투명도
- 앨범 배경 레이어 모션 속도!
+ 앨범 배경 레이어 모션 속도
글꼴 색상 (비 전류 재생 영역)
@@ -844,6 +883,9 @@
가사 타임 라인 동기화 임계 값
+
+ 가사 타임라인 동기화
+
번역 하이라이트
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
index cdc24a7..7a80a31 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
@@ -219,6 +219,9 @@
歌词来源
+
+ 手动检索歌词
+
歌词样式与效果快捷设置
@@ -249,6 +252,42 @@
翻译来源
+
+ 艺术家
+
+
+ * 保存更改立即生效,此后将以映射信息和目标歌词源检索该曲目歌词;标记为纯音乐将直接返回纯音乐占位歌词。重置以按原始数据检索。
+
+
+ 歌词预览
+
+
+ 映射为
+
+
+ 标记为纯音乐
+
+
+ 未找到
+
+
+ 重置
+
+
+ 保存更改
+
+
+ 搜索
+
+
+ 歌曲信息映射
+
+
+ 目标歌词搜索提供商
+
+
+ 标题
+
本地 .ESLRC 文件
@@ -844,6 +883,9 @@
歌词时间轴同步阈值
+
+ 歌词时间轴同步
+
翻译高亮
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
index c23988b..57785e8 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
@@ -219,6 +219,9 @@
歌詞來源
+
+ 手動檢索歌詞
+
歌詞樣式與效果快捷設置
@@ -249,6 +252,42 @@
翻譯來源
+
+ 藝術家
+
+
+ * 保存更改立即生效,此後將以映射信息和目標歌詞源檢索該曲目歌詞;標記為純音樂將直接返回純音樂佔位歌詞。重置以按原始數據檢索。
+
+
+ 歌詞預覽
+
+
+ 映射爲
+
+
+ 標記為純音樂
+
+
+ 找不到
+
+
+ 重設
+
+
+ 保存更改
+
+
+ 搜索
+
+
+ 歌曲信息映射
+
+
+ 目標歌詞搜尋提供者
+
+
+ 標題
+
本地 .ESLRC 文件
@@ -485,7 +524,7 @@
歌詞背景材質
- 專輯背景壓克力效果強度!
+ 專輯背景壓克力效果強度
歌詞背景
@@ -695,13 +734,13 @@
歌詞背景
- 專輯背景層模糊度!
+ 專輯背景層模糊度
- 專輯背景層不透明度!
+ 專輯背景層不透明度
- 專輯背景層運動速率!
+ 專輯背景層運動速率
字體顏色(非當前播放區域)
@@ -838,6 +877,9 @@
極細
+
+ 歌詞時間軌同步閾值
+
當歌詞進度抖動時,請嘗試增加該閾值;更改此值會導致歌詞同步偏差
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Update.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Update.cs
index cf41bd0..0d687d3 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Update.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Update.cs
@@ -673,7 +673,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
private void UpdateTimelineSyncThreshold()
{
- _timelineSyncThreshold = _mediaSessionsService.GetCurrentMediaSourceProviderInfo()?.TimelineSyncThreshold ?? 0;
+ var current = _mediaSessionsService.GetCurrentMediaSourceProviderInfo();
+ _timelineSyncThreshold = current?.TimelineSyncThreshold ?? 0;
}
private void UpdatePositionOffset()
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsSearchControlViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsSearchControlViewModel.cs
new file mode 100644
index 0000000..f6c370f
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsSearchControlViewModel.cs
@@ -0,0 +1,166 @@
+using BetterLyrics.WinUI3.Helper;
+using BetterLyrics.WinUI3.Models;
+using BetterLyrics.WinUI3.Models.Settings;
+using BetterLyrics.WinUI3.Services.LyricsSearchService;
+using BetterLyrics.WinUI3.Services.MediaSessionsService;
+using BetterLyrics.WinUI3.Services.SettingsService;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using CommunityToolkit.Mvvm.Messaging;
+using CommunityToolkit.Mvvm.Messaging.Messages;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.ViewModels
+{
+ public partial class LyricsSearchControlViewModel : BaseViewModel
+ {
+ private readonly ILyricsSearchService _lyricsSearchService;
+ private readonly IMediaSessionsService _mediaSessionsService;
+ private readonly ISettingsService _settingsService;
+ private LatestOnlyTaskRunner _lyricsSearchRunner = new();
+
+ [ObservableProperty]
+ public partial AppSettings AppSettings { get; set; }
+
+ [ObservableProperty]
+ public partial ObservableCollection LyricsSearchResults { get; set; } = [];
+
+ [ObservableProperty]
+ public partial LyricsSearchResult? SelectedLyricsSearchResult { get; set; }
+
+ [ObservableProperty]
+ public partial LyricsData? LyricsData { get; set; }
+
+ [ObservableProperty]
+ public partial MappedSongSearchQuery? MappedSongSearchQuery { get; set; }
+
+ [ObservableProperty]
+ public partial bool IsSearching { get; set; } = false;
+
+ public LyricsSearchControlViewModel(ILyricsSearchService lyricsSearchService, IMediaSessionsService mediaSessionsService, ISettingsService settingsService)
+ {
+ _lyricsSearchService = lyricsSearchService;
+ _mediaSessionsService = mediaSessionsService;
+ _settingsService = settingsService;
+
+ AppSettings = _settingsService.AppSettings;
+
+ _mediaSessionsService.SongInfoChanged += MediaSessionsService_SongInfoChanged;
+
+ InitMappedSongSearchQuery();
+ }
+
+ private void MediaSessionsService_SongInfoChanged(object? sender, Events.SongInfoChangedEventArgs e)
+ {
+ InitMappedSongSearchQuery();
+ }
+
+ private void InitMappedSongSearchQuery()
+ {
+ LyricsSearchResults.Clear();
+ if (_mediaSessionsService.SongInfo != null)
+ {
+ var found = GetMappedSongSearchQueryFromSettings();
+ if (found == null)
+ {
+ MappedSongSearchQuery = new MappedSongSearchQuery
+ {
+ OriginalTitle = _mediaSessionsService.SongInfo.Title,
+ OriginalArtist = _mediaSessionsService.SongInfo.Artist,
+ MappedTitle = _mediaSessionsService.SongInfo.Title,
+ MappedArtist = _mediaSessionsService.SongInfo.Artist,
+ };
+ }
+ else
+ {
+ MappedSongSearchQuery = found.Clone();
+ }
+ }
+ }
+
+ private MappedSongSearchQuery? GetMappedSongSearchQueryFromSettings()
+ {
+ if (_mediaSessionsService.SongInfo == null)
+ {
+ return null;
+ }
+ var found = AppSettings.MappedSongSearchQueries
+ .Where(x => x.OriginalTitle == _mediaSessionsService.SongInfo.Title && x.OriginalArtist == _mediaSessionsService.SongInfo.Artist).FirstOrDefault();
+ return found;
+ }
+
+ [RelayCommand]
+ private void Search()
+ {
+ if (MappedSongSearchQuery == null)
+ {
+ return;
+ }
+
+ IsSearching = true;
+ LyricsSearchResults.Clear();
+ MappedSongSearchQuery.LyricsSearchProvider = null;
+ _ = _lyricsSearchRunner.RunAsync(async (token) =>
+ {
+ LyricsSearchResults = [..await Task.Run(async () =>
+ {
+ return await _lyricsSearchService.SearchAllAsync(
+ MappedSongSearchQuery.MappedTitle,
+ MappedSongSearchQuery.MappedArtist,
+ _mediaSessionsService.SongInfo?.Album ?? "",
+ _mediaSessionsService.SongInfo?.DurationMs ?? 0, token);
+ }, token)];
+ IsSearching = false;
+ });
+ }
+
+ [RelayCommand]
+ private void Save()
+ {
+ if (MappedSongSearchQuery == null)
+ {
+ return;
+ }
+
+ var existing = GetMappedSongSearchQueryFromSettings();
+ if (existing != null)
+ {
+ AppSettings.MappedSongSearchQueries.Remove(existing);
+ }
+ AppSettings.MappedSongSearchQueries.Add(MappedSongSearchQuery);
+ MappedSongSearchQuery = MappedSongSearchQuery.Clone();
+ }
+
+ [RelayCommand]
+ private void Reset()
+ {
+ var existing = GetMappedSongSearchQueryFromSettings();
+ if (existing != null)
+ {
+ AppSettings.MappedSongSearchQueries.Remove(existing);
+ }
+ InitMappedSongSearchQuery();
+ SelectedLyricsSearchResult = null;
+ }
+
+ partial void OnSelectedLyricsSearchResultChanged(LyricsSearchResult? value)
+ {
+ MappedSongSearchQuery?.LyricsSearchProvider = value?.Provider;
+ if (value?.Raw != null)
+ {
+ var lyricsParser = new LyricsParser();
+ var lyricsDataArr = lyricsParser.Parse(value?.Raw, (int?)_mediaSessionsService.SongInfo?.DurationMs);
+ LyricsData = lyricsDataArr.FirstOrDefault();
+ }
+ else
+ {
+ LyricsData = null;
+ }
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs
index 2f92859..9cf76b6 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs
@@ -80,14 +80,17 @@ namespace BetterLyrics.WinUI3.ViewModels
var file = await picker.PickSingleFileAsync();
- var succeed = _settingsService.ImportSettings(file.Path);
- if (succeed)
+ if (file != null)
{
- WindowHelper.RestartApp();
- }
- else
- {
- App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader?.GetString("ImportSettingsFailed") ?? "");
+ var succeed = _settingsService.ImportSettings(file.Path);
+ if (succeed)
+ {
+ WindowHelper.RestartApp();
+ }
+ else
+ {
+ App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader?.GetString("ImportSettingsFailed") ?? "");
+ }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml
index 9bffa42..79415ad 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml
@@ -237,7 +237,25 @@
-
+
+
+