Compare commits

..

19 Commits

Author SHA1 Message Date
Zhe Fang
22b813e687 chores: bump to v1.1.186.0 2025-12-13 17:02:55 -05:00
Zhe Fang
fda94d5020 fix: settings save issue 2025-12-13 16:54:08 -05:00
Zhe Fang
205cbe8fb6 fix: settings storage issue 2025-12-13 16:19:05 -05:00
Zhe Fang
816f7064db fix: fan style lyrics animation 2025-12-13 15:45:41 -05:00
Zhe Fang
132c5267b0 chores: bump to v1.1.184.0 2025-12-13 12:20:20 -05:00
Zhe Fang
4e866818df fix: font family issue 2025-12-13 12:11:50 -05:00
Zhe Fang
9b7b56a0ee Revise acknowledgments in README.CN.md
Updated the acknowledgments section to reflect ongoing support and gratitude towards contributors and users.
2025-12-13 09:46:47 -05:00
Zhe Fang
66f2da0e4c Revise acknowledgments and donation list in README
Updated the acknowledgments section to reflect user support and removed the manual donation list.
2025-12-13 09:46:04 -05:00
Zhe Fang
1735c6a7e6 Add sponsors list and gratitude section to SPONSORS.md 2025-12-13 09:44:10 -05:00
Zhe Fang
8c06c98068 Update README.CN.md to acknowledge supporters
Added a section to thank supporters and users.
2025-12-13 09:36:00 -05:00
Zhe Fang
e2ac4c166c Add acknowledgments for supporters in README
Added a section to acknowledge and thank supporters.
2025-12-13 09:34:22 -05:00
Zhe Fang
728397cafa chores: code cleanup 2025-12-13 08:39:48 -05:00
Zhe Fang
059787a28f chores: bump to v1.1.183.0 2025-12-13 08:16:23 -05:00
Zhe Fang
4c4231b48c fix: white line in fullscreen mode 2025-12-13 07:58:28 -05:00
Zhe Fang
2412927b29 Add Zread badge to README.CN.md 2025-12-12 16:53:45 -05:00
Zhe Fang
f3bdbba83e Add Zread badge to README 2025-12-12 16:53:30 -05:00
Zhe Fang
4c811b12ca Create initial wiki structure for BetterLyrics
Added comprehensive documentation for BetterLyrics, including sections on installation, configuration, architecture, user interface, media integration, and development.
2025-12-12 16:20:42 -05:00
Zhe Fang
933103c57f Update badge links in README.CN.md 2025-12-12 15:55:15 -05:00
Zhe Fang
718e7bdad3 Fix badge formatting in README.md 2025-12-12 15:52:48 -05:00
13 changed files with 448 additions and 32 deletions

291
.devin/wiki.json Normal file
View File

@@ -0,0 +1,291 @@
{
"repo_notes": [
{
"content": "Always use the latest files in the repo to generate the wiki"
}
],
"pages": [
{
"title": "Overview",
"purpose": "Introduce BetterLyrics, its purpose as a WinUI3 lyrics display application, key features, and supported music players",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Getting Started",
"purpose": "Guide users through installation, initial setup, and basic usage of BetterLyrics",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Installation and Deployment",
"purpose": "Explain how to install BetterLyrics from Microsoft Store or build from source, system requirements, and supported Windows versions",
"parent": "Getting Started",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Initial Configuration",
"purpose": "Walk through first-time setup including media player configuration, folder selection, and basic settings",
"parent": "Getting Started",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Architecture",
"purpose": "Provide technical overview of BetterLyrics' internal architecture, design patterns, and component organization",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Application Entry Point and Dependency Injection",
"purpose": "Document the App.xaml.cs entry point, service registration, and dependency injection container configuration",
"parent": "Architecture",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Service Layer Architecture",
"purpose": "Explain the service-oriented architecture, service interfaces, and their implementations including MediaSessionsService, LyricsSearchService, and SettingsService",
"parent": "Architecture",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Data Models",
"purpose": "Document core data models including LyricsLine, LyricsData, SongInfo, and configuration models",
"parent": "Architecture",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Multi-Window System",
"purpose": "Explain how BetterLyrics manages multiple simultaneous lyrics windows, window lifecycle, and state management",
"parent": "Architecture",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "User Interface",
"purpose": "Document the UI components, windows, and user interaction patterns in BetterLyrics",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Now Playing Window",
"purpose": "Detail the main lyrics display window, its components, and integration with the rendering system",
"parent": "User Interface",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Display Modes and Window Configurations",
"purpose": "Explain different display modes (Standard, Desktop, Docked, Fullscreen, Narrow, Taskbar) and how to configure them",
"parent": "User Interface",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Settings and Customization",
"purpose": "Document the settings interface, configuration options, and how to customize lyrics appearance and behavior",
"parent": "User Interface",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Music Gallery",
"purpose": "Explain the local music library management feature, including playback, playlist management, and integration with media controls",
"parent": "User Interface",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "System Tray and Global Controls",
"purpose": "Document the system tray integration, global hotkeys, and application-wide controls",
"parent": "User Interface",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Lyrics System",
"purpose": "Comprehensive documentation of the lyrics acquisition, processing, and display pipeline",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Lyrics Search and Providers",
"purpose": "Document the lyrics search system, supported providers (QQ Music, Netease, Kugou, LrcLib, Apple Music, local files), and search strategies",
"parent": "Lyrics System",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Parsing and Translation",
"purpose": "Explain how lyrics are parsed from different formats (LRC, QRC, TTML), translation system using LibreTranslate, and metadata matching",
"parent": "Lyrics System",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Rendering Pipeline",
"purpose": "Document the Win2D-based rendering system, LyricsCanvas, PlayingLineRenderer, UnplayingLineRenderer, and LyricsLayoutManager",
"parent": "Lyrics System",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Visual Effects and Animation",
"purpose": "Explain character-level effects (glow, float, scale), background effects (fluid, snow, fog, spectrum), and the animation transition system",
"parent": "Lyrics System",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Media Integration",
"purpose": "Document how BetterLyrics integrates with music players and manages media sessions",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Windows Media Transport Controls Integration",
"purpose": "Explain how BetterLyrics uses Windows SMTC to work universally with media players",
"parent": "Media Integration",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Supported Players and Special Configurations",
"purpose": "List supported media players, document special configurations (Apple Music token, LX Music SSE), and player-specific handling",
"parent": "Media Integration",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Album Art and Theme Colors",
"purpose": "Document album art retrieval from multiple sources, color palette generation (MedianCut, OctTree), and adaptive theming",
"parent": "Media Integration",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Internationalization",
"purpose": "Explain the localization system, supported languages, and how resources are managed",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Development",
"purpose": "Technical documentation for developers contributing to or extending BetterLyrics",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Build Configuration and Deployment",
"purpose": "Document the build process, publish profiles for different architectures, CI/CD pipeline, and packaging for Microsoft Store",
"parent": "Development",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "Helper Utilities and Extensions",
"purpose": "Document utility classes including TaskbarHook, WindowHook, ColorHelper, ImageHelper, and various extension methods",
"parent": "Development",
"page_notes": [
{
"content": ""
}
]
},
{
"title": "External Dependencies and Libraries",
"purpose": "List and explain third-party dependencies including Win2D, NAudio, ATL.NET, FlaUI, and their usage in the application",
"parent": "Development",
"page_notes": [
{
"content": ""
}
]
}
]
}

View File

@@ -12,7 +12,7 @@
<Identity
Name="37412.BetterLyrics"
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
Version="1.1.182.0" />
Version="1.1.186.0" />
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

View File

@@ -48,7 +48,7 @@ namespace BetterLyrics.WinUI3.Controls
// FontFamilies = fontFamilies;
// });
//});
FontFamilies = FontHelper.SystemFontFamilies.OrderBy(x => x).ToList();
FontFamilies = FontHelper.GetSystemFontFamilies();
}
private void AutoSuggestBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)

View File

@@ -1,6 +1,8 @@
using Microsoft.Graphics.Canvas.Text;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Media;
@@ -8,8 +10,6 @@ namespace BetterLyrics.WinUI3.Helper
{
public static class FontHelper
{
public static string[] SystemFontFamilies => CanvasTextFormat.GetSystemFontFamilies().Order().ToArray();
public static string GetLocalizedFontFamilyName(string sourceName, string langCode)
{
if (langCode == "")
@@ -33,5 +33,20 @@ namespace BetterLyrics.WinUI3.Helper
return sourceName;
}
public static List<string> GetSystemFontFamilies()
{
List<string> fontFamilies = new();
foreach (var font in Fonts.SystemFontFamilies)
{
if (font.FamilyNames.TryGetValue(XmlLanguage.GetLanguage("en-us"), out string englishFamilyName))
{
fontFamilies.Add(englishFamilyName);
}
}
return fontFamilies.Order().ToList();
}
}
}

View File

@@ -282,23 +282,27 @@ namespace BetterLyrics.WinUI3.Hooks
}
}
public static void SetIsFullscreen(this Window window, bool enable)
public static bool SetIsFullscreen(this Window window, bool enable, bool defaultExtendsContentIntoTitleBar = true)
{
if (window.AppWindow == null) return;
if (window.AppWindow == null) return false;
if (enable)
{
window.ExtendsContentIntoTitleBar = false;
window.AppWindow.SetPresenter(AppWindowPresenterKind.FullScreen);
}
else
{
window.ExtendsContentIntoTitleBar = defaultExtendsContentIntoTitleBar;
window.AppWindow.SetPresenter(AppWindowPresenterKind.Overlapped);
}
return true;
}
public static void SetIsMaximized(this Window window, bool enable)
public static bool SetIsMaximized(this Window window, bool enable)
{
if (window.AppWindow == null) return;
if (window.AppWindow == null) return false;
if (enable)
{
@@ -308,6 +312,8 @@ namespace BetterLyrics.WinUI3.Hooks
{
window.Restore();
}
return true;
}
public static void SetIsShowInSwitchers(this Window window, bool enable)

View File

@@ -52,15 +52,74 @@ namespace BetterLyrics.WinUI3.Models
public LyricsWindowStatus()
{
LyricsStyleSettings.PropertyChanged += LyricsStyleSettings_PropertyChanged;
LyricsEffectSettings.PropertyChanged += LyricsEffectSettings_PropertyChanged;
LyricsBackgroundSettings.PropertyChanged += LyricsBackgroundSettings_PropertyChanged;
AlbumArtLayoutSettings.PropertyChanged += AlbumArtLayoutSettings_PropertyChanged;
AlbumArtAreaEffectSettings.PropertyChanged += AlbumArtAreaEffectSettings_PropertyChanged;
}
public LyricsWindowStatus(Window? targetWindow = null)
public LyricsWindowStatus(Window? targetWindow = null) : this()
{
UpdateMonitorNameAndBounds(targetWindow);
UpdateDemoWindowAndMonitorBounds();
}
partial void OnLyricsStyleSettingsChanged(LyricsStyleSettings oldValue, LyricsStyleSettings newValue)
{
oldValue.PropertyChanged -= LyricsStyleSettings_PropertyChanged;
newValue.PropertyChanged += LyricsStyleSettings_PropertyChanged;
}
private void LyricsStyleSettings_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
OnPropertyChanged(nameof(LyricsStyleSettings));
}
partial void OnLyricsEffectSettingsChanged(LyricsEffectSettings oldValue, LyricsEffectSettings newValue)
{
oldValue.PropertyChanged -= LyricsEffectSettings_PropertyChanged;
newValue.PropertyChanged += LyricsEffectSettings_PropertyChanged;
}
private void LyricsEffectSettings_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
OnPropertyChanged(nameof(LyricsEffectSettings));
}
partial void OnLyricsBackgroundSettingsChanged(LyricsBackgroundSettings oldValue, LyricsBackgroundSettings newValue)
{
oldValue.PropertyChanged -= LyricsBackgroundSettings_PropertyChanged;
newValue.PropertyChanged += LyricsBackgroundSettings_PropertyChanged;
}
private void LyricsBackgroundSettings_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
OnPropertyChanged(nameof(LyricsBackgroundSettings));
}
partial void OnAlbumArtLayoutSettingsChanged(AlbumArtAreaStyleSettings oldValue, AlbumArtAreaStyleSettings newValue)
{
oldValue.PropertyChanged -= AlbumArtLayoutSettings_PropertyChanged;
newValue.PropertyChanged += AlbumArtLayoutSettings_PropertyChanged;
}
private void AlbumArtLayoutSettings_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
OnPropertyChanged(nameof(AlbumArtLayoutSettings));
}
partial void OnAlbumArtAreaEffectSettingsChanged(AlbumArtAreaEffectSettings oldValue, AlbumArtAreaEffectSettings newValue)
{
oldValue.PropertyChanged -= AlbumArtAreaEffectSettings_PropertyChanged;
newValue.PropertyChanged += AlbumArtAreaEffectSettings_PropertyChanged;
}
private void AlbumArtAreaEffectSettings_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
OnPropertyChanged(nameof(AlbumArtAreaEffectSettings));
}
partial void OnWindowBoundsChanged(Rect value)
{
UpdateMonitorNameAndBounds();

View File

@@ -34,8 +34,8 @@ namespace BetterLyrics.WinUI3.Models.Settings
[ObservableProperty][NotifyPropertyChangedRecipients] public partial double LyricsLineSpacingFactor { get; set; } = 0.5;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LyricsCJKFontFamily { get; set; } = FontHelper.SystemFontFamilies.FirstOrDefault() ?? "";
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LyricsWesternFontFamily { get; set; } = FontHelper.SystemFontFamilies.FirstOrDefault() ?? "";
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LyricsCJKFontFamily { get; set; } = "Arial";
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LyricsWesternFontFamily { get; set; } = "Arial";
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int PlayingLineTopOffset { get; set; } = 50; // 50 %

View File

@@ -135,7 +135,8 @@ namespace BetterLyrics.WinUI3.Renderer
var effectSettings = windowStatus.LyricsEffectSettings;
var styleSettings = windowStatus.LyricsStyleSettings;
var rotationY = currentPlayingLine.OriginalPosition.WithX(effectSettings.FanLyricsAngle < 0 ? (float)lyricsWidth : 0);
var rotationX = effectSettings.FanLyricsAngle < 0 ? lyricsWidth : 0;
rotationX += lyricsWidth / 2 * (effectSettings.FanLyricsAngle < 0 ? 1 : -1);
for (int i = startVisibleIndex; i <= endVisibleIndex; i++)
{
@@ -145,14 +146,19 @@ namespace BetterLyrics.WinUI3.Renderer
if (line.OriginalCanvasTextLayout == null) continue;
if (line.OriginalCanvasTextLayout.LayoutBounds.Width <= 0) continue;
double xOffset = lyricsX;
double yOffset = line.YOffsetTransition.Value + userScrollOffset + lyricsY + lyricsHeight * playingLineTopOffsetFactor;
var transform =
Matrix3x2.CreateScale((float)line.ScaleTransition.Value, line.CenterPosition) *
Matrix3x2.CreateRotation((float)line.AngleTransition.Value, rotationY) *
Matrix3x2.CreateTranslation((float)lyricsX, (float)yOffset);
ds.Transform = Matrix3x2.CreateScale((float)line.ScaleTransition.Value, line.CenterPosition);
ds.Transform = transform;
if (effectSettings.IsFanLyricsEnabled)
{
xOffset += Math.Abs(line.AngleTransition.Value) / (Math.PI / 2) * lyricsWidth / 2 * (effectSettings.FanLyricsAngle < 0 ? 1 : -1);
var rotationY = line.CenterPosition.Y;
ds.Transform *= Matrix3x2.CreateRotation((float)line.AngleTransition.Value, new Vector2((float)rotationX, rotationY));
}
ds.Transform *= Matrix3x2.CreateTranslation((float)xOffset, (float)yOffset);
using (var textOnlyLayer = RenderBaseTextLayer(control, line, styleSettings.LyricsFontStrokeWidth, strokeColor, line.ColorTransition.Value))
{

View File

@@ -14,6 +14,7 @@
mc:Ignorable="d">
<Grid x:Name="RootGrid" SizeChanged="RootGrid_SizeChanged">
<Grid
x:Name="PlaceholderGrid"
Width="1"

View File

@@ -63,8 +63,6 @@ namespace BetterLyrics.WinUI3.Views
AppWindow.Changed += AppWindow_Changed;
AppWindow.Closing += AppWindow_Closing;
SystemBackdrop = SystemBackdropHelper.CreateSystemBackdrop(BackdropType.Transparent);
WeakReferenceMessenger.Default.RegisterAll(this);
UpdateAlbumArtThemeColors();
@@ -204,20 +202,24 @@ namespace BetterLyrics.WinUI3.Views
private void OnIsFullscreenChanged()
{
this.SetIsFullscreen(LyricsWindowStatus.IsFullscreen);
EnterFullscreenFontIcon.Opacity = LyricsWindowStatus.IsFullscreen ? 0 : 1;
ExitFullscreenFontIcon.Opacity = LyricsWindowStatus.IsFullscreen ? 1 : 0;
MaximizeButton.Visibility = LyricsWindowStatus.IsFullscreen ? Visibility.Collapsed : Visibility.Visible;
AOTButton.Visibility = LyricsWindowStatus.IsFullscreen ? Visibility.Collapsed : Visibility.Visible;
MinimizeButton.Visibility = LyricsWindowStatus.IsFullscreen ? Visibility.Collapsed : Visibility.Visible;
LockButton.Visibility = LyricsWindowStatus.IsFullscreen ? Visibility.Collapsed : Visibility.Visible;
if (this.SetIsFullscreen(LyricsWindowStatus.IsFullscreen))
{
EnterFullscreenFontIcon.Opacity = LyricsWindowStatus.IsFullscreen ? 0 : 1;
ExitFullscreenFontIcon.Opacity = LyricsWindowStatus.IsFullscreen ? 1 : 0;
MaximizeButton.Visibility = LyricsWindowStatus.IsFullscreen ? Visibility.Collapsed : Visibility.Visible;
AOTButton.Visibility = LyricsWindowStatus.IsFullscreen ? Visibility.Collapsed : Visibility.Visible;
MinimizeButton.Visibility = LyricsWindowStatus.IsFullscreen ? Visibility.Collapsed : Visibility.Visible;
LockButton.Visibility = LyricsWindowStatus.IsFullscreen ? Visibility.Collapsed : Visibility.Visible;
}
}
private void OnIsMaximizedChanged()
{
this.SetIsMaximized(LyricsWindowStatus.IsMaximized);
EnterMaximizeFontIcon.Opacity = LyricsWindowStatus.IsMaximized ? 0 : 1;
ExitMaximizeFontIcon.Opacity = LyricsWindowStatus.IsMaximized ? 1 : 0;
if (this.SetIsMaximized(LyricsWindowStatus.IsMaximized))
{
EnterMaximizeFontIcon.Opacity = LyricsWindowStatus.IsMaximized ? 0 : 1;
ExitMaximizeFontIcon.Opacity = LyricsWindowStatus.IsMaximized ? 1 : 0;
}
}
private void OnAutoShowOrHideWindowChanged()

View File

@@ -20,13 +20,18 @@ BetterLyrics
<div align=center>
![Static Badge](https://img.shields.io/badge/Language-C%23-purple) ![Static Badge](https://img.shields.io/badge/License-GPL_v3.0-blue) ![Static Badge](https://img.shields.io/badge/IDE-Visual%20Studio-purple) ![Static Badge](https://img.shields.io/badge/Framework-WinUI%203-blue)
![Static Badge](https://img.shields.io/badge/Language-C%23-purple)
![Static Badge](https://img.shields.io/badge/License-GPL_v3.0-blue)
![Static Badge](https://img.shields.io/badge/IDE-Visual%20Studio-purple)
![Static Badge](https://img.shields.io/badge/Framework-WinUI%203-blue)
</div>
<div align=center>
[![GitHub Repo stars](https://img.shields.io/github/stars/jayfunc/BetterLyrics)](https://github.com/jayfunc/BetterLyrics/stargazers)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/jayfunc/BetterLyrics)
[![zread](https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/jayfunc/BetterLyrics)
</div>
@@ -147,6 +152,8 @@ BetterLyrics
</details>
本项目的持续发展离不开大家的支持。**[查看完整鸣谢名单](SPONSORS.md)**
## 📄 许可证
本项目采用 GNU 通用公共许可证 v3.0 授权。详情请参阅 [LICENSE](https://github.com/jayfunc/BetterLyrics/blob/dev/LICENSE) 文件。

View File

@@ -20,13 +20,18 @@ BetterLyrics
<div align=center>
![Static Badge](https://img.shields.io/badge/Language-C%23-purple) ![Static Badge](https://img.shields.io/badge/License-GPL_v3.0-blue) ![Static Badge](https://img.shields.io/badge/IDE-Visual%20Studio-purple) ![Static Badge](https://img.shields.io/badge/Framework-WinUI%203-blue)
![Static Badge](https://img.shields.io/badge/Language-C%23-purple)
![Static Badge](https://img.shields.io/badge/License-GPL_v3.0-blue)
![Static Badge](https://img.shields.io/badge/IDE-Visual%20Studio-purple)
![Static Badge](https://img.shields.io/badge/Framework-WinUI%203-blue)
</div>
<div align=center>
[![GitHub Repo stars](https://img.shields.io/github/stars/jayfunc/BetterLyrics)](https://github.com/jayfunc/BetterLyrics/stargazers)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/jayfunc/BetterLyrics)
[![zread](https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/jayfunc/BetterLyrics)
</div>
@@ -153,6 +158,8 @@ You can donate via:
</details>
This project is made possible by the generous support of our users. **[View the full Hall of Fame](SPONSORS.md)**
## 📄 License
This project is licensed under the GNU General Public License v3.0. See the [LICENSE](https://github.com/jayfunc/BetterLyrics/blob/dev/LICENSE) file for details.

22
SPONSORS.md Normal file
View File

@@ -0,0 +1,22 @@
Special thanks to the following people for their support!
特别感谢以下朋友的支持!
| Date / 日期 | Name / 昵称 |
| :--- | :--- |
| Dec 13, 2025 | \<Anonymous\> |
| Dec 3, 2025 | YE |
| Dec 2, 2025 | \<Anonymous\> |
| Nov 23, 2025 | \*\*玄 |
| Nov 21, 2025 | \*\*智 |
| Nov 17, 2025 | \*鹤 |
| Nov 2, 2025 | 借过 |
| Aug 28, 2025 | \*\*华 |
> *List is updated manually. If you donated but don't see your name here, please contact me.*
>
> *名单手动更新。如果您已捐赠但未在此看到您的名字,请联系我。*
I would also like to express my sincere gratitude to **all users who purchased the app from the Store**. Your support is the driving force behind this project!
同时,向 **所有在商店购买应用的用户** 表达最诚挚的感谢。你们的支持是本项目不断前行的动力!