diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest index e9e170f..9925b8f 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest @@ -12,7 +12,7 @@ + Version="1.0.11.0" /> diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Discord.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Discord.png new file mode 100644 index 0000000..c49cc20 Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Discord.png differ diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/QQ.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/QQ.png new file mode 100644 index 0000000..b498b85 Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/QQ.png differ diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LineRenderingType.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LineRenderingType.cs index f78d472..c823797 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LineRenderingType.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LineRenderingType.cs @@ -4,7 +4,8 @@ namespace BetterLyrics.WinUI3.Enums { public enum LineRenderingType { - UntilCurrentChar, - CurrentCharOnly, + CurrentChar, + LineStartToCurrentChar, + CurrentLine } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/CollectionHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/CollectionHelper.cs deleted file mode 100644 index d8a304f..0000000 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/CollectionHelper.cs +++ /dev/null @@ -1,15 +0,0 @@ -// 2025/6/23 by Zhe Fang - -using System.Collections.Generic; - -namespace BetterLyrics.WinUI3.Helper -{ - public static class CollectionHelper - { - public static T? SafeGet(this IList list, int index) - { - if (list == null || index < 0 || index >= list.Count) return default; - return list[index]; - } - } -} diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DesktopModeHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DesktopModeHelper.cs index 8396c54..6d6855b 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DesktopModeHelper.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DesktopModeHelper.cs @@ -47,13 +47,6 @@ namespace BetterLyrics.WinUI3.Helper _originalWindowBounds.Remove(hwnd); } - // »Ö¸´Ñùʽ - if (_originalWindowStyles.TryGetValue(hwnd, out var style)) - { - window.SetWindowStyle(style); - _originalWindowStyles.Remove(hwnd); - } - window.SetIsShownInSwitchers(true); } @@ -83,10 +76,6 @@ namespace BetterLyrics.WinUI3.Helper new Windows.Graphics.RectInt32(targetX, targetY, targetWidth, targetHeight) ); - // ¼ÇÒäÔ­Ñùʽ - if (!_originalWindowStyles.ContainsKey(hwnd)) - _originalWindowStyles[hwnd] = window.GetWindowStyle(); - // ¼ÇÒäÔ­TopMost״̬ if (!_originalTopmostStates.ContainsKey(hwnd)) _originalTopmostStates[hwnd] = window.GetIsAlwaysOnTop(); @@ -95,8 +84,6 @@ namespace BetterLyrics.WinUI3.Helper window.SetIsAlwaysOnTop(true); window.SetIsShownInSwitchers(false); - - window.ToggleWindowStyle(true, WindowStyle.Popup | WindowStyle.Visible); } public static void SetClickThrough(Window window, bool enable) @@ -105,11 +92,22 @@ namespace BetterLyrics.WinUI3.Helper int exStyle = User32.GetWindowLong(hwnd, User32.WindowLongFlags.GWL_EXSTYLE); if (enable) { + // ¼ÇÒäÔ­Ñùʽ + if (!_originalWindowStyles.ContainsKey(hwnd)) + _originalWindowStyles[hwnd] = window.GetWindowStyle(); + + window.ToggleWindowStyle(true, WindowStyle.Popup | WindowStyle.Visible); User32.SetWindowLong(hwnd, User32.WindowLongFlags.GWL_EXSTYLE, exStyle | (int)User32.WindowStylesEx.WS_EX_TRANSPARENT | (int)User32.WindowStylesEx.WS_EX_LAYERED); } else { User32.SetWindowLong(hwnd, User32.WindowLongFlags.GWL_EXSTYLE, exStyle & ~(int)User32.WindowStylesEx.WS_EX_TRANSPARENT); + // »Ö¸´Ñùʽ + if (_originalWindowStyles.TryGetValue(hwnd, out var style)) + { + window.SetWindowStyle(style); + _originalWindowStyles.Remove(hwnd); + } } } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs index e60032c..815764d 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs @@ -69,9 +69,9 @@ namespace BetterLyrics.WinUI3.Helper public static bool IsSwitchableNormalizedMatch(string fileName, string q1, string q2) { - var normFileName = fileName.Normalize(); - var normQ1 = q1.Normalize(); - var normQ2 = q2.Normalize(); + var normFileName = StringHelper.Normalize(fileName.Normalize()); + var normQ1 = StringHelper.Normalize(q1); + var normQ2 = StringHelper.Normalize(q2); // 常è§ä¸¤ç§é¡ºåº return normFileName == normQ1 + normQ2 diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs index 4b3202b..2a22ccc 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs @@ -102,7 +102,7 @@ namespace BetterLyrics.WinUI3.Helper } } - public static List GetAccentColorsFromByte(byte[] bytes) + public static List GetAccentColorsFromByte(byte[] bytes) { // 使用 ImageSharp 读å–图片 using var image = SixLabors.ImageSharp.Image.Load(bytes); @@ -172,21 +172,21 @@ namespace BetterLyrics.WinUI3.Helper return memoryStream.ToArray(); } - //public static float GetAverageLuminance(CanvasBitmap bitmap) - //{ - // var pixels = bitmap.GetPixelBytes(); - // double sum = 0; - // for (int i = 0; i < pixels.Length; i += 4) - // { - // // BGRA - // byte b = pixels[i]; - // byte g = pixels[i + 1]; - // byte r = pixels[i + 2]; - // // 忽略A - // double y = 0.299 * r + 0.587 * g + 0.114 * b; - // sum += y / 255.0; - // } - // return (float)(sum / (pixels.Length / 4)); - //} + public static float GetAverageLuminance(CanvasBitmap bitmap) + { + var pixels = bitmap.GetPixelBytes(); + double sum = 0; + for (int i = 0; i < pixels.Length; i += 4) + { + // BGRA + byte b = pixels[i]; + byte g = pixels[i + 1]; + byte r = pixels[i + 2]; + // 忽略A + double y = 0.299 * r + 0.587 * g + 0.114 * b; + sum += y / 255.0; + } + return (float)(sum / (pixels.Length / 4)); + } } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs index 6f0751f..591546a 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs @@ -1,4 +1,5 @@ using BetterLyrics.WinUI3.Helper; +using CommunityToolkit.Mvvm.DependencyInjection; using Lyricify.Lyrics.Helpers.General; using NTextCat; using System; @@ -12,6 +13,7 @@ namespace BetterLyrics.WinUI3.Services { private static readonly RankedLanguageIdentifierFactory _factory = new(); private static readonly RankedLanguageIdentifier _identifier; + private static readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService(); public static List SupportedTargetLanguages => [ @@ -106,5 +108,10 @@ namespace BetterLyrics.WinUI3.Services // 其他语言直接返回两字æ¯ä»£ç  return code; } + + public static string GetUserTargetLanguageCode() + { + return SupportedTargetLanguages[_settingsService.SelectedTargetLanguageIndex].Code; + } } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs index 0a200c2..772d6c3 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs @@ -10,29 +10,21 @@ using System.Linq; using System.Text.RegularExpressions; using System.Xml.Linq; using Windows.Globalization.Fonts; +using LyricsData = BetterLyrics.WinUI3.Models.LyricsData; namespace BetterLyrics.WinUI3.Helper { public class LyricsParser { - private List> _multiLangLyricsLines = []; + private List _lyricsDataArr = []; - public List> Parse(string? raw, int durationMs) + public List Parse(string? raw, int? durationMs) { - _multiLangLyricsLines = []; + durationMs ??= (int)TimeSpan.FromMinutes(99).TotalMilliseconds; + _lyricsDataArr = []; if (raw == null) { - _multiLangLyricsLines.Add( - [ - new LyricsLine - { - StartMs = 0, - EndMs = durationMs, - OriginalText = App.ResourceLoader!.GetString("LyricsNotFound"), - CharTimings = [], - }, - ] - ); + _lyricsDataArr.Add(LyricsData.GetNotfoundPlaceholder(durationMs.Value)); } else { @@ -43,10 +35,10 @@ namespace BetterLyrics.WinUI3.Helper ParseLrc(raw); break; case LyricsFormat.Qrc: - ParseUsingLyricify(Lyricify.Lyrics.Parsers.QrcParser.Parse(raw).Lines); + ParseQQNeteaseKugou(Lyricify.Lyrics.Parsers.QrcParser.Parse(raw).Lines); break; case LyricsFormat.Krc: - ParseUsingLyricify(Lyricify.Lyrics.Parsers.KrcParser.Parse(raw).Lines); + ParseQQNeteaseKugou(Lyricify.Lyrics.Parsers.KrcParser.Parse(raw).Lines); break; case LyricsFormat.Ttml: ParseTtml(raw); @@ -55,8 +47,8 @@ namespace BetterLyrics.WinUI3.Helper break; } } - PostProcessLyricsLines(durationMs); - return _multiLangLyricsLines; + PostProcessLyricsLines(durationMs.Value); + return _lyricsDataArr; } private void ParseLrc(string raw) @@ -120,9 +112,9 @@ namespace BetterLyrics.WinUI3.Helper int languageCount = grouped.Max(g => g.Count()); // åˆå§‹åŒ–æ¯ç§è¯­è¨€çš„æ­Œè¯åˆ—表 - _multiLangLyricsLines.Clear(); + _lyricsDataArr.Clear(); for (int i = 0; i < languageCount; i++) - _multiLangLyricsLines.Add(new List()); + _lyricsDataArr.Add(new LyricsData()); // é历æ¯ä¸ªæ—¶é—´åˆ†ç»„ foreach (var group in grouped) @@ -159,7 +151,7 @@ namespace BetterLyrics.WinUI3.Helper currentIndex += charText?.Length ?? 0; } } - _multiLangLyricsLines[langIdx].Add(line); + _lyricsDataArr[langIdx].LyricsLines.Add(line); } } } @@ -259,9 +251,9 @@ namespace BetterLyrics.WinUI3.Helper }); } } - _multiLangLyricsLines.Add(originalLines); + _lyricsDataArr.Add(new LyricsData(originalLines)); if (translationLines.Count > 0) - _multiLangLyricsLines.Add(translationLines); + _lyricsDataArr.Add(new LyricsData(translationLines)); } catch { @@ -330,7 +322,7 @@ namespace BetterLyrics.WinUI3.Helper return 0; } - private void ParseUsingLyricify(List? lines) + private void ParseQQNeteaseKugou(List? lines) { lines = lines?.Where(x => x.Text != string.Empty).ToList(); List lyricsLines = []; @@ -384,27 +376,27 @@ namespace BetterLyrics.WinUI3.Helper } } - _multiLangLyricsLines.Add(lyricsLines); + _lyricsDataArr.Add(new LyricsData(lyricsLines)); } private void PostProcessLyricsLines(int durationMs) { - for (int langIdx = 0; langIdx < _multiLangLyricsLines.Count; langIdx++) + for (int langIdx = 0; langIdx < _lyricsDataArr.Count; langIdx++) { - var linesInSingleLang = _multiLangLyricsLines[langIdx]; - for (int i = 0; i < linesInSingleLang.Count; i++) + var lines = _lyricsDataArr[langIdx].LyricsLines; + for (int i = 0; i < lines.Count; i++) { - if (i + 1 < linesInSingleLang.Count) + if (i + 1 < lines.Count) { - linesInSingleLang[i].EndMs = linesInSingleLang[i + 1].StartMs; + lines[i].EndMs = lines[i + 1].StartMs; } else { - linesInSingleLang[i].EndMs = durationMs; + lines[i].EndMs = durationMs; } // 修正 CharTimings çš„ EndMs - var timings = linesInSingleLang[i].CharTimings; + var timings = lines[i].CharTimings; if (timings.Count > 0) { for (int j = 0; j < timings.Count; j++) @@ -415,21 +407,21 @@ namespace BetterLyrics.WinUI3.Helper } else { - timings[j].EndMs = linesInSingleLang[i].EndMs; + timings[j].EndMs = lines[i].EndMs; } } } } - if (linesInSingleLang.Count > 0) + if (lines.Count > 0) { - if (linesInSingleLang[0].StartMs > 0) + if (lines[0].StartMs > 0) { - linesInSingleLang.Insert( + lines.Insert( 0, new LyricsLine { StartMs = 0, - EndMs = linesInSingleLang[0].StartMs, + EndMs = lines[0].StartMs, OriginalText = "â— â— â—", CharTimings = [], } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/MetadataHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/MetadataHelper.cs index c824dcc..c30c5c6 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/MetadataHelper.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/MetadataHelper.cs @@ -27,6 +27,8 @@ namespace BetterLyrics.WinUI3.Helper } public const string GithubUrl = "https://github.com/jayfunc/BetterLyrics"; + public const string QQGroupUrl = "https://qun.qq.com/universal-share/share?ac=1&authKey=4Q%2BYTq3wZldYpF5SbS5c19ECFsiYoLZFAIcBNNzYpBUtiEjaZ8sZ%2F%2BnFN0qw3lad&busi_data=eyJncm91cENvZGUiOiIxMDU0NzAwMzg4IiwidG9rZW4iOiJiVnhqemVYN0N5QVc3b1ZkR24wWmZOTUtvUkJoWm1JRWlaWW5iZnlBcXJtZUtGc2FFTHNlUlFZMi9iRm03cWF5IiwidWluIjoiMTM5NTczOTY2MCJ9&data=39UmAihyH_o6CZaOs7nk2mO_lz2ruODoDou6pxxh7utcxP4WF5sbDBDOPvZ_Wqfzeey4441anegsLYQJxkrBAA&svctype=4&tempid=h5_group_info"; + public const string DiscordUrl = "https://discord.gg/5yAQPnyCKv"; public static async Task GetBuildDate() { diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs index 88038d2..3453b6e 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs @@ -20,18 +20,26 @@ namespace BetterLyrics.WinUI3.Helper public static string LogDirectory => Path.Combine(CacheFolder, "logs"); public static string LogFilePattern => Path.Combine(LogDirectory, "log-.txt"); - public static string LrcLibLyricsCacheDirectory => Path.Combine(CacheFolder, "lrclib-lyrics"); - public static string NeteaseLyricsCacheDirectory => Path.Combine(CacheFolder, "netease-lyrics"); - public static string QQLyricsCacheDirectory => Path.Combine(CacheFolder, "qq-lyrics"); - public static string KugouLyricsCacheDirectory => Path.Combine(CacheFolder, "kugou-lyrics"); - public static string AmllTtmlDbLyricsCacheDirectory => Path.Combine(CacheFolder, "amll-ttml-db-lyrics"); - public static string AmllTtmlDbIndexPath => Path.Combine(CacheFolder, "amll-ttml-db-index.json"); + public static string LyricsCacheDirectory => Path.Combine(CacheFolder, "lyrics"); - public static string iTunesAlbumArtCacheDirectory => Path.Combine(CacheFolder, "itunes-album-art"); + public static string LrcLibLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "lrclib"); + public static string NeteaseLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "netease"); + public static string QQLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "qq"); + public static string KugouLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "kugou"); + public static string AmllTtmlDbLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "amll-ttml-db"); + public static string AmllTtmlDbIndexPath => Path.Combine(LyricsCacheDirectory, "amll-ttml-db-index.json"); + 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 AlbumArtCacheDirectory => Path.Combine(CacheFolder, "album-art"); + + public static string iTunesAlbumArtCacheDirectory => Path.Combine(AlbumArtCacheDirectory, "itunes"); public static void EnsureDirectories() { - Directory.CreateDirectory(LocalFolder); Directory.CreateDirectory(LogDirectory); Directory.CreateDirectory(LrcLibLyricsCacheDirectory); @@ -40,6 +48,8 @@ namespace BetterLyrics.WinUI3.Helper Directory.CreateDirectory(NeteaseLyricsCacheDirectory); Directory.CreateDirectory(AmllTtmlDbLyricsCacheDirectory); + Directory.CreateDirectory(QQTranslationCacheDirectory); + Directory.CreateDirectory(iTunesAlbumArtCacheDirectory); } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/StringHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/StringHelper.cs index a10b6d5..bd6ce23 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/StringHelper.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/StringHelper.cs @@ -9,10 +9,11 @@ namespace BetterLyrics.WinUI3.Helper public static class StringHelper { // åŽ»é™¤ç©ºæ ¼ã€æ‹¬å·ã€ä¸‹åˆ’çº¿ã€æ¨ªæ ã€ç‚¹ã€å¤§å°å†™ç­‰ - public static string Normalize(this string s) => + public static string Normalize(string s) => new string(s .Where(c => char.IsLetterOrDigit(c)) .ToArray()) .ToLowerInvariant(); + public static string NewLine = "\n"; } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsData.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsData.cs new file mode 100644 index 0000000..da6de05 --- /dev/null +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsData.cs @@ -0,0 +1,95 @@ +using BetterLyrics.WinUI3.Helper; +using BetterLyrics.WinUI3.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BetterLyrics.WinUI3.Models +{ + public class LyricsData + { + public List LyricsLines { get; set; } + public string? LanguageCode => LanguageHelper.DetectLanguageCode(WrappedOriginalText); + public string WrappedOriginalText => string.Join(StringHelper.NewLine, LyricsLines.Select(line => line.OriginalText)); + + public LyricsData() + { + LyricsLines = []; + } + + public LyricsData(List lyricsLines) + { + LyricsLines = lyricsLines; + } + + public void SetDisplayedTextAlongWith(LyricsData translationData) + { + int i = 0; + foreach (var line in LyricsLines) + { + if (i >= translationData.LyricsLines.Count) + { + line.DisplayedText = line.OriginalText; // No translation available, keep original text + } + else + { + line.DisplayedText = $"{line.OriginalText}{StringHelper.NewLine}({translationData.LyricsLines[i].OriginalText})"; + } + i++; + } + } + + public void SetDisplayedTextAlongWith(string translation) + { + List translationArr = translation.Split(StringHelper.NewLine).ToList(); + int i = 0; + foreach (var line in LyricsLines) + { + if (i >= translationArr.Count) + { + line.DisplayedText = line.OriginalText; // No translation available, keep original text + } + else + { + line.DisplayedText = $"{line.OriginalText}{StringHelper.NewLine}({translationArr[i]})"; + } + i++; + } + } + + public void SetDisplayedTextInOriginalText() + { + foreach (var line in LyricsLines) + { + line.DisplayedText = line.OriginalText; + } + } + + public static LyricsData GetNotfoundPlaceholder(int durationMs) + { + return new LyricsData([new LyricsLine + { + StartMs = 0, + EndMs = durationMs, + OriginalText = App.ResourceLoader!.GetString("LyricsNotFound"), + CharTimings = [], + }]); + } + + public static LyricsData GetLoadingPlaceholder() + { + return new LyricsData([ + new LyricsLine + { + StartMs = 0, + EndMs = (int)TimeSpan.FromMinutes(99).TotalMilliseconds, + OriginalText = "â— â— â—", + DisplayedText = "â— â— â—", + CharTimings = [], + }, + ]); + } + } +} diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ISettingsService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ISettingsService.cs index 6de4158..b94f924 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ISettingsService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ISettingsService.cs @@ -67,6 +67,7 @@ namespace BetterLyrics.WinUI3.Services LyricsFontWeight LyricsFontWeight { get; set; } LineRenderingType LyricsGlowEffectScope { get; set; } + LineRenderingType LyricsHighlightScope { get; set; } float LyricsLineSpacingFactor { get; set; } @@ -84,5 +85,7 @@ namespace BetterLyrics.WinUI3.Services bool IsTranslationEnabled { get; set; } LyricsDisplayType PreferredDisplayType { get; set; } + + int TimelineSyncThreshold { get; set; } } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ITranslateService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ITranslateService.cs index 527fa8d..25a6282 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ITranslateService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ITranslateService.cs @@ -1,4 +1,5 @@ -using System; +using BetterLyrics.WinUI3.Models; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -9,6 +10,8 @@ namespace BetterLyrics.WinUI3.Services { public interface ITranslateService { - Task TranslateAsync(string text, string targetLangCode, CancellationToken? token); + Task TranslateTextAsync(string text, string targetLangCode, CancellationToken? token); + + int SearchTranslatedLyricsItself(List lyricsDataArr); } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService.cs index de097ac..d686d2c 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService.cs @@ -15,6 +15,7 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Windows.Storage; namespace BetterLyrics.WinUI3.Services { @@ -39,6 +40,23 @@ namespace BetterLyrics.WinUI3.Services _amllTtmlDbHttpClient = new(); } + private static bool IsAmllTtmlDbIndexInvalid() + { + bool existed = File.Exists(PathHelper.AmllTtmlDbIndexPath); + + if (!existed) + { + return true; + } + else + { + long currentTs = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + string lastUpdatedStr = File.ReadAllText(PathHelper.AmllTtmlDbLastUpdatedPath); + long lastUpdated = Convert.ToInt64(lastUpdatedStr); + return currentTs - lastUpdated > 1 * 24 * 60 * 60; + } + } + public async Task DownloadAmllTtmlDbIndexAsync() { const string url = "https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/refs/heads/main/metadata/raw-lyrics-index.jsonl"; @@ -56,6 +74,9 @@ namespace BetterLyrics.WinUI3.Services ); await stream.CopyToAsync(fs); + long currentTs = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + File.WriteAllText(PathHelper.AmllTtmlDbLastUpdatedPath, currentTs.ToString()); + return true; } catch @@ -192,11 +213,10 @@ namespace BetterLyrics.WinUI3.Services private async Task SearchAmllTtmlDbAsync(string title, string artist) { - // 检索本地 JSONL 索引文件,查找 rawLyricFile - if (!File.Exists(PathHelper.AmllTtmlDbIndexPath)) + if (IsAmllTtmlDbIndexInvalid()) { var downloadOk = await DownloadAmllTtmlDbIndexAsync(); - if (!downloadOk || !File.Exists(PathHelper.AmllTtmlDbIndexPath)) + if (!downloadOk) return null; } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService.cs index 46726a9..ef2cebd 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService.cs @@ -62,6 +62,7 @@ namespace BetterLyrics.WinUI3.Services private const string LyricsFontSizeKey = "LyricsFontSize"; private const string LyricsFontWeightKey = "LyricsFontWeightKey"; private const string LyricsGlowEffectScopeKey = "LyricsGlowEffectScope"; + private const string LyricsHighlightSopeKey = "LyricsHighlightSope"; private const string LyricsLineSpacingFactorKey = "LyricsLineSpacingFactor"; private const string LyricsSearchProvidersInfoKey = "LyricsSearchProvidersInfo"; private const string AlbumArtSearchProvidersInfoKey = "AlbumArtSearchProvidersInfo"; @@ -80,6 +81,8 @@ namespace BetterLyrics.WinUI3.Services private const string LyricsScrollEasingTypeKey = "LyricsScrollEasingType"; private const string LyricsScrollDurationKey = "LyricsScrollDuration"; + public const string TimelineSyncThresholdKey = "TimelineSyncThreshold"; + private readonly ApplicationDataContainer _localSettings; public SettingsService() @@ -155,7 +158,7 @@ namespace BetterLyrics.WinUI3.Services SetDefault(IsCoverOverlayEnabledKey, true); SetDefault(IsDynamicCoverOverlayEnabledKey, true); SetDefault(CoverOverlayOpacityKey, 100); // 100 % = 1.0 - SetDefault(CoverOverlayBlurAmountKey, 200); + SetDefault(CoverOverlayBlurAmountKey, 100); SetDefault(CoverImageRadiusKey, 12); // 12 % // Lyrics SetDefault(LyricsAlignmentTypeKey, (int)TextAlignmentType.Center); @@ -177,7 +180,8 @@ namespace BetterLyrics.WinUI3.Services SetDefault(LyricsLineSpacingFactorKey, 0.5f); SetDefault(LyricsVerticalEdgeOpacityKey, 0); SetDefault(IsLyricsGlowEffectEnabledKey, true); - SetDefault(LyricsGlowEffectScopeKey, (int)LineRenderingType.CurrentCharOnly); + SetDefault(LyricsGlowEffectScopeKey, (int)LineRenderingType.CurrentChar); + SetDefault(LyricsHighlightSopeKey, (int)LineRenderingType.LineStartToCurrentChar); SetDefault(IsFanLyricsEnabledKey, false); SetDefault(LibreTranslateServerKey, ""); @@ -190,6 +194,7 @@ namespace BetterLyrics.WinUI3.Services SetDefault(LyricsScrollEasingTypeKey, (int)EasingType.EaseInOutQuad); SetDefault(LyricsScrollDurationKey, 500); // 500ms + SetDefault(TimelineSyncThresholdKey, 0); // 0ms } public EasingType LyricsScrollEasingType @@ -419,6 +424,12 @@ namespace BetterLyrics.WinUI3.Services set => SetValue(LyricsGlowEffectScopeKey, (int)value); } + public LineRenderingType LyricsHighlightScope + { + get => (LineRenderingType)GetValue(LyricsHighlightSopeKey); + set => SetValue(LyricsHighlightSopeKey, (int)value); + } + public float LyricsLineSpacingFactor { get => GetValue(LyricsLineSpacingFactorKey); @@ -506,6 +517,12 @@ namespace BetterLyrics.WinUI3.Services set => SetValue(IgnoreFullscreenWindowKey, value); } + public int TimelineSyncThreshold + { + get => GetValue(TimelineSyncThresholdKey); + set => SetValue(TimelineSyncThresholdKey, value); + } + private T? GetValue(string key) { if (_localSettings.Values.TryGetValue(key, out object? value)) diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService.cs index 474c7de..ab40cb8 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService.cs @@ -1,6 +1,7 @@ using BetterLyrics.WinUI3.Helper; using BetterLyrics.WinUI3.Models; using BetterLyrics.WinUI3.Serialization; +using BetterLyrics.WinUI3.ViewModels; using Lyricify.Lyrics.Helpers.General; using System; using System.Collections.Generic; @@ -13,19 +14,16 @@ using System.Threading.Tasks; namespace BetterLyrics.WinUI3.Services { - public class TranslateService : ITranslateService + public class TranslateService : BaseViewModel, ITranslateService { - private readonly ISettingsService _settingsService; - private readonly HttpClient _httpClient; - public TranslateService(ISettingsService settingsService) + public TranslateService(ISettingsService settingsService) :base(settingsService) { - _settingsService = settingsService; _httpClient = new HttpClient(); } - public async Task TranslateAsync(string text, string targetLangCode, CancellationToken? token) + public async Task TranslateTextAsync(string text, string targetLangCode, CancellationToken? token) { if (string.IsNullOrWhiteSpace(text)) { @@ -46,6 +44,19 @@ namespace BetterLyrics.WinUI3.Services return ChineseConverter.ConvertToTraditionalChinese(text); } + if (string.IsNullOrEmpty(_settingsService.LibreTranslateServer)) + { + _dispatcherQueue.TryEnqueue(() => + { + App.Current.LyricsWindowNotificationPanel?.Notify( + App.ResourceLoader!.GetString("TranslateServerNotSet"), + Microsoft.UI.Xaml.Controls.InfoBarSeverity.Warning + ); + }); + + throw new InvalidOperationException("LibreTranslate server URL is not configured."); + } + var url = $"{_settingsService.LibreTranslateServer}/translate"; var response = await _httpClient.PostAsync(url, new FormUrlEncodedContent( [ @@ -62,5 +73,21 @@ namespace BetterLyrics.WinUI3.Services var result = System.Text.Json.JsonSerializer.Deserialize(json, SourceGenerationContext.Default.TranslateResponse); return result?.TranslatedText ?? string.Empty; } + + public int SearchTranslatedLyricsItself(List lyricsDataArr) + { + string targetLangCode = LanguageHelper.GetUserTargetLanguageCode(); + if (lyricsDataArr.Count > 1) + { + for (int i = 1; i < lyricsDataArr.Count; i++) + { + if (lyricsDataArr[i].LanguageCode == targetLangCode) + { + return i; // Translation lyrics data found + } + } + } + return -1; // No translation lyrics data found + } } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw index ea523a6..6132af7 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw @@ -310,7 +310,7 @@ No music playing now - Developer options + Advanced options Play test music @@ -459,13 +459,10 @@ Extra Black - - Whole lyrics - - + Current line - + Current char @@ -717,4 +714,25 @@ Ease-in-out cubic + + Current line start to current char + + + Highlight scope + + + Lyrics timeline sync threshold + + + If the lyrics progress is jittery, try increasing this threshold; changing this value can cause lyrics synchronization to deviate + + + QQ feedback & chat group + + + Discord + + + Join now + \ No newline at end of file diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw index 93b3b0d..002b876 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw @@ -310,7 +310,7 @@ 今ã¯éŸ³æ¥½ãŒå†ç”Ÿã•れã¦ã„ã¾ã›ã‚“ - 開発者オプション + 高度ãªã‚ªãƒ—ション テスト音楽をå†ç”Ÿã—ã¾ã™ @@ -459,13 +459,10 @@ 余分ãªé»’ - - 歌詞全体 - - + ç¾åœ¨ã®è¡Œ - + ç¾åœ¨ã®æ–‡å­— @@ -717,4 +714,25 @@ 3ã¤ã®é…ã„インã¨ã‚¢ã‚¦ãƒˆ + + ç¾åœ¨ã®ãƒ©ã‚¤ãƒ³ãŒç¾åœ¨ã®æ–‡å­—ã‹ã‚‰å§‹ã¾ã‚Šã¾ã™ + + + ãƒã‚¤ãƒ©ã‚¤ãƒˆã‚¹ã‚³ãƒ¼ãƒ— + + + æ­Œè©žã‚¿ã‚¤ãƒ ãƒ©ã‚¤ãƒ³åŒæœŸã—ãã„値 + + + 歌詞ã®é€²è¡ŒãŒä¸å®‰å®šãªå ´åˆã¯ã€ã“ã®ã—ãã„値を増やã—ã¦ã¿ã¦ãã ã•ã„。ã“ã®å€¤ã‚’変更ã™ã‚‹ã¨ã€æ­Œè©žã®åŒæœŸãŒé€¸è„±ã™ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ + + + QQフィードãƒãƒƒã‚¯ï¼†ãƒãƒ£ãƒƒãƒˆã‚°ãƒ«ãƒ¼ãƒ— + + + Discord + + + 今ã™ãå‚加ã—ã¦ãã ã•ã„ + \ 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 8bc6aea..b6c61de 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw @@ -310,7 +310,7 @@ 지금 ìŒì•…ì´ ìž¬ìƒë˜ì§€ 않습니다 - ê°œë°œìž ì˜µì…˜ + 고급 옵션 테스트 ìŒì•…ì„ ìž¬ìƒí•˜ì‹­ì‹œì˜¤ @@ -459,13 +459,10 @@ ì—¬ë¶„ì˜ ê²€ì€ ìƒ‰ - - ì „ì²´ 가사 - - + 현재 ë¼ì¸ - + 현재 숯 @@ -717,4 +714,25 @@ 세 번 ëŠë¦¬ê²Œ 안팎으로 + + 현재 ë¼ì¸ì€ 현재 숯으로 시작합니다 + + + 하ì´ë¼ì´íЏ 범위 + + + 가사 타임 ë¼ì¸ ë™ê¸°í™” 임계 ê°’ + + + 가사 ì§„í–‰ ìƒí™©ì´ ë¶ˆì•ˆí•˜ë‹¤ë©´ì´ ìž„ê³„ ê°’ì„ ë†’ì´ì‹­ì‹œì˜¤. ì´ ê°’ì„ ë³€ê²½í•˜ë©´ 가사가 ë™ê¸°í™” ë  ìˆ˜ 있습니다 + + + QQ 피드백 ë° ì±„íŒ… 그룹 + + + Discord + + + 지금 가입하십시오 + \ No newline at end of file diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw index f6215a5..7038654 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw @@ -310,7 +310,7 @@ 当剿²¡æœ‰æ­£åœ¨æ’­æ”¾çš„éŸ³ä¹ - å¼€å‘者选项 + 高级选项 æ’­æ”¾æµ‹è¯•éŸ³ä¹ @@ -459,13 +459,10 @@ 超黑 - - å…¨éƒ¨æ­Œè¯ - - + 当å‰è¡Œ - + 当å‰å­—符 @@ -717,4 +714,25 @@ 三次缓入缓出 + + 当剿­Œè¯å¼€å§‹åˆ°å½“å‰å­—符 + + + 高亮显示范围 + + + æ­Œè¯æ—¶é—´è½´åŒæ­¥é˜ˆå€¼ + + + 当歌è¯è¿›åº¦æŠ–动时,请å°è¯•增加该阈值;更改此值会导致歌è¯åŒæ­¥æœ‰åå·® + + + QQ å馈交æµç¾¤ + + + Discord + + + ç«‹å³åŠ å…¥ + \ No newline at end of file diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw index 09ea241..e210a20 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw @@ -310,7 +310,7 @@ ç›®å‰æ²’有正在播放的音樂 - 開發者é¸é … + 高級é¸é … 播放測試音樂 @@ -459,13 +459,10 @@ 超黑 - - 全部歌詞 - - + ç›®å‰è¡Œ - + ç›®å‰å­—å…ƒ @@ -717,4 +714,25 @@ 三次緩入緩出 + + ç•¶å‰æ­Œè©žé–‹å§‹åˆ°ç•¶å‰å­—符 + + + é«˜äº®é¡¯ç¤ºç¯„åœ + + + æ­Œè©žæ™‚é–“è»¸åŒæ­¥é–¾å€¼ + + + ç•¶æ­Œè©žé€²åº¦æŠ–å‹•æ™‚ï¼Œè«‹å˜—è©¦å¢žåŠ è©²é–¾å€¼ï¼›æ›´æ”¹æ­¤å€¼æœƒå°Žè‡´æ­Œè©žåŒæ­¥åå·® + + + QQ 回饋交æµç¾¤ + + + Discord + + + ç«‹å³åŠ å…¥ + \ No newline at end of file diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseWindowViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseWindowViewModel.cs index fdc961a..6b86c24 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseWindowViewModel.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseWindowViewModel.cs @@ -11,8 +11,7 @@ using Microsoft.UI.Xaml; namespace BetterLyrics.WinUI3.ViewModels { - public partial class BaseWindowViewModel : BaseViewModel + public partial class BaseWindowViewModel(ISettingsService settingsService) : BaseViewModel(settingsService) { - public BaseWindowViewModel(ISettingsService settingsService) : base(settingsService) { } } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs index 77ad185..5401973 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs @@ -15,7 +15,7 @@ using System.Threading.Tasks; namespace BetterLyrics.WinUI3.ViewModels { - public partial class LyricsPageViewModel : BaseViewModel, IRecipient>, IRecipient> + public partial class LyricsPageViewModel : BaseViewModel, IRecipient> { private readonly IPlaybackService _playbackService; @@ -23,15 +23,12 @@ namespace BetterLyrics.WinUI3.ViewModels public LyricsPageViewModel(ISettingsService settingsService, IPlaybackService playbackService) : base(settingsService) { - LyricsFontSize = _settingsService.LyricsFontSize; + IsFirstRun = _settingsService.IsFirstRun; IsTranslationEnabled = _settingsService.IsTranslationEnabled; PreferredDisplayType = _settingsService.PreferredDisplayType; _playbackService = playbackService; _playbackService.SongInfoChanged += PlaybackService_SongInfoChanged; - - - IsFirstRun = _settingsService.IsFirstRun; } private void PlaybackService_SongInfoChanged(object? sender, Events.SongInfoChangedEventArgs e) @@ -51,12 +48,6 @@ namespace BetterLyrics.WinUI3.ViewModels [ObservableProperty] public partial bool IsWelcomeTeachingTipOpen { get; set; } - [ObservableProperty] - public partial Visibility BottomCommandGridVisibility { get; set; } = Visibility.Visible; - - [ObservableProperty] - public partial int LyricsFontSize { get; set; } - [ObservableProperty] public partial LyricsDisplayType PreferredDisplayType { get; set; } @@ -69,7 +60,7 @@ namespace BetterLyrics.WinUI3.ViewModels [ObservableProperty] [NotifyPropertyChangedRecipients] - public partial bool IsTranslationEnabled { get; set; } = false; + public partial bool IsTranslationEnabled { get; set; } partial void OnIsTranslationEnabledChanged(bool value) { @@ -98,19 +89,8 @@ namespace BetterLyrics.WinUI3.ViewModels } } - public void Receive(PropertyChangedMessage message) - { - if (message.Sender is SettingsPageViewModel) - { - if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFontSize)) - { - LyricsFontSize = message.NewValue; - } - } - } - [RelayCommand] - private void OpenSettingsWindow() + private static void OpenSettingsWindow() { WindowHelper.OpenOrShowWindow(); } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Ctor.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Ctor.cs index cfcb2b9..daaf80c 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Ctor.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Ctor.cs @@ -33,6 +33,7 @@ namespace BetterLyrics.WinUI3.ViewModels _lyricsBlurAmount = _settingsService.LyricsBlurAmount; _isLyricsGlowEffectEnabled = _settingsService.IsLyricsGlowEffectEnabled; _lyricsGlowEffectScope = _settingsService.LyricsGlowEffectScope; + _lyricsHighlightScope = _settingsService.LyricsHighlightScope; _customBgFontColor = _settingsService.LyricsCustomBgFontColor; _customFgFontColor = _settingsService.LyricsCustomFgFontColor; @@ -45,6 +46,8 @@ namespace BetterLyrics.WinUI3.ViewModels _targetLanguageIndex = _settingsService.SelectedTargetLanguageIndex; _titleTextFormat.HorizontalAlignment = _artistTextFormat.HorizontalAlignment = _settingsService.SongInfoAlignmentType.ToCanvasHorizontalAlignment(); + _timelineSyncThreshold = _settingsService.TimelineSyncThreshold; + _canvasYScrollTransition.SetDuration(_settingsService.LyricsScrollDuration / 1000f); _canvasYScrollTransition.SetEasingType(_settingsService.LyricsScrollEasingType); @@ -56,7 +59,7 @@ namespace BetterLyrics.WinUI3.ViewModels _playbackService.AlbumArtChangedChanged += PlaybackService_AlbumArtChangedChanged; _playbackService.PositionChanged += PlaybackService_PositionChanged; - UpdateFontColor(); + UpdateColorConfig(); } } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Draw.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Draw.cs index 3b42bc4..23b57d3 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Draw.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Draw.cs @@ -67,9 +67,9 @@ namespace BetterLyrics.WinUI3.ViewModels if (_isDebugOverlayEnabled) { - var currentPlayingLine = _multiLangLyrics - .SafeGet(_langIndex) - ?.SafeGet(_playingLineIndex); + var currentPlayingLine = _lyricsDataArr + .ElementAtOrDefault(_langIndex) + ?.LyricsLines.ElementAtOrDefault(_playingLineIndex); if (currentPlayingLine != null) { @@ -85,7 +85,7 @@ namespace BetterLyrics.WinUI3.ViewModels $"Cur playing {_playingLineIndex}, char start idx {charStartIndex}, length {charLength}, prog {charProgress}\n" + $"Visible lines [{_startVisibleLineIndex}, {_endVisibleLineIndex}]\n" + $"Cur time {_totalTime + _positionOffset}\n" + - $"Lang size {_multiLangLyrics.Count}\n" + + $"Lang size {_lyricsDataArr.Count}\n" + $"Song duration {TimeSpan.FromMilliseconds(SongInfo?.DurationMs ?? 0)}", new Vector2(10, 10), ThemeTypeSent == Microsoft.UI.Xaml.ElementTheme.Light ? Colors.Black : Colors.White @@ -118,13 +118,13 @@ namespace BetterLyrics.WinUI3.ViewModels float x = _canvasWidth / 2 - imageWidth * scaleFactor / 2; float y = _canvasHeight / 2 - imageHeight * scaleFactor / 2; - // Source: https://zhuanlan.zhihu.com/p/37178216 - float bright = _lyricsBgBrightnessTransition.Value / 1f * 2f; // æ˜Žåº¦å‚æ•°ï¼ŒèŒƒå›´åœ¨0.0f到2.0f之间 + // Original source: https://zhuanlan.zhihu.com/p/37178216 + float gain = _lyricsBgBrightnessTransition.Value; - float whiteX = Math.Min(2 - bright, 1); - float whiteY = 1f; - float blackX = Math.Max(1 - bright, 0); - float blackY = 0f; + float whiteX = 1 - 0.5f * gain; + float whiteY = 0.5f + 0.5f * gain; + float blackX = 0.5f - 0.5f * gain; + float blackY = 0 + 0.5f * gain; ds.DrawImage(new OpacityEffect { @@ -274,9 +274,9 @@ namespace BetterLyrics.WinUI3.ViewModels private void DrawBlurredLyrics(ICanvasAnimatedControl control, CanvasDrawingSession ds) { - var currentPlayingLine = _multiLangLyrics - .SafeGet(_langIndex) - ?.SafeGet(_playingLineIndex); + var currentPlayingLine = _lyricsDataArr + .ElementAtOrDefault(_langIndex) + ?.LyricsLines.ElementAtOrDefault(_playingLineIndex); if (currentPlayingLine == null) { @@ -285,7 +285,7 @@ namespace BetterLyrics.WinUI3.ViewModels for (int i = _startVisibleLineIndex; i <= _endVisibleLineIndex; i++) { - var line = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(i); + var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(i); if (line == null) { @@ -486,8 +486,9 @@ namespace BetterLyrics.WinUI3.ViewModels Source = fgLyrics, AlphaMask = _lyricsGlowEffectScope switch { - LineRenderingType.UntilCurrentChar => mask, - LineRenderingType.CurrentCharOnly => highlightMask, + LineRenderingType.CurrentChar => highlightMask, + LineRenderingType.LineStartToCurrentChar => mask, + LineRenderingType.CurrentLine => fgLyrics, _ => mask, }, }, @@ -498,7 +499,13 @@ namespace BetterLyrics.WinUI3.ViewModels Foreground = new AlphaMaskEffect { Source = fgLyrics, - AlphaMask = mask, + AlphaMask = _lyricsHighlightScope switch + { + LineRenderingType.CurrentChar => highlightMask, + LineRenderingType.LineStartToCurrentChar => mask, + LineRenderingType.CurrentLine => fgLyrics, + _ => mask, + }, }, }, Opacity = line.HighlightOpacityTransition.Value * _lyricsOpacityTransition.Value, diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Messages.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Messages.cs index 3c9d781..d3e6696 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Messages.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Messages.cs @@ -57,8 +57,6 @@ namespace BetterLyrics.WinUI3.ViewModels } } - // Receive methods for handling messages from other view models - public void Receive(PropertyChangedMessage message) { if (message.Sender is SettingsPageViewModel) @@ -86,12 +84,12 @@ namespace BetterLyrics.WinUI3.ViewModels if (message.PropertyName == nameof(LyricsWindowViewModel.IsDockMode)) { _isDockMode = message.NewValue; - UpdateFontColor(); + UpdateColorConfig(); } else if (message.PropertyName == nameof(LyricsWindowViewModel.IsDesktopMode)) { _isDesktopMode = message.NewValue; - UpdateFontColor(); + UpdateColorConfig(); } else if (message.PropertyName == nameof(LyricsWindowViewModel.IsLyricsWindowLocked)) { @@ -122,7 +120,7 @@ namespace BetterLyrics.WinUI3.ViewModels { _immersiveBgTransition.StartTransition(message.NewValue); _environmentalColor = message.NewValue; - UpdateFontColor(); + UpdateColorConfig(); } } else if (message.Sender is SettingsPageViewModel) @@ -130,17 +128,17 @@ namespace BetterLyrics.WinUI3.ViewModels if (message.PropertyName == nameof(SettingsPageViewModel.LyricsCustomBgFontColor)) { _customBgFontColor = message.NewValue; - UpdateFontColor(); + UpdateColorConfig(); } else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsCustomFgFontColor)) { _customFgFontColor = message.NewValue; - UpdateFontColor(); + UpdateColorConfig(); } else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsCustomStrokeFontColor)) { _customStrokeFontColor = message.NewValue; - UpdateFontColor(); + UpdateColorConfig(); } } } @@ -202,6 +200,10 @@ namespace BetterLyrics.WinUI3.ViewModels { _canvasYScrollTransition.SetDuration(message.NewValue / 1000f); } + else if (message.PropertyName == nameof(SettingsPageViewModel.TimelineSyncThreshold)) + { + _timelineSyncThreshold = message.NewValue; + } } else if (message.Sender is LyricsPageViewModel) { @@ -220,6 +222,10 @@ namespace BetterLyrics.WinUI3.ViewModels { _lyricsGlowEffectScope = message.NewValue; } + else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsHighlightScope)) + { + _lyricsHighlightScope = message.NewValue; + } } } @@ -251,17 +257,17 @@ namespace BetterLyrics.WinUI3.ViewModels if (message.PropertyName == nameof(SettingsPageViewModel.LyricsBgFontColorType)) { _lyricsBgFontColorType = message.NewValue; - UpdateFontColor(); + UpdateColorConfig(); } else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFgFontColorType)) { _lyricsFgFontColorType = message.NewValue; - UpdateFontColor(); + UpdateColorConfig(); } else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsStrokeFontColorType)) { _lyricsStrokeFontColorType = message.NewValue; - UpdateFontColor(); + UpdateColorConfig(); } } } @@ -285,7 +291,7 @@ namespace BetterLyrics.WinUI3.ViewModels if (message.PropertyName == nameof(SettingsPageViewModel.LyricsBackgroundTheme)) { _lyricsBgTheme = message.NewValue; - UpdateFontColor(); + UpdateColorConfig(); } } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Update.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Update.cs index 2140ff9..1e9d106 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Update.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Update.cs @@ -7,6 +7,7 @@ using Microsoft.Graphics.Canvas.UI.Xaml; using Microsoft.UI; using Microsoft.UI.Xaml; using System; +using System.Linq; using System.Numerics; using Windows.UI; @@ -135,9 +136,9 @@ namespace BetterLyrics.WinUI3.ViewModels float y = 0; // Init Positions - for (int i = 0; i < _multiLangLyrics.SafeGet(_langIndex)?.Count; i++) + for (int i = 0; i < _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.Count; i++) { - var line = _multiLangLyrics[_langIndex].SafeGet(i); + var line = _lyricsDataArr[_langIndex].LyricsLines.ElementAtOrDefault(i); if (line == null) { @@ -178,7 +179,7 @@ namespace BetterLyrics.WinUI3.ViewModels if ((!_isPlayingLineChanged && forceScroll) || _isPlayingLineChanged) { - LyricsLine? currentPlayingLine = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(_playingLineIndex); + LyricsLine? currentPlayingLine = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(_playingLineIndex); if (currentPlayingLine == null) return; @@ -186,7 +187,7 @@ namespace BetterLyrics.WinUI3.ViewModels if (playingTextLayout == null) return; - float? targetYScrollOffset = (float?)(-currentPlayingLine!.Position.Y + _multiLangLyrics.SafeGet(_langIndex)?[0].Position.Y - playingTextLayout.LayoutBounds.Height / 2); + float? targetYScrollOffset = (float?)(-currentPlayingLine!.Position.Y + _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines[0].Position.Y - playingTextLayout.LayoutBounds.Height / 2); if (!targetYScrollOffset.HasValue) return; @@ -201,7 +202,7 @@ namespace BetterLyrics.WinUI3.ViewModels // Update visible line indices for (int i = startLineIndex; i <= endLineIndex; i++) { - var line = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(i); + var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(i); if (line == null || line.CanvasTextLayout == null) { @@ -249,7 +250,7 @@ namespace BetterLyrics.WinUI3.ViewModels _endVisibleLineIndex = endVisibleLineIndex; } - private void UpdateFontColor() + private void UpdateColorConfig() { if (_isDesktopMode || _isDockMode) { @@ -360,15 +361,15 @@ namespace BetterLyrics.WinUI3.ViewModels private void UpdateLinesProps() { - var currentPlayingLine = _multiLangLyrics - .SafeGet(_langIndex) - ?.SafeGet(_playingLineIndex); + var currentPlayingLine = _lyricsDataArr + .ElementAtOrDefault(_langIndex) + ?.LyricsLines.ElementAtOrDefault(_playingLineIndex); if (currentPlayingLine == null) return; for (int i = _startVisibleLineIndex; i <= _endVisibleLineIndex; i++) { - var line = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(i); + var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(i); if (line == null) continue; diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs index b5b464f..10f647b 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs @@ -72,6 +72,7 @@ namespace BetterLyrics.WinUI3.ViewModels private ElementTheme _lyricsBgTheme; private LineRenderingType _lyricsGlowEffectScope; + private LineRenderingType _lyricsHighlightScope; private int _lyricsFontStrokeWidth; private int _lyricsFontSize; @@ -134,11 +135,13 @@ namespace BetterLyrics.WinUI3.ViewModels private int _langIndex = 0; - private List> _multiLangLyrics = []; + private List _lyricsDataArr = []; private List _translationList = []; private bool _isTranslationEnabled = false; private int _targetLanguageIndex = 6; + private int _timelineSyncThreshold; + private CanvasTextFormat _lyricsTextFormat = new() { HorizontalAlignment = CanvasHorizontalAlignment.Left, @@ -184,9 +187,9 @@ namespace BetterLyrics.WinUI3.ViewModels private int GetCurrentPlayingLineIndex() { - for (int i = 0; i < _multiLangLyrics.SafeGet(_langIndex)?.Count; i++) + for (int i = 0; i < _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.Count; i++) { - var line = _multiLangLyrics.SafeGet(_langIndex)?[i]; + var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines[i]; if (line == null) { continue; @@ -262,14 +265,14 @@ namespace BetterLyrics.WinUI3.ViewModels { if ( SongInfo == null - || _multiLangLyrics.SafeGet(_langIndex) == null - || _multiLangLyrics[_langIndex].Count == 0 + || _lyricsDataArr.ElementAtOrDefault(_langIndex) == null + || _lyricsDataArr[_langIndex].LyricsLines.Count == 0 ) { return new Tuple(-1, -1); } - return new Tuple(0, _multiLangLyrics[_langIndex].Count - 1); + return new Tuple(0, _lyricsDataArr[_langIndex].LyricsLines.Count - 1); } private void LibWatcherService_MusicLibraryFilesChanged(object? sender, LibChangedEventArgs e) @@ -288,7 +291,10 @@ namespace BetterLyrics.WinUI3.ViewModels private void PlaybackService_PositionChanged(object? sender, PositionChangedEventArgs e) { - _totalTime = e.Position; + if (Math.Abs(_totalTime.TotalMilliseconds - e.Position.TotalMilliseconds) >= _timelineSyncThreshold) + { + _totalTime = e.Position; + } } private void PlaybackService_SongInfoChanged(object? sender, SongInfoChangedEventArgs e) @@ -330,7 +336,7 @@ namespace BetterLyrics.WinUI3.ViewModels _albumArtBgTransition.Reset(0f); _albumArtBgTransition.StartTransition(1f); - UpdateFontColor(); + UpdateColorConfig(); } } @@ -341,93 +347,55 @@ namespace BetterLyrics.WinUI3.ViewModels { _ = _refreshLyricsRunner.RunAsync(async token => { - await ShowTranslationsAsync(token); + await SetDisplayedAlongWithTranslationsAsync(token); IsTranslating = false; + _isLayoutChanged = true; }); } else { - ShowOriginalsOnly(); + _lyricsDataArr[0].SetDisplayedTextInOriginalText(); IsTranslating = false; + _isLayoutChanged = true; } } - private async Task ShowTranslationsAsync(CancellationToken token) + private async Task SetDisplayedAlongWithTranslationsAsync(CancellationToken token) { _logger.LogInformation("Showing translation for lyrics..."); - string targetLangCode = LanguageHelper.SupportedTargetLanguages[_settingsService.SelectedTargetLanguageIndex].Code; - var originalText = string.Join("\n", _multiLangLyrics.FirstOrDefault()?.Select(x => x.OriginalText) ?? []); + string targetLangCode = LanguageHelper.GetUserTargetLanguageCode(); + string originalText = _lyricsDataArr[0].WrappedOriginalText; string? originalLangCode = LanguageHelper.DetectLanguageCode(originalText); if (originalLangCode == targetLangCode) { _logger.LogInformation("Original lyrics already in target language: {TargetLangCode}", targetLangCode); - ShowOriginalsOnly(); - return; - } - - // Try get translation from itself first - if (_multiLangLyrics.Count > 1) - { - foreach (var langLyrics in _multiLangLyrics.Skip(1)) - { - var translationList = langLyrics.Select(x => x.OriginalText).ToList(); - var translation = string.Join("\n", translationList); - if (LanguageHelper.DetectLanguageCode(translation) == targetLangCode) - { - _translationList = translationList; - break; - } - } + _lyricsDataArr[0].SetDisplayedTextInOriginalText(); } else { - if (string.IsNullOrEmpty(_settingsService.LibreTranslateServer)) + // Try get translation from itself first + int found = _translateService.SearchTranslatedLyricsItself(_lyricsDataArr); + if (found >= 0) { - _dispatcherQueue.TryEnqueue(() => - { - App.Current.LyricsWindowNotificationPanel?.Notify( - App.ResourceLoader!.GetString("TranslateServerNotSet"), - Microsoft.UI.Xaml.Controls.InfoBarSeverity.Warning - ); - }); - ShowOriginalsOnly(); - return; + _lyricsDataArr[0].SetDisplayedTextAlongWith(_lyricsDataArr[found]); } - - var translated = await _translateService.TranslateAsync(originalText, targetLangCode, token); - token.ThrowIfCancellationRequested(); - - _translationList = translated.Split('\n').ToList(); - } - - int i = 0; - foreach (var line in _multiLangLyrics.FirstOrDefault() ?? []) - { - line.DisplayedText = i < _translationList.Count ? $"{line.OriginalText}\n{_translationList[i]}" : line.OriginalText; - i++; - } - _isLayoutChanged = true; - } - - private void ShowOriginalsOnly() - { - _logger.LogInformation("Showing original lyrics only, translation disabled."); - foreach (var langLyrics in _multiLangLyrics) - { - foreach (var line in langLyrics) + else { - line.DisplayedText = line.OriginalText; + var translated = await _translateService.TranslateTextAsync(originalText, targetLangCode, token); + token.ThrowIfCancellationRequested(); + + _lyricsDataArr[0].SetDisplayedTextAlongWith(translated); } } - _isLayoutChanged = true; } private async Task RefreshLyricsAsync(CancellationToken token) { _logger.LogInformation("Refreshing lyrics..."); - SetLyricsLoadingPlaceholder(); + _lyricsDataArr = [LyricsData.GetLoadingPlaceholder()]; + _isLayoutChanged = true; string? lyricsRaw = null; @@ -448,33 +416,14 @@ namespace BetterLyrics.WinUI3.ViewModels _logger.LogWarning("SongInfo is null, cannot search lyrics."); } - _multiLangLyrics = new LyricsParser().Parse( - lyricsRaw, - (int?)SongInfo?.DurationMs ?? (int)TimeSpan.FromMinutes(99).TotalMilliseconds - ); - _logger.LogInformation("Parsed lyrics: {MultiLangLyricsCount} languages", _multiLangLyrics.Count); + _lyricsDataArr = new LyricsParser().Parse(lyricsRaw, (int?)SongInfo?.DurationMs); + _logger.LogInformation("Parsed lyrics: {MultiLangLyricsCount} languages", _lyricsDataArr.Count); // This ensures that original lyrics are always shown while waiting for translations - ShowOriginalsOnly(); - UpdateTranslations(); - } - - private void SetLyricsLoadingPlaceholder() - { - _multiLangLyrics = []; - _multiLangLyrics.Add( - [ - new LyricsLine - { - StartMs = 0, - EndMs = (int)TimeSpan.FromMinutes(99).TotalMilliseconds, - OriginalText = "â— â— â—", - DisplayedText = "â— â— â—", - CharTimings = [], - }, - ] - ); + _lyricsDataArr[0].SetDisplayedTextInOriginalText(); _isLayoutChanged = true; + + UpdateTranslations(); } } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs index a5ae94c..92add0a 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs @@ -1,7 +1,5 @@ // 2025/6/23 by Zhe Fang -using System.Diagnostics; -using System.Threading.Tasks; using BetterLyrics.WinUI3.Enums; using BetterLyrics.WinUI3.Helper; using BetterLyrics.WinUI3.Models; @@ -15,8 +13,11 @@ using CommunityToolkit.Mvvm.Messaging.Messages; using Microsoft.UI; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; +using System.Diagnostics; +using System.Threading.Tasks; using Windows.UI; using WinRT.Interop; +using WinUIEx; namespace BetterLyrics.WinUI3 { @@ -26,7 +27,8 @@ namespace BetterLyrics.WinUI3 IRecipient>, IRecipient> { - private ForegroundWindowWatcher? _watcherHelper = null; + private ForegroundWindowWatcher? _windowWatcher = null; + private bool _ignoreFullscreenWindow = false; public LyricsWindowViewModel(ISettingsService settingsService) : base(settingsService) { @@ -49,24 +51,16 @@ namespace BetterLyrics.WinUI3 [NotifyPropertyChangedRecipients] public partial bool IsLyricsWindowLocked { get; set; } = false; - [ObservableProperty] - public partial bool ShowInfoBar { get; set; } = false; - [ObservableProperty] public partial ElementTheme ThemeType { get; set; } = ElementTheme.Default; [ObservableProperty] public partial double TitleBarFontSize { get; set; } = 11; - [ObservableProperty] - public partial double TitleBarHeight { get; set; } = 36; - [ObservableProperty] [NotifyPropertyChangedRecipients] public partial bool IsMouseWithinWindow { get; set; } = false; - private bool _ignoreFullscreenWindow = false; - public void Receive(PropertyChangedMessage message) { if (message.Sender is SystemTrayViewModel) @@ -122,7 +116,7 @@ namespace BetterLyrics.WinUI3 if (window == null) return; var hwnd = WindowNative.GetWindowHandle(window); - _watcherHelper = new ForegroundWindowWatcher( + _windowWatcher = new ForegroundWindowWatcher( hwnd, onWindowChanged => { @@ -133,10 +127,16 @@ namespace BetterLyrics.WinUI3 UpdateAccentColor(hwnd, mode); } ); - _watcherHelper.Start(); + _windowWatcher.Start(); UpdateAccentColor(hwnd, mode); } + private void StopWatchWindowColorChange() + { + _windowWatcher?.Stop(); + _windowWatcher = null; + } + public void UpdateAccentColor(nint hwnd, WindowPixelSampleMode mode) { ActivatedWindowAccentColor = Helper.ColorHelper.GetAccentColor(hwnd, mode).ToColor(); @@ -152,12 +152,6 @@ namespace BetterLyrics.WinUI3 IsLyricsWindowLocked = true; } - private void StopWatchWindowColorChange() - { - _watcherHelper?.Stop(); - _watcherHelper = null; - } - [RelayCommand] private void ToggleDesktopMode() { diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs index 9fc82b6..8510cbe 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs @@ -69,6 +69,7 @@ namespace BetterLyrics.WinUI3.ViewModels LyricsFontSize = _settingsService.LyricsFontSize; IsLyricsGlowEffectEnabled = _settingsService.IsLyricsGlowEffectEnabled; LyricsGlowEffectScope = _settingsService.LyricsGlowEffectScope; + LyricsHighlightScope = _settingsService.LyricsHighlightScope; IsFanLyricsEnabled = _settingsService.IsFanLyricsEnabled; LyricsBgFontColorType = _settingsService.LyricsBgFontColorType; @@ -86,6 +87,7 @@ namespace BetterLyrics.WinUI3.ViewModels LyricsScrollEasingType = _settingsService.LyricsScrollEasingType; LyricsScrollDuration = _settingsService.LyricsScrollDuration; + TimelineSyncThreshold = _settingsService.TimelineSyncThreshold; _playbackService.MediaSourceProvidersInfoChanged += PlaybackService_SessionIdsChanged; @@ -207,6 +209,10 @@ namespace BetterLyrics.WinUI3.ViewModels [NotifyPropertyChangedRecipients] public partial LineRenderingType LyricsGlowEffectScope { get; set; } + [ObservableProperty] + [NotifyPropertyChangedRecipients] + public partial LineRenderingType LyricsHighlightScope { get; set; } + [ObservableProperty] [NotifyPropertyChangedRecipients] public partial float LyricsLineSpacingFactor { get; set; } @@ -218,7 +224,7 @@ namespace BetterLyrics.WinUI3.ViewModels [ObservableProperty] public partial object NavViewSelectedItemTag { get; set; } - public string Version { get; set; } = Helper.MetadataHelper.AppVersion; + public string Version { get; set; } = MetadataHelper.AppVersion; public string BuildDate { get; set; } = string.Empty; @@ -248,25 +254,9 @@ namespace BetterLyrics.WinUI3.ViewModels [NotifyPropertyChangedRecipients] public partial int LyricsScrollDuration { get; set; } - partial void OnLyricsScrollEasingTypeChanged(EasingType value) - { - _settingsService.LyricsScrollEasingType = value; - } - - partial void OnLyricsScrollDurationChanged(int value) - { - _settingsService.LyricsScrollDuration = value; - } - - partial void OnLyricsBackgroundThemeChanged(ElementTheme value) - { - _settingsService.LyricsBackgroundTheme = value; - } - - partial void OnLyricsFontStrokeWidthChanged(int value) - { - _settingsService.LyricsFontStrokeWidth = value; - } + [ObservableProperty] + [NotifyPropertyChangedRecipients] + public partial int TimelineSyncThreshold { get; set; } public void OnLyricsSearchProvidersReordered() { @@ -288,11 +278,6 @@ namespace BetterLyrics.WinUI3.ViewModels ); } - public void OpenMusicFolder(LocalLyricsFolder folder) - { - OpenFolderInFileExplorer(folder.Path); - } - public void RemoveFolderAsync(LocalLyricsFolder folder) { LocalLyricsFolders.Remove(folder); @@ -371,31 +356,13 @@ namespace BetterLyrics.WinUI3.ViewModels } [RelayCommand] - private void OpenCacheFolder() + private static async Task OpenCacheFolderAsync() { - OpenFolderInFileExplorer(PathHelper.CacheFolder); - } - - private void OpenFolderInFileExplorer(string path) - { - Process.Start( - new ProcessStartInfo - { - FileName = "explorer.exe", - Arguments = path, - UseShellExecute = true, - } - ); + await Launcher.LaunchFolderPathAsync(PathHelper.CacheFolder); } [RelayCommand] - private void PlayTestingMusicTask() - { - WindowHelper.OpenOrShowWindow(); - } - - [RelayCommand] - private void RestartApp() + private static void RestartApp() { WindowHelper.RestartApp(); } @@ -429,7 +396,7 @@ namespace BetterLyrics.WinUI3.ViewModels try { string targetLangCode = LanguageHelper.SupportedTargetLanguages[SelectedTargetLanguageIndex].Code; - string result = await _libreTranslateService.TranslateAsync("Hello, world!", targetLangCode, null); + string result = await _libreTranslateService.TranslateTextAsync("Hello, world!", targetLangCode, null); _dispatcherQueue.TryEnqueue(() => { App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageLibreTranslateTestSuccessInfo"), Microsoft.UI.Xaml.Controls.InfoBarSeverity.Success); @@ -479,51 +446,58 @@ namespace BetterLyrics.WinUI3.ViewModels return result; } + partial void OnLyricsScrollEasingTypeChanged(EasingType value) + { + _settingsService.LyricsScrollEasingType = value; + } + partial void OnLyricsScrollDurationChanged(int value) + { + _settingsService.LyricsScrollDuration = value; + } + partial void OnLyricsBackgroundThemeChanged(ElementTheme value) + { + _settingsService.LyricsBackgroundTheme = value; + } + partial void OnLyricsFontStrokeWidthChanged(int value) + { + _settingsService.LyricsFontStrokeWidth = value; + } partial void OnIgnoreFullscreenWindowChanged(bool value) { _settingsService.IgnoreFullscreenWindow = value; } - partial void OnSelectedTargetLanguageIndexChanged(int value) { _settingsService.SelectedTargetLanguageIndex = value; } - partial void OnLibreTranslateServerChanged(string value) { _settingsService.LibreTranslateServer = value; } - partial void OnAutoStartWindowTypeChanged(AutoStartWindowType value) { _settingsService.AutoStartWindowType = value; } - partial void OnAutoLockOnDesktopModeChanged(bool value) { _settingsService.AutoLockOnDesktopMode = value; } - partial void OnCoverImageRadiusChanged(int value) { _settingsService.CoverImageRadius = value; } - partial void OnCoverOverlayBlurAmountChanged(int value) { _settingsService.CoverOverlayBlurAmount = value; } - partial void OnCoverOverlayOpacityChanged(int value) { _settingsService.CoverOverlayOpacity = value; } - partial void OnIsDynamicCoverOverlayEnabledChanged(bool value) { _settingsService.IsDynamicCoverOverlayEnabled = value; } - partial void OnLanguageChanged(Enums.Language value) { switch (value) @@ -551,85 +525,78 @@ namespace BetterLyrics.WinUI3.ViewModels } _settingsService.Language = Language; } - partial void OnIsFanLyricsEnabledChanged(bool value) { _settingsService.IsFanLyricsEnabled = value; } - partial void OnIsLyricsGlowEffectEnabledChanged(bool value) { _settingsService.IsLyricsGlowEffectEnabled = value; } - partial void OnLyricsAlignmentTypeChanged(TextAlignmentType value) { _settingsService.LyricsAlignmentType = value; } - partial void OnSongInfoAlignmentTypeChanged(TextAlignmentType value) { _settingsService.SongInfoAlignmentType = value; } - partial void OnLyricsBlurAmountChanged(int value) { _settingsService.LyricsBlurAmount = value; } - partial void OnLyricsCustomBgFontColorChanged(Color value) { _settingsService.LyricsCustomBgFontColor = value; } - partial void OnLyricsCustomFgFontColorChanged(Color value) { _settingsService.LyricsCustomFgFontColor = value; } - partial void OnLyricsCustomStrokeFontColorChanged(Color value) { _settingsService.LyricsCustomStrokeFontColor = value; } - partial void OnLyricsBgFontColorTypeChanged(LyricsFontColorType value) { _settingsService.LyricsBgFontColorType = value; } - partial void OnLyricsFgFontColorTypeChanged(LyricsFontColorType value) { _settingsService.LyricsFgFontColorType = value; } - partial void OnLyricsStrokeFontColorTypeChanged(LyricsFontColorType value) { _settingsService.LyricsStrokeFontColorType = value; } - partial void OnLyricsFontSizeChanged(int value) { _settingsService.LyricsFontSize = value; } - partial void OnLyricsFontWeightChanged(LyricsFontWeight value) { _settingsService.LyricsFontWeight = value; } - partial void OnLyricsGlowEffectScopeChanged(LineRenderingType value) { _settingsService.LyricsGlowEffectScope = value; } - + partial void OnLyricsHighlightScopeChanged(LineRenderingType value) + { + _settingsService.LyricsHighlightScope = value; + } partial void OnLyricsLineSpacingFactorChanged(float value) { _settingsService.LyricsLineSpacingFactor = value; } - partial void OnLyricsVerticalEdgeOpacityChanged(int value) { _settingsService.LyricsVerticalEdgeOpacity = value; } + partial void OnTimelineSyncThresholdChanged(int value) + { + _settingsService.TimelineSyncThreshold = value; + } + } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsWindowViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsWindowViewModel.cs index d32b8f6..d79b4d9 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsWindowViewModel.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsWindowViewModel.cs @@ -2,8 +2,7 @@ namespace BetterLyrics.WinUI3.ViewModels { - public class SettingsWindowViewModel : BaseWindowViewModel + public partial class SettingsWindowViewModel(ISettingsService settingsService) : BaseWindowViewModel(settingsService) { - public SettingsWindowViewModel(ISettingsService settingsService) : base(settingsService) { } } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SystemTrayViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SystemTrayViewModel.cs index 225f98f..ecf1758 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SystemTrayViewModel.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SystemTrayViewModel.cs @@ -8,10 +8,8 @@ using CommunityToolkit.Mvvm.Messaging.Messages; namespace BetterLyrics.WinUI3.ViewModels { - public partial class SystemTrayViewModel : BaseViewModel, IRecipient> + public partial class SystemTrayViewModel(ISettingsService settingsService) : BaseViewModel(settingsService), IRecipient> { - public SystemTrayViewModel(ISettingsService settingsService) : base(settingsService) { } - [ObservableProperty] [NotifyPropertyChangedRecipients] public partial bool IsLyricsWindowLocked { get; set; } = false; @@ -34,15 +32,14 @@ namespace BetterLyrics.WinUI3.ViewModels } [RelayCommand] - private void ExitApp() + private static void ExitApp() { WindowHelper.ExitAllWindows(); } [RelayCommand] - private void OpenSettings() + private static void OpenSettings() { - // æ‰“å¼€è®¾ç½®çª—å£ WindowHelper.OpenOrShowWindow(); } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/SettingsPage.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/SettingsPage.xaml index c59e65a..5da2387 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/SettingsPage.xaml +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/SettingsPage.xaml @@ -188,8 +188,8 @@ VerticalAlignment="Center" Text="{x:Bind ViewModel.CoverOverlayBlurAmount, Mode=OneWay}" /> + + + + + + + + - - + + + @@ -794,6 +803,7 @@ + @@ -815,24 +825,52 @@ Glyph=}" IsClickEnabled="True" /> + +