Compare commits

...

59 Commits

Author SHA1 Message Date
Zhe Fang
619a3ba196 chores: bump to v1.1.198.0 2025-12-17 15:55:33 -05:00
Zhe Fang
13526bb85c chores: i18n 2025-12-17 15:43:48 -05:00
Zhe Fang
61f4f608db fix 2025-12-17 15:06:22 -05:00
Zhe Fang
f690da8501 feat: add language info in playback settings 2025-12-17 14:52:01 -05:00
Zhe Fang
145c13a0e6 chores: improve lyrics window switch exp 2025-12-17 14:05:28 -05:00
Zhe Fang
cea4fbb54d fix: PasswordVaultHelper save issue 2025-12-17 10:54:44 -05:00
Zhe Fang
1d489c68e9 chores: bump to v1.1.194.0 2025-12-15 15:45:25 -05:00
Zhe Fang
90e7fa42d0 chores 2025-12-15 15:36:50 -05:00
Zhe Fang
29a6879e45 chores: remove csharp-kana 2025-12-15 14:58:51 -05:00
Zhe Fang
58499a2d09 chores: update i18n 2025-12-15 14:55:37 -05:00
Zhe Fang
580255699b chores: change romaji method 2025-12-15 14:42:11 -05:00
Zhe Fang
9cac7818f1 fix: system tray left click 2025-12-15 10:45:24 -05:00
Zhe Fang
118668a457 fix: timeline 2025-12-15 07:36:26 -05:00
Zhe Fang
37621dbf2a chores: adjust margin for NowPlayingBar 2025-12-15 07:29:26 -05:00
Zhe Fang
aa7d56f1cb chores: bump to v1.1.190.0 2025-12-14 11:56:24 -05:00
Zhe Fang
8dbe76e790 chores: change bg color for top title bar and now playing bar 2025-12-14 11:45:09 -05:00
Zhe Fang
de6410492e fix: Canvas_CreateResources 2025-12-14 11:20:04 -05:00
Zhe Fang
26df7c7f67 chores: bump to 1.1.188.0 2025-12-14 09:48:01 -05:00
Zhe Fang
3c411374bd chores: undo 2025-12-14 09:40:13 -05:00
Zhe Fang
99f0b9443b fix: spectrum count is not updating when chaning amount 2025-12-14 09:26:19 -05:00
Zhe Fang
a3bc148816 fix: prop clone 2025-12-14 09:18:49 -05:00
Zhe Fang
cea757702b feat: add settings item for always hiding unlock button 2025-12-14 09:17:27 -05:00
Zhe Fang
8938a5c798 feat: add settings item for stop music when closing music gallery window 2025-12-14 08:18:21 -05:00
Zhe Fang
46f4589b64 chores: dispose cover renderer when closed 2025-12-14 08:03:58 -05:00
Zhe Fang
adb02658f4 feat: add cover background 2025-12-14 07:58:41 -05:00
Zhe Fang
3d7e6061e9 fix: lyrics window settings config panel wont auto hide when open again 2025-12-14 06:52:08 -05:00
Zhe Fang
a51220c7b9 fix: playing line top offset out of bounds 2025-12-14 05:51:49 -05:00
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
Zhe Fang
42284b4f45 add: CoverBackgroundRenderer 2025-12-11 15:20:51 -05:00
Zhe Fang
7da8af7c2a fix: lyrics window manager tab not showing 2025-12-11 08:24:51 -05:00
Zhe Fang
a4fc457065 chores: bump to v1.1.181.0 2025-12-11 07:44:20 -05:00
Zhe Fang
d3c2ee592c fix: selectorbar section disappear 2025-12-11 07:19:05 -05:00
Zhe Fang
2eef88523c Modify taskbar.json for layout and style changes
Updated taskbar settings including bounds, opacity, and effects.
2025-12-10 16:17:25 -05:00
Zhe Fang
220b1063ac fix: taskbar mode is not working in release mode 2025-12-10 16:15:58 -05:00
Zhe Fang
28bcd8ddfc chores: remove taskbar mode entry 2025-12-10 14:09:16 -05:00
Zhe Fang
5750bd3ad7 add: more info in thanks control 2025-12-10 11:54:03 -05:00
Zhe Fang
1667c701b0 feat: taskbar mode 2025-12-10 11:09:53 -05:00
Zhe Fang
160398f7ab fix: add null check for Window.AppWindow 2025-12-10 10:51:45 -05:00
Zhe Fang
c25ddf770f fix: when open app with window locked, then unlock the window, title bar and bottom bar will not be interactive 2025-12-10 10:42:06 -05:00
Zhe Fang
44fa3312b2 fix: docked mode ux exp 2025-12-10 07:09:08 -05:00
Zhe Fang
81f3d1f6bf fix: cannot exit app when docked mode is on 2025-12-10 06:54:21 -05:00
75 changed files with 2100 additions and 593 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.175.0" />
Version="1.1.198.0" />
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

View File

@@ -10,7 +10,8 @@ using BetterLyrics.WinUI3.Services.LyricsSearchService;
using BetterLyrics.WinUI3.Services.MediaSessionsService;
using BetterLyrics.WinUI3.Services.ResourceService;
using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.Services.TranslateService;
using BetterLyrics.WinUI3.Services.TranslationService;
using BetterLyrics.WinUI3.Services.TransliterationService;
using BetterLyrics.WinUI3.ViewModels;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.DependencyInjection;
@@ -114,7 +115,8 @@ namespace BetterLyrics.WinUI3
.AddSingleton<IAlbumArtSearchService, AlbumArtSearchService>()
.AddSingleton<ILyricsSearchService, LyricsSearchService>()
.AddSingleton<ILibWatcherService, LibWatcherService>()
.AddSingleton<ITranslateService, TranslateService>()
.AddSingleton<ITranslationService, TranslationService>()
.AddSingleton<ITransliterationService, TransliterationService>()
.AddSingleton<ILastFMService, LastFMService>()
.AddSingleton<IResourceService, ResourceService>()
.AddSingleton<IDiscordService, DiscordService>()

View File

@@ -67,27 +67,26 @@
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
<PackageReference Include="CommunityToolkit.WinUI.Triggers" Version="8.2.250402" />
<PackageReference Include="ComputeSharp.D2D1.WinUI" Version="3.2.0" />
<PackageReference Include="csharp-kana" Version="1.0.2" />
<PackageReference Include="csharp-pinyin" Version="1.0.1" />
<PackageReference Include="DevWinUI.Controls" Version="9.7.0" />
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" />
<PackageReference Include="DevWinUI.Controls" Version="9.7.1" />
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.6" />
<PackageReference Include="F23.StringSimilarity" Version="7.0.1" />
<PackageReference Include="FlaUI.UIA3" Version="5.0.0" />
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.4.1" />
<PackageReference Include="Hqub.Last.fm" Version="2.5.1" />
<PackageReference Include="Interop.UIAutomationClient" Version="10.19041.0" />
<PackageReference Include="Lyricify.Lyrics.Helper-NativeAot" Version="0.1.4-alpha.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.1" />
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.7175" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.8.251106002" />
<PackageReference Include="NAudio.Wasapi" Version="2.2.1" />
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
<PackageReference Include="Nito.AsyncEx.Tasks" Version="5.1.2" />
<PackageReference Include="NTextCat" Version="0.3.65" />
<PackageReference Include="Serilog.Extensions.Logging" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="System.Drawing.Common" Version="10.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="10.0.0" />
<PackageReference Include="System.Drawing.Common" Version="10.0.1" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="10.0.1" />
<PackageReference Include="TagLibSharp" Version="2.3.0" />
<PackageReference Include="Ude.NetStandard" Version="1.2.0" />
<PackageReference Include="Vanara.PInvoke.DwmApi" Version="4.2.1" />
@@ -115,6 +114,8 @@
</ItemGroup>
<!--Disable Trimming for Specific Packages-->
<ItemGroup>
<TrimmerRootAssembly Include="FlaUI.UIA3" />
<TrimmerRootAssembly Include="Interop.UIAutomationClient" />
<TrimmerRootAssembly Include="NAudio.Wasapi" />
<TrimmerRootAssembly Include="TagLibSharp" />
<TrimmerRootAssembly Include="Vanara.PInvoke.DwmApi" />

View File

@@ -5,9 +5,9 @@
public const string MicrosoftStore = "https://apps.microsoft.com/detail/9p1wcd1p597r";
public const string AuthorGitHub = "https://github.com/jayfunc";
public const string BetterLyricsGitHub = $"{AuthorGitHub}/BetterLyrics";
public const string ShareHub = $"{BetterLyricsGitHub}/blob/dev/ShareHub/index.md";
public const string TermsOfService = $"{BetterLyricsGitHub}/blob/dev/TermsofService.md";
public const string PrivacyPolicy = $"{BetterLyricsGitHub}/blob/dev/PrivacyPolicy.md";

View File

@@ -248,7 +248,7 @@
</Hyperlink>
</Paragraph>
<!-- 打赏者 -->
<!-- 赞助 -->
<Paragraph Margin="0,20,0,0" FontWeight="Bold">
<Run x:Uid="SettingsPagePatrons" />
</Paragraph>
@@ -277,231 +277,94 @@
<Run Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="Aug 28, 2025" />
</Paragraph>
<Paragraph>
<Run x:Uid="SettingsPageYouNowUsing" FontStyle="Italic" />
<Run x:Uid="SettingsPageUserWhoPurchased" />
</Paragraph>
<!-- 依赖包 -->
<!-- 特别鸣谢 -->
<Paragraph Margin="0,20,0,0" FontWeight="Bold">
<Run x:Uid="SetingsPageSpecialThanks" />
</Paragraph>
<Paragraph>
<Run x:Uid="SettingsPageYouNowUsing" />
</Paragraph>
<!-- 代码参考 -->
<Paragraph Margin="0,20,0,0" FontWeight="Bold">
<Run x:Uid="SetingsPageDeps" />
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/3v.EvtSource">
<Run Text="3v.EvtSource" />
<Hyperlink NavigateUri="https://gist.github.com/mcworkaholic/82fbf203e3f1043bbe534b5b2974c0ce">
<Run Text="Get album artwork from ITunes (with Python3 or C#)" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.Labs.WinUI.Controls.OpacityMaskView">
<Run Text="CommunityToolkit.Labs.WinUI.Controls.OpacityMaskView" />
<Hyperlink NavigateUri="https://stackoverflow.com/a/32013610/11048731">
<Run Text="FullyObservableCollection" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.Labs.WinUI.Shimmer">
<Run Text="CommunityToolkit.Labs.WinUI.Shimmer" />
<Hyperlink NavigateUri="https://github.com/Storyteller-Studios/Impressionist">
<Run Text="Impressionist" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.Mvvm">
<Run Text="CommunityToolkit.Mvvm" />
<Hyperlink NavigateUri="https://github.com/Storyteller-Studios/ColorThief.WinUI3">
<Run Text="ColorThief.WinUI3" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Behaviors">
<Run Text="CommunityToolkit.WinUI.Behaviors" />
<Hyperlink NavigateUri="https://github.com/Johnwikix/SpectrumVisualization">
<Run Text="SpectrumVisualization" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Controls.Primitives">
<Run Text="CommunityToolkit.WinUI.Controls.Primitives" />
<Hyperlink NavigateUri="https://www.shadertoy.com/view/Mdt3Df">
<Run Text="Snow (as shown in sweden)" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Controls.Segmented">
<Run Text="CommunityToolkit.WinUI.Controls.Segmented" />
<Hyperlink NavigateUri="https://www.shadertoy.com/view/lllSR2">
<Run Text="w10" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Converters">
<Run Text="CommunityToolkit.WinUI.Converters" />
<Hyperlink NavigateUri="https://github.com/mo-jinran/Taskbar-Lyrics">
<Run Text="Taskbar-Lyrics" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Extensions">
<Run Text="CommunityToolkit.WinUI.Extensions" />
<Hyperlink NavigateUri="https://github.com/jayfunc/BetterLyrics/network/dependencies">
<Run Text="..." />
</Hyperlink>
</Paragraph>
<!-- UI/UX 设计参考 -->
<Paragraph Margin="0,20,0,0" FontWeight="Bold">
<Run x:Uid="SetingsPageUIUXRef" />
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://github.com/solstice23/refined-now-playing-netease">
<Run Text="refined-now-playing-netease" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Helpers">
<Run Text="CommunityToolkit.WinUI.Helpers" />
<Hyperlink NavigateUri="https://github.com/WXRIW/Lyricify-App">
<Run Text="Lyricify" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Media">
<Run Text="CommunityToolkit.WinUI.Media" />
<Hyperlink NavigateUri="https://moriafly.com/program/salt-player">
<Run Text="椒盐音乐 Salt Player" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/CommunityToolkit.WinUI.Triggers">
<Run Text="CommunityToolkit.WinUI.Triggers" />
<Hyperlink NavigateUri="https://github.com/TwilightLemon/MyToolBar">
<Run Text="MyToolBar" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/ComputeSharp.D2D1.WinUI">
<Run Text="ComputeSharp.D2D1.WinUI" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/csharp-kana">
<Run Text="csharp-kana" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/csharp-pinyin">
<Run Text="csharp-pinyin" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/DevWinUI.Controls">
<Run Text="DevWinUI.Controls" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Dubya.WindowsMediaController">
<Run Text="Dubya.WindowsMediaController" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/F23.StringSimilarity">
<Run Text="F23.StringSimilarity" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/H.NotifyIcon.WinUI">
<Run Text="H.NotifyIcon.WinUI" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Hqub.Last.fm">
<Run Text="Hqub.Last.fm" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Lyricify.Lyrics.Helper-NativeAot">
<Run Text="Lyricify.Lyrics.Helper-NativeAot" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection">
<Run Text="Microsoft.Extensions.DependencyInjection" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Microsoft.Extensions.Logging">
<Run Text="Microsoft.Extensions.Logging" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Microsoft.Graphics.Win2D">
<Run Text="Microsoft.Graphics.Win2D" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Microsoft.Windows.SDK.BuildTools">
<Run Text="Microsoft.Windows.SDK.BuildTools" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Microsoft.WindowsAppSDK">
<Run Text="Microsoft.WindowsAppSDK" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/NAudio.Wasapi">
<Run Text="NAudio.Wasapi" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Nito.AsyncEx">
<Run Text="Nito.AsyncEx" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Nito.AsyncEx.Tasks">
<Run Text="Nito.AsyncEx.Tasks" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/NTextCat">
<Run Text="NTextCat" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Serilog.Extensions.Logging">
<Run Text="Serilog.Extensions.Logging" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Serilog.Sinks.File">
<Run Text="Serilog.Sinks.File" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/System.Drawing.Common">
<Run Text="System.Drawing.Common" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/System.Text.Encoding.CodePages">
<Run Text="System.Text.Encoding.CodePages" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/TagLibSharp">
<Run Text="TagLibSharp" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Ude.NetStandard">
<Run Text="Ude.NetStandard" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Vanara.PInvoke.DwmApi">
<Run Text="Vanara.PInvoke.DwmApi" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Vanara.PInvoke.Gdi32">
<Run Text="Vanara.PInvoke.Gdi32" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Vanara.PInvoke.Shell32">
<Run Text="Vanara.PInvoke.Shell32" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Vanara.PInvoke.User32">
<Run Text="Vanara.PInvoke.User32" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/Vanara.Windows.Shell">
<Run Text="Vanara.Windows.Shell" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/VCollab.DiscordRichPresence">
<Run Text="VCollab.DiscordRichPresence" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/WinUIEx">
<Run Text="WinUIEx" />
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink NavigateUri="https://www.nuget.org/packages/z440.atl.core">
<Run Text="z440.atl.core" />
<Hyperlink NavigateUri="">
<Run Text="" />
</Hyperlink>
</Paragraph>

View File

@@ -3,7 +3,6 @@ using CommunityToolkit.Mvvm.DependencyInjection;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using System.Threading.Tasks;
using Windows.UI.ApplicationSettings;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.

View File

@@ -71,6 +71,10 @@
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.MusicGallerySettings.AutoPlay, Mode=TwoWay}" />
</dev:SettingsCard>
<dev:SettingsCard x:Uid="SettingsPageStopTrackOnGalleryWindowClosed" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=&#xE71A;}">
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.MusicGallerySettings.StopOnWindowClosed, Mode=TwoWay}" />
</dev:SettingsCard>
<dev:SettingsCard x:Uid="SettingsPageExitOnGalleryWindowClosed" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=&#xE711;}">
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.MusicGallerySettings.ExitOnWindowClosed, Mode=TwoWay}" />
</dev:SettingsCard>

View File

@@ -7,6 +7,7 @@
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:local="using:BetterLyrics.WinUI3.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI"
mc:Ignorable="d">
<Grid
@@ -91,6 +92,47 @@
Text="{x:Bind LyricsWindowStatus.Name, Mode=OneWay}"
TextWrapping="Wrap" />
</Grid>
<Grid Background="{ThemeResource AcrylicInAppFillColorDefaultBrush}" Opacity="0">
<Grid.OpacityTransition>
<ScalarTransition />
</Grid.OpacityTransition>
<interactivity:Interaction.Behaviors>
<interactivity:EventTriggerBehavior EventName="PointerEntered">
<interactivity:ChangePropertyAction PropertyName="Opacity" Value="1" />
</interactivity:EventTriggerBehavior>
<interactivity:EventTriggerBehavior EventName="PointerExited">
<interactivity:ChangePropertyAction PropertyName="Opacity" Value="0" />
</interactivity:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Click="OpenButton_Click"
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
Glyph=&#xE78B;}">
<ToolTipService.ToolTip>
<TextBlock x:Uid="SystemTrayLyrics" />
</ToolTipService.ToolTip>
</Button>
<Button
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Click="CloseButton_Click"
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
Glyph=&#xE711;}"
IsEnabled="{x:Bind LyricsWindowStatus.IsOpened, Mode=OneWay}">
<ToolTipService.ToolTip>
<TextBlock x:Uid="SettingsPageCloseStatus" />
</ToolTipService.ToolTip>
</Button>
</Grid>
</Grid>
</UserControl>

View File

@@ -1,6 +1,12 @@
using BetterLyrics.WinUI3.Hooks;
using BetterLyrics.WinUI3.Models;
using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.DependencyInjection;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Linq;
using static Vanara.PInvoke.User32.RAWINPUT;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
@@ -9,6 +15,8 @@ namespace BetterLyrics.WinUI3.Controls;
public sealed partial class DemoWindowGrid : UserControl
{
private readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
public DemoWindowGrid()
{
InitializeComponent();
@@ -22,4 +30,32 @@ public sealed partial class DemoWindowGrid : UserControl
get => (LyricsWindowStatus)GetValue(LyricsWindowStatusProperty);
set => SetValue(LyricsWindowStatusProperty, value);
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
var data = (LyricsWindowStatus)(((FrameworkElement)sender).DataContext);
var window = WindowHook.GetWindows<NowPlayingWindow>().FirstOrDefault(x => x.LyricsWindowStatus == data);
window?.CloseWindow();
}
private void OpenButton_Click(object sender, RoutedEventArgs e)
{
var status = (LyricsWindowStatus)(((FrameworkElement)sender).DataContext);
// <20>࿪ģʽ
if (_settingsService.AppSettings.GeneralSettings.MultiNowPlayingWindowMode)
{
WindowHook.OpenOrShowWindow<NowPlayingWindow>(status);
}
// <20><><EFBFBD><EFBFBD>ģʽ
else
{
var openedWindows = WindowHook.GetWindows<NowPlayingWindow>();
foreach (var item in openedWindows.Where(x => x.LyricsWindowStatus != status))
{
item.CloseWindow();
}
WindowHook.OpenOrShowWindow<NowPlayingWindow>(status);
}
}
}

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

@@ -47,6 +47,51 @@
</dev:SettingsExpander.Items>
</dev:SettingsExpander>
<dev:SettingsExpander
x:Uid="SettingsPageAlbumArtLayer"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
Glyph=&#xE93C;}"
IsExpanded="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=TwoWay}" />
<dev:SettingsExpander.Items>
<dev:SettingsCard x:Uid="SettingsPageOpacity" IsEnabled="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=OneWay}">
<uc:ExtendedSlider
Default="100"
Maximum="100"
Minimum="0"
Unit="%"
Value="{x:Bind LyricsBackgroundSettings.CoverOverlayOpacity, Mode=TwoWay}" />
</dev:SettingsCard>
<dev:SettingsCard x:Uid="SettingsPageSpeed" IsEnabled="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=OneWay}">
<uc:ExtendedSlider
Default="50"
Maximum="100"
Minimum="0"
Unit="%"
Value="{x:Bind LyricsBackgroundSettings.CoverOverlaySpeed, Mode=TwoWay}" />
</dev:SettingsCard>
<dev:SettingsCard x:Uid="SettingsPageBlurAmount" IsEnabled="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=OneWay}">
<uc:ExtendedSlider
Default="100"
Maximum="200"
Minimum="0"
Value="{x:Bind LyricsBackgroundSettings.CoverOverlayBlurAmount, Mode=TwoWay}" />
</dev:SettingsCard>
<!--<dev:SettingsCard x:Uid="SettingsPageBackgroundAcrylicEffectAmount" IsEnabled="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=OneWay}">
<uc:ExtendedSlider
Default="0"
Maximum="10"
Minimum="0"
Value="{x:Bind LyricsBackgroundSettings.CoverAcrylicEffectAmount, Mode=TwoWay}" />
</dev:SettingsCard>-->
</dev:SettingsExpander.Items>
</dev:SettingsExpander>
<dev:SettingsExpander
x:Uid="SettingsPageFluidLayer"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},

View File

@@ -13,15 +13,21 @@ using BetterLyrics.WinUI3.Services.SettingsService;
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
using Lyricify.Lyrics.Providers.Web.Netease;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.UI.Xaml;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Storage.Streams;
using Windows.UI;
using static Vanara.PInvoke.Ole32;
namespace BetterLyrics.WinUI3.Controls
{
@@ -34,7 +40,8 @@ namespace BetterLyrics.WinUI3.Controls
IRecipient<PropertyChangedMessage<bool>>,
IRecipient<PropertyChangedMessage<TextAlignmentType>>,
IRecipient<PropertyChangedMessage<LyricsFontWeight>>,
IRecipient<PropertyChangedMessage<string>>
IRecipient<PropertyChangedMessage<string>>,
IRecipient<PropertyChangedMessage<IRandomAccessStream?>>
{
private readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
private readonly IMediaSessionsService _mediaSessionsService = Ioc.Default.GetRequiredService<IMediaSessionsService>();
@@ -42,6 +49,7 @@ namespace BetterLyrics.WinUI3.Controls
private readonly LyricsRenderer _lyricsRenderer = new();
private readonly FluidBackgroundRenderer _fluidRenderer = new();
private readonly CoverBackgroundRenderer _coverRenderer = new();
private readonly PureColorBackgroundRenderer _pureColorRenderer = new();
private readonly SnowRenderer _snowRenderer = new();
private readonly FogRenderer _fogRenderer = new();
@@ -368,8 +376,8 @@ namespace BetterLyrics.WinUI3.Controls
lyricsBg.IsPureColorOverlayEnabled
);
_fluidRenderer.Opacity = lyricsBg.FluidOverlayOpacity / 100.0;
_fluidRenderer.IsEnabled = lyricsBg.IsFluidOverlayEnabled;
_coverRenderer.Draw(sender, args.DrawingSession);
_fluidRenderer.Draw(sender, args.DrawingSession);
_snowRenderer.Draw(sender, args.DrawingSession);
@@ -549,16 +557,21 @@ namespace BetterLyrics.WinUI3.Controls
_isLayoutChanged = false;
if (_fluidRenderer.IsEnabled)
{
_fluidRenderer.UpdateColors(
_accentColor1Transition.Value,
_accentColor2Transition.Value,
_accentColor3Transition.Value,
_accentColor4Transition.Value
);
_fluidRenderer.Update(elapsedTime);
}
_fluidRenderer.IsEnabled = lyricsBg.IsFluidOverlayEnabled;
_fluidRenderer.Opacity = lyricsBg.FluidOverlayOpacity / 100.0;
_fluidRenderer.UpdateColors(
_accentColor1Transition.Value,
_accentColor2Transition.Value,
_accentColor3Transition.Value,
_accentColor4Transition.Value
);
_fluidRenderer.Update(elapsedTime);
_coverRenderer.IsEnabled = lyricsBg.IsCoverOverlayEnabled;
_coverRenderer.Opacity = lyricsBg.CoverOverlayOpacity;
_coverRenderer.BlurAmount = lyricsBg.CoverOverlayBlurAmount;
_coverRenderer.Speed = lyricsBg.CoverOverlaySpeed;
_coverRenderer.Update(elapsedTime);
_snowRenderer.IsEnabled = lyricsBg.IsSnowFlakeOverlayEnabled;
_snowRenderer.Amount = lyricsBg.SnowFlakeOverlayAmount / 100f;
@@ -586,6 +599,7 @@ namespace BetterLyrics.WinUI3.Controls
private void Canvas_Unloaded(object sender, RoutedEventArgs e)
{
_fluidRenderer.Dispose();
_coverRenderer.Dispose();
_snowRenderer.Dispose();
_fogRenderer.Dispose();
_spectrumRenderer.Dispose();
@@ -600,7 +614,13 @@ namespace BetterLyrics.WinUI3.Controls
private async void Canvas_CreateResources(CanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{
args.TrackAsyncAction(_fluidRenderer.LoadResourcesAsync().AsAsyncAction());
var tasks = new Task[]
{
_fluidRenderer.LoadResourcesAsync(),
ReloadCoverBackgroundResourcesAsync()
};
args.TrackAsyncAction(Task.WhenAll(tasks).AsAsyncAction());
_snowRenderer.LoadResources();
_fogRenderer.LoadResources();
@@ -682,6 +702,16 @@ namespace BetterLyrics.WinUI3.Controls
}).ToList();
}
private async Task ReloadCoverBackgroundResourcesAsync()
{
if (_mediaSessionsService.AlbumArtBitmapStream is IRandomAccessStream stream)
{
stream.Seek(0);
CanvasBitmap bitmap = await CanvasBitmap.LoadAsync(Canvas, stream);
_coverRenderer.SetCoverBitmap(bitmap);
}
}
public void Receive(PropertyChangedMessage<TimeSpan> message)
{
if (message.Sender is IMediaSessionsService)
@@ -827,6 +857,14 @@ namespace BetterLyrics.WinUI3.Controls
{
_isLayoutChanged = true;
}
else if (message.PropertyName == nameof(LyricsEffectSettings.IsLyricsFadeOutEffectEnabled))
{
_isLayoutChanged = true;
}
else if (message.PropertyName == nameof(LyricsEffectSettings.IsLyricsOutOfSightEffectEnabled))
{
_isLayoutChanged = true;
}
}
else if (message.Sender == LyricsWindowStatus?.LyricsStyleSettings)
{
@@ -874,5 +912,15 @@ namespace BetterLyrics.WinUI3.Controls
}
}
public void Receive(PropertyChangedMessage<IRandomAccessStream?> message)
{
if (message.Sender is IMediaSessionsService)
{
if (message.PropertyName == nameof(IMediaSessionsService.AlbumArtBitmapStream))
{
_ = ReloadCoverBackgroundResourcesAsync();
}
}
}
}
}

View File

@@ -28,6 +28,16 @@
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsBlurEffectEnabled, Mode=TwoWay}" />
</dev:SettingsCard>
<!-- 淡出效果 -->
<dev:SettingsCard x:Uid="SettingsPageLyricsFadeOutEffect" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=&#xE89F;}">
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsFadeOutEffectEnabled, Mode=TwoWay}" />
</dev:SettingsCard>
<!-- 远离视野 -->
<dev:SettingsCard x:Uid="SettingsPageLyricsOutOfSightEffect" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=&#xF19D;}">
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsOutOfSightEffectEnabled, Mode=TwoWay}" />
</dev:SettingsCard>
<!-- 辉光效果 -->
<dev:SettingsExpander x:Uid="SettingsPageLyricsGlowEffect" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=&#xE9A9;}">
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsGlowEffectEnabled, Mode=TwoWay}" />

View File

@@ -32,8 +32,8 @@
<dev:SettingsCard x:Uid="SettingsPageLyricsCenterTopOffset" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=&#xE78A;}">
<local:ExtendedSlider
Default="50"
Maximum="100"
Minimum="0"
Maximum="99"
Minimum="1"
Unit="%"
Value="{x:Bind LyricsStyleSettings.PlayingLineTopOffset, Mode=TwoWay}" />
</dev:SettingsCard>

View File

@@ -11,6 +11,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:uc="using:BetterLyrics.WinUI3.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
Loaded="UserControl_Loaded"
mc:Ignorable="d">
<Grid>
@@ -37,6 +38,7 @@
<MenuFlyoutItem x:Uid="SettingsPageDockedMode" Command="{x:Bind ViewModel.CreateDockedLyricsWindowStatusCommand}" />
<MenuFlyoutItem x:Uid="SettingsPageFullscreenMode" Command="{x:Bind ViewModel.CreateFullLyricsWindowStatusCommand}" />
<MenuFlyoutItem x:Uid="SettingsPageNarrowMode" Command="{x:Bind ViewModel.CreateNarrowLyricsWindowStatusCommand}" />
<MenuFlyoutItem x:Uid="SettingsPageTaskbarMode" Command="{x:Bind ViewModel.CreateTaskbarLyricsWindowStatusCommand}" />
</MenuFlyout>
</Button.Flyout>
</Button>
@@ -98,10 +100,7 @@
BorderThickness="4"
CornerRadius="4"
Visibility="{Binding IsOpened, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
<uc:DemoWindowGrid
Margin="4"
LyricsWindowStatus="{Binding}"
Tapped="DemoWindowGrid_Tapped" />
<uc:DemoWindowGrid Margin="4" LyricsWindowStatus="{Binding}" />
</Grid>
<Grid>
<ToggleButton
@@ -115,7 +114,6 @@
<Grid ColumnSpacing="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="0"
@@ -123,13 +121,6 @@
Click="ConfigButton_Click">
<TextBlock x:Uid="LyricsWindowSettingsControlLyricsWindowConfig" />
</Button>
<Button
Grid.Column="1"
HorizontalAlignment="Stretch"
Click="CloseStatusButton_Click"
IsEnabled="{Binding IsOpened, Mode=OneWay}">
<TextBlock x:Uid="SettingsPageCloseStatus" />
</Button>
</Grid>
</StackPanel>
</DataTemplate>
@@ -194,26 +185,34 @@
Style="{StaticResource AccentButtonStyle}" />
</Grid>
<SelectorBar x:Name="ConfigSelectorBar" SelectionChanged="ConfigSelectorBar_SelectionChanged">
<controls:Segmented
x:Name="ConfigSegmented"
SelectionChanged="ConfigSegmented_SelectionChanged"
Style="{StaticResource PivotSegmentedStyle}">
<SelectorBarItem
x:Name="WindowSelectorBarItem"
x:Uid="AppSettingsControlGeneral"
Tag="Window" />
<SelectorBarItem
x:Name="LayoutSelectorBarItem"
x:Uid="SettingsPageLayout"
Tag="Layout" />
<SelectorBarItem
x:Name="AlbumArtStyleSelectorBarItem"
x:Uid="SettingsPageAlbumStyle"
Tag="AlbumArtStyle" />
<SelectorBarItem x:Uid="SettingsPageAlbumEffect" Tag="AlbumArtEffect" />
<SelectorBarItem x:Uid="SettingsPageLyricsStyle" Tag="LyricsStyle" />
<SelectorBarItem x:Uid="SettingsPageLyricsEffect" Tag="LyricsEffect" />
<SelectorBarItem x:Uid="SettingsPageBackgroundOverlay" Tag="LyricsBackground" />
<controls:SegmentedItem x:Name="WindowSegmentedItem" Tag="Window">
<TextBlock x:Uid="AppSettingsControlGeneral" />
</controls:SegmentedItem>
<controls:SegmentedItem x:Name="LayoutSegmentedItem" Tag="Layout">
<TextBlock x:Uid="SettingsPageLayout" />
</controls:SegmentedItem>
<controls:SegmentedItem x:Name="AlbumArtStyleSegmentedItem" Tag="AlbumArtStyle">
<TextBlock x:Uid="SettingsPageAlbumStyle" />
</controls:SegmentedItem>
<controls:SegmentedItem Tag="AlbumArtEffect">
<TextBlock x:Uid="SettingsPageAlbumEffect" />
</controls:SegmentedItem>
<controls:SegmentedItem Tag="LyricsStyle">
<TextBlock x:Uid="SettingsPageLyricsStyle" />
</controls:SegmentedItem>
<controls:SegmentedItem Tag="LyricsEffect">
<TextBlock x:Uid="SettingsPageLyricsEffect" />
</controls:SegmentedItem>
<controls:SegmentedItem Tag="LyricsBackground">
<TextBlock x:Uid="SettingsPageBackgroundOverlay" />
</controls:SegmentedItem>
</SelectorBar>
</controls:Segmented>
</StackPanel>
</Grid>

View File

@@ -6,9 +6,11 @@ using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.ViewModels;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.WinUI.Controls;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -25,14 +27,14 @@ namespace BetterLyrics.WinUI3.Controls
private readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
public LyricsWindowStatus LyricsWindowStatus
public LyricsWindowStatus? LyricsWindowStatus
{
get { return (LyricsWindowStatus)GetValue(LyricsWindowStatusProperty); }
get { return (LyricsWindowStatus?)GetValue(LyricsWindowStatusProperty); }
set { SetValue(LyricsWindowStatusProperty, value); }
}
public static readonly DependencyProperty LyricsWindowStatusProperty =
DependencyProperty.Register(nameof(LyricsWindowStatus), typeof(LyricsWindowStatus), typeof(LyricsWindowSettingsControl), new PropertyMetadata(default));
DependencyProperty.Register(nameof(LyricsWindowStatus), typeof(LyricsWindowStatus), typeof(LyricsWindowSettingsControl), new PropertyMetadata(null));
public LyricsWindowSettingsControl()
{
@@ -151,61 +153,28 @@ namespace BetterLyrics.WinUI3.Controls
private void ConfigButton_Click(object sender, RoutedEventArgs e)
{
WindowSelectorBarItem.Visibility = LayoutSelectorBarItem.Visibility = Visibility.Visible;
ConfigSelectorBar.SelectedItem = WindowSelectorBarItem;
WindowSegmentedItem.IsEnabled = LayoutSegmentedItem.IsEnabled = true;
ConfigSegmented.SelectedItem = WindowSegmentedItem;
LyricsWindowStatus = (LyricsWindowStatus)((Button)sender).DataContext;
ViewModel.OpenConfigPanel();
}
private void EmbeddedConfigButton_Click(object sender, RoutedEventArgs e)
{
WindowSelectorBarItem.Visibility = LayoutSelectorBarItem.Visibility = Visibility.Collapsed;
ConfigSelectorBar.SelectedItem = AlbumArtStyleSelectorBarItem;
WindowSegmentedItem.IsEnabled = LayoutSegmentedItem.IsEnabled = false;
ConfigSegmented.SelectedItem = AlbumArtStyleSegmentedItem;
LyricsWindowStatus = _settingsService.AppSettings.MusicGallerySettings.LyricsWindowStatus;
ViewModel.OpenConfigPanel();
}
private void DemoWindowGrid_Tapped(object sender, TappedRoutedEventArgs e)
private void ConfigSegmented_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var status = (LyricsWindowStatus)(((FrameworkElement)sender).DataContext);
// <20>࿪ģʽ
if (_settingsService.AppSettings.GeneralSettings.MultiNowPlayingWindowMode)
{
WindowHook.OpenOrShowWindow<NowPlayingWindow>(status);
}
// <20><><EFBFBD><EFBFBD>ģʽ
else
{
var openedWindows = WindowHook.GetWindows<NowPlayingWindow>();
foreach (var item in openedWindows.Where(x => x.LyricsWindowStatus != status))
{
item.CloseWindow();
}
WindowHook.OpenOrShowWindow<NowPlayingWindow>(status);
}
ViewModel.SelectorBarSelectedItemTag = (string)((SegmentedItem)((Segmented)sender).SelectedItem).Tag;
}
private void ConfigSelectorBar_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs args)
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (sender is SelectorBar bar)
{
if (bar.SelectedItem is SelectorBarItem item)
{
ViewModel?.SelectorBarSelectedItemTag = item.Tag;
}
}
}
private void CloseStatusButton_Click(object sender, RoutedEventArgs e)
{
if (sender is FrameworkElement element)
{
if (element.DataContext is LyricsWindowStatus data)
{
var window = WindowHook.GetWindows<NowPlayingWindow>().FirstOrDefault(x => x.LyricsWindowStatus == data);
window?.CloseWindow();
}
}
ViewModel.CloseConfigPanelCommand.Execute(null);
}
}
}

View File

@@ -29,22 +29,6 @@ namespace BetterLyrics.WinUI3.Controls
private async void Grid_Tapped(object sender, TappedRoutedEventArgs e)
{
var status = (LyricsWindowStatus)(((FrameworkElement)sender).DataContext);
// <20>࿪ģʽ
if (_settingsService.AppSettings.GeneralSettings.MultiNowPlayingWindowMode)
{
WindowHook.OpenOrShowWindow<NowPlayingWindow>(status);
}
// <20><><EFBFBD><EFBFBD>ģʽ
else
{
var openedWindows = WindowHook.GetWindows<NowPlayingWindow>();
foreach (var item in openedWindows.Where(x => x.LyricsWindowStatus != status))
{
item.CloseWindow();
}
WindowHook.OpenOrShowWindow<NowPlayingWindow>(status);
}
await HideAsync();
}

View File

@@ -14,7 +14,7 @@
<Grid
x:Name="BottomCommandGrid"
Background="{ThemeResource AcrylicInAppFillColorDefaultBrush}"
Background="{ThemeResource LayerOnMicaBaseAltFillColorDefaultBrush}"
Opacity="{x:Bind ViewModel.BottomCommandGridOpacity, Mode=OneWay}"
PointerEntered="BottomCommandGrid_PointerEntered"
PointerExited="BottomCommandGrid_PointerExited">
@@ -342,7 +342,7 @@
<Slider
x:Name="TimelineSlider"
Margin="0,-12,0,0"
Margin="0,-14,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Maximum="{x:Bind ViewModel.MediaSessionsService.CurrentSongInfo.DurationMs, Mode=OneWay, Converter={StaticResource MillisecondsToSecondsConverter}}"

View File

@@ -290,10 +290,7 @@ public sealed partial class NowPlayingBar : UserControl,
{
if (message.PropertyName == nameof(IMediaSessionsService.CurrentPosition))
{
DispatcherQueue.TryEnqueue(() =>
{
TimelineSlider.Value = message.NewValue.TotalSeconds;
});
TimelineSlider.Value = message.NewValue.TotalSeconds;
}
}
}

View File

@@ -348,6 +348,7 @@
x:Uid="LyricsSearchControlDurauion"
Unit="s"
Value="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.Duration, TargetNullValue=N/A, Mode=OneWay}" />
<local:PropertyRow x:Uid="LyricsPageLanguageCode" Value="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsData.LanguageCode, TargetNullValue=N/A, Mode=OneWay, Converter={StaticResource LanguageCodeToDisplayedNameConverter}}" />
<local:PropertyRow
x:Uid="LyricsPageLyricsProviderPrefix"
Link="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.Reference, Mode=OneWay}"
@@ -397,16 +398,23 @@
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.TranslationSettings.IsLibreTranslateEnabled, Mode=TwoWay}" />
</dev:SettingsCard>
<dev:SettingsCard x:Uid="SettingsPageLibreTranslateServer" IsEnabled="{x:Bind ViewModel.AppSettings.TranslationSettings.IsLibreTranslateEnabled, Mode=OneWay}">
<StackPanel Orientation="Horizontal" Spacing="12">
<Grid ColumnSpacing="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox
x:Uid="LibreTranslateServerTextBox"
Grid.Column="0"
IsEnabled="{x:Bind ViewModel.IsLibreTranslateServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}"
Text="{x:Bind ViewModel.AppSettings.TranslationSettings.LibreTranslateServer, Mode=TwoWay}" />
Text="{x:Bind ViewModel.AppSettings.TranslationSettings.LibreTranslateServer, Mode=TwoWay}"
TextWrapping="Wrap" />
<Button
x:Uid="SettingsPageServerTestButton"
Grid.Column="1"
Command="{x:Bind ViewModel.LibreTranslateServerTestCommand}"
IsEnabled="{x:Bind ViewModel.IsLibreTranslateServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}" />
</StackPanel>
</Grid>
</dev:SettingsCard>
</dev:SettingsExpander.Items>
</dev:SettingsExpander>
@@ -424,9 +432,33 @@
</dev:SettingsCard>
</dev:SettingsExpander.Items>
</dev:SettingsExpander>
<dev:SettingsCard x:Uid="SettingsPageJapanese">
<dev:SettingsExpander x:Uid="SettingsPageJapanese" IsExpanded="{x:Bind ViewModel.AppSettings.TranslationSettings.IsJapaneseRomanizationEnabled, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.TranslationSettings.IsJapaneseRomanizationEnabled, Mode=TwoWay}" />
</dev:SettingsCard>
<dev:SettingsExpander.Items>
<dev:SettingsCard x:Uid="SettingsPageCutletDockerServer" IsEnabled="{x:Bind ViewModel.AppSettings.TranslationSettings.IsJapaneseRomanizationEnabled, Mode=OneWay}">
<dev:SettingsCard.Description>
<HyperlinkButton Content="https://github.com/jayfunc/cutlet-docker" NavigateUri="https://github.com/jayfunc/cutlet-docker" />
</dev:SettingsCard.Description>
<Grid ColumnSpacing="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox
x:Uid="CutletServerTextBox"
Grid.Column="0"
IsEnabled="{x:Bind ViewModel.IsCutletDockerServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}"
Text="{x:Bind ViewModel.AppSettings.TranslationSettings.CutletDockerServer, Mode=TwoWay}"
TextWrapping="Wrap" />
<Button
x:Uid="SettingsPageServerTestButton"
Grid.Column="1"
Command="{x:Bind ViewModel.CutletDockerServerTestCommand}"
IsEnabled="{x:Bind ViewModel.IsCutletDockerServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}" />
</Grid>
</dev:SettingsCard>
</dev:SettingsExpander.Items>
</dev:SettingsExpander>
<!-- 中文简体繁体偏好 -->
<TextBlock x:Uid="SettingsPageChineseLyrics" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />

View File

@@ -14,7 +14,6 @@
x:Name="TrayIcon"
x:FieldModifier="public"
ContextMenuMode="SecondWindow"
DoubleClickCommand="{x:Bind ViewModel.OpenLyricsWindowSwitchCommand}"
IconSource="ms-appx:///Assets/Logo.ico"
LeftClickCommand="{x:Bind ViewModel.OpenLyricsWindowSwitchCommand}"
NoLeftClickDelay="True"

View File

@@ -86,6 +86,26 @@
</dev:SettingsExpander.Items>
</dev:SettingsExpander>
<dev:SettingsExpander
x:Uid="SettingsPagePinToTaskbar"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
Glyph=&#xE7C4;}"
IsExpanded="{x:Bind LyricsWindowStatus.IsPinToTaskbar, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind LyricsWindowStatus.IsPinToTaskbar, Mode=TwoWay}" />
<dev:SettingsExpander.Items>
<dev:SettingsCard x:Uid="SettingsPageTaskbarPlacement">
<ComboBox SelectedIndex="{x:Bind LyricsWindowStatus.TaskbarPlacement, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
<ComboBoxItem x:Uid="SettingsPageLeft" />
<ComboBoxItem x:Uid="SettingsPageRight" />
</ComboBox>
</dev:SettingsCard>
</dev:SettingsExpander.Items>
</dev:SettingsExpander>
<dev:SettingsCard x:Uid="SettingsPageAlwaysHideUnlockButton" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=&#xE785;}">
<ToggleSwitch IsOn="{x:Bind LyricsWindowStatus.IsAlwaysHideUnlockButton, Mode=TwoWay}" />
</dev:SettingsCard>
<dev:SettingsExpander
x:Uid="SettingsPageAOT"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},

View File

@@ -27,6 +27,7 @@ namespace BetterLyrics.WinUI3.Converter
TransliterationSearchProvider.LocalEslrcFile => _resourceService.GetLocalizedString("LyricsSearchProviderEslrcFile"),
TransliterationSearchProvider.LocalTtmlFile => _resourceService.GetLocalizedString("LyricsSearchProviderTtmlFile"),
TransliterationSearchProvider.BetterLyrics => "BetterLyrics",
TransliterationSearchProvider.CutletDocker => "cutlet-docker",
_ => "N/A",
};
}

View File

@@ -0,0 +1,8 @@
namespace BetterLyrics.WinUI3.Enums
{
public enum TaskbarPlacement
{
Left,
Right,
}
}

View File

@@ -12,6 +12,7 @@
LocalLrcFile,
LocalEslrcFile,
LocalTtmlFile,
BetterLyrics
BetterLyrics,
CutletDocker
}
}

View File

@@ -0,0 +1,14 @@
using System;
using Windows.Foundation;
namespace BetterLyrics.WinUI3.Events
{
public class TaskbarFreeBoundsChangedEventArgs : EventArgs
{
public Rect TaskbarFreeBounds { get; }
public TaskbarFreeBoundsChangedEventArgs(Rect taskbarBounds)
{
TaskbarFreeBounds = taskbarBounds;
}
}
}

View File

@@ -22,9 +22,9 @@ namespace BetterLyrics.WinUI3.Extensions
Name = _resourceService.GetLocalizedString("DesktopMode"),
LyricsDisplayType = LyricsDisplayType.LyricsOnly,
WindowBounds = new Rect(100, 100, 600, 250),
IsLocked = true,
IsAlwaysOnTop = true,
IsAlwaysOnTopPolling = true,
IsLocked = true,
IsAdaptToEnvironment = true,
IsShownInSwitchers = false,
EnvironmentSampleMode = WindowPixelSampleMode.WindowEdge,
@@ -52,7 +52,6 @@ namespace BetterLyrics.WinUI3.Extensions
IsShownInSwitchers = false,
LyricsDisplayType = LyricsDisplayType.LyricsOnly,
EnvironmentSampleMode = WindowPixelSampleMode.BelowWindow,
TitleBarArea = TitleBarArea.None,
LyricsStyleSettings = new LyricsStyleSettings
{
LyricsAlignmentType = TextAlignmentType.Center,
@@ -108,5 +107,30 @@ namespace BetterLyrics.WinUI3.Extensions
LyricsLayoutOrientation = LyricsLayoutOrientation.Vertical,
};
}
public static LyricsWindowStatus TaskbarMode(Window? window = null)
{
window ??= WindowHook.GetWindow<SystemTrayWindow>();
return new LyricsWindowStatus(window)
{
Name = _resourceService.GetLocalizedString("TaskbarMode"),
LyricsDisplayType = LyricsDisplayType.LyricsOnly,
IsPinToTaskbar = true,
IsLocked = true,
IsAlwaysOnTop = true,
IsAlwaysOnTopPolling = true,
IsAdaptToEnvironment = true,
IsShownInSwitchers = false,
EnvironmentSampleMode = WindowPixelSampleMode.WindowEdge,
LyricsStyleSettings = new()
{
LyricsAlignmentType = TextAlignmentType.Center,
},
LyricsBackgroundSettings = new LyricsBackgroundSettings
{
IsFluidOverlayEnabled = false,
}
};
}
}
}

View File

@@ -1,4 +1,5 @@
using Windows.Foundation;
using Vanara.PInvoke;
using Windows.Foundation;
using Windows.Graphics;
namespace BetterLyrics.WinUI3.Extensions
@@ -77,5 +78,15 @@ namespace BetterLyrics.WinUI3.Extensions
);
}
}
extension(RECT rect)
{
public Rect ToRect() => new(
rect.Left,
rect.Top,
rect.Right - rect.Left,
rect.Bottom - rect.Top
);
}
}
}

View File

@@ -0,0 +1,18 @@
using System.Drawing;
using Windows.Foundation;
namespace BetterLyrics.WinUI3.Extensions
{
public static class RectangleExtensions
{
extension(Rectangle rect)
{
public Rect ToRect() => new(
rect.Left,
rect.Top,
rect.Right - rect.Left,
rect.Bottom - rect.Top
);
}
}
}

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

@@ -1,4 +1,5 @@
using Windows.Security.Credentials;
using System;
using Windows.Security.Credentials;
namespace BetterLyrics.WinUI3.Helper
{
@@ -12,23 +13,13 @@ namespace BetterLyrics.WinUI3.Helper
/// <param name="value">要保存的值</param>
public static void Save(string resource, string key, string value)
{
// 删除旧值(避免重复存储)
try
{
var vault = new PasswordVault();
var oldCredential = vault.Retrieve(resource, key);
if (oldCredential != null)
{
vault.Remove(oldCredential);
}
vault.Add(new PasswordCredential(resource, key, value));
}
catch
{
// 没有旧值就忽略
}
catch (Exception) { }
}
/// <summary>
@@ -47,7 +38,7 @@ namespace BetterLyrics.WinUI3.Helper
credential.RetrievePassword();
return credential.Password;
}
catch
catch (Exception)
{
return null;
}
@@ -65,10 +56,7 @@ namespace BetterLyrics.WinUI3.Helper
var credential = vault.Retrieve(resource, key);
vault.Remove(credential);
}
catch
{
// 不存在就忽略
}
catch (Exception) { }
}
}
}

View File

@@ -32,11 +32,6 @@ namespace BetterLyrics.WinUI3.Helper
}
}
public static string ToRomaji(string text)
{
return Kana.Kana.KanaToRomaji(text, Kana.Error.Ignore).ToStr();
}
public static string ToPinyin(string text, Pinyin.ManTone.Style style = Pinyin.ManTone.Style.TONE)
{
return Pinyin.Pinyin.Instance.HanziToPinyin(text, style).ToStr();

View File

@@ -1,24 +1,211 @@
using Microsoft.UI.Xaml;
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Events;
using BetterLyrics.WinUI3.Extensions;
using FlaUI.Core.AutomationElements;
using FlaUI.Core.Definitions;
using FlaUI.Core.EventHandlers;
using FlaUI.UIA3;
using Microsoft.UI.Dispatching;
using System;
using System.Drawing;
using System.Threading;
namespace BetterLyrics.WinUI3.Hooks
{
public class TaskbarHook
public partial class TaskbarHook : IDisposable
{
private readonly DispatcherTimer _timer;
private readonly UIA3Automation _automation;
private AutomationElement? _taskbar;
public Action<EventArgs> OnTaskbarBoundsChanged;
private StructureChangedEventHandlerBase? _structureHandler;
private PropertyChangedEventHandlerBase? _propertyHandler;
public TaskbarHook()
private TaskbarPlacement _currentPlacement;
private readonly DispatcherQueue _dispatcherQueue;
private readonly Action<TaskbarFreeBoundsChangedEventArgs> _onLayoutChanged;
private Timer? _debounceTimer;
private const int DebounceDelay = 150;
private bool _isDisposed;
public TaskbarHook(TaskbarPlacement placement, Action<TaskbarFreeBoundsChangedEventArgs> onLayoutChanged)
{
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(50);
_timer.Tick += Timer_Tick;
_automation = new UIA3Automation();
_onLayoutChanged = onLayoutChanged;
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
_currentPlacement = placement;
StartHook();
}
private void Timer_Tick(object? sender, object e)
public void UpdatePlacement(TaskbarPlacement newPlacement)
{
_currentPlacement = newPlacement;
RequestUpdate(); // 立即刷新位置
}
private void StartHook()
{
try
{
var desktop = _automation.GetDesktop();
_taskbar = desktop.FindFirstChild(cf => cf.ByClassName("Shell_TrayWnd"));
if (_taskbar == null) return;
// 监听结构变化
// 这里的返回值就是一个可以 Dispose 的对象
_structureHandler = _taskbar.RegisterStructureChangedEvent(
TreeScope.Descendants,
(element, type, id) => RequestUpdate());
// 监听属性变化
_propertyHandler = _taskbar.RegisterPropertyChangedEvent(
TreeScope.Element,
(element, id, val) => RequestUpdate(),
_automation.PropertyLibrary.Element.BoundingRectangle);
RequestUpdate();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Hook Init Failed: {ex.Message}");
}
}
private void RequestUpdate()
{
if (_isDisposed) return;
_debounceTimer?.Dispose();
_debounceTimer = new Timer(_ =>
{
Rectangle voidRect = CalculateVoidRect(_currentPlacement);
_dispatcherQueue.TryEnqueue(() =>
{
if (!_isDisposed && voidRect != Rectangle.Empty)
{
_onLayoutChanged?.Invoke(new TaskbarFreeBoundsChangedEventArgs(voidRect.ToRect()));
}
});
}, null, DebounceDelay, Timeout.Infinite);
}
private Rectangle CalculateVoidRect(TaskbarPlacement placement)
{
try
{
if (_taskbar == null) return Rectangle.Empty;
try { var _ = _taskbar.BoundingRectangle; }
catch
{
var desktop = _automation.GetDesktop();
_taskbar = desktop.FindFirstChild(cf => cf.ByClassName("Shell_TrayWnd"));
if (_taskbar == null) return Rectangle.Empty;
}
Rectangle taskbarRect = _taskbar.BoundingRectangle;
// 绝对右边界:托盘
int barrierRight = taskbarRect.Right;
var tray = _taskbar.FindFirstDescendant(cf => cf.ByAutomationId("SystemTrayIcon")); // Win11
if (tray == null) tray = _taskbar.FindFirstDescendant(cf => cf.ByClassName("TrayNotifyWnd")); // Win10
if (tray != null) barrierRight = tray.BoundingRectangle.Left;
// 绝对左边界:任务栏左边缘 或 小组件(Win11)
int barrierLeft = taskbarRect.Left;
var widgets = _taskbar.FindFirstDescendant(cf => cf.ByAutomationId("WidgetsButton"));
// 只有当小组件确实在最左侧时 (Win11默认),它才构成左边界
// 如果用户把任务栏设为靠左对齐,小组件会在开始按钮右边,这时候不把它当做左边界
if (widgets != null && widgets.BoundingRectangle.Left < taskbarRect.Left + 100)
{
barrierLeft = (int)widgets.BoundingRectangle.Right;
}
// 寻找 中间内容区域 (Start + Search + Apps) 的 左右极值
int contentMinLeft = barrierRight;
int contentMaxRight = barrierLeft;
// 定义所有中间元素
string[] systemButtonIds = new[] {
"StartButton", "SearchButton", "TaskViewButton", "ChatButton"
};
// 系统按钮
foreach (var id in systemButtonIds)
{
var btn = _taskbar.FindFirstDescendant(cf => cf.ByAutomationId(id));
if (btn != null)
{
var rect = btn.BoundingRectangle;
// 排除不可见的
if (rect.Width <= 0) continue;
// 更新极值
if (rect.Left < contentMinLeft) contentMinLeft = (int)rect.Left;
if (rect.Right > contentMaxRight) contentMaxRight = (int)rect.Right;
}
}
// App 图标
var appIcons = _taskbar.FindAllDescendants(cf => cf.ByClassName("Taskbar.TaskListButtonAutomationPeer"));
foreach (var icon in appIcons)
{
var rect = icon.BoundingRectangle;
if (rect.Width <= 0) continue;
if (rect.Left < contentMinLeft) contentMinLeft = (int)rect.Left;
if (rect.Right > contentMaxRight) contentMaxRight = (int)rect.Right;
}
// 如果完全没找到内容,重置为中间
if (contentMinLeft == barrierRight) contentMinLeft = taskbarRect.Left;
if (contentMaxRight == barrierLeft) contentMaxRight = taskbarRect.Left;
int finalLeft, finalRight;
int padding = 10;
if (placement == TaskbarPlacement.Left)
{
// 【小组件】... [空隙] ...【开始按钮】
// 如果是 Win10 或 Win11左对齐contentMinLeft 几乎等于 barrierLeft空隙为0
finalLeft = barrierLeft + padding;
finalRight = contentMinLeft - padding;
}
else // Right
{
// 【最后一个图标】... [空隙] ...【托盘】
finalLeft = contentMaxRight + padding;
finalRight = barrierRight - padding;
}
int width = finalRight - finalLeft;
if (width < 20) return Rectangle.Empty;
return new Rectangle(finalLeft, taskbarRect.Top, width, taskbarRect.Height);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Calc Rect Error: {ex.Message}");
return Rectangle.Empty;
}
}
public void Dispose()
{
if (_isDisposed) return;
_isDisposed = true;
_debounceTimer?.Dispose();
_structureHandler?.Dispose();
_propertyHandler?.Dispose();
_automation?.Dispose();
}
}
}
}

View File

@@ -23,8 +23,8 @@ namespace BetterLyrics.WinUI3.Hooks
private static List<object> _activeWindows = [];
private static List<object> _workAreas = [];
private static readonly Dictionary<HWND, WindowStyle> _defaultWindowStyle = [];
private static readonly Dictionary<HWND, ExtendedWindowStyle> _defaultExtendedWindowStyle = [];
private static WindowStyle? _defaultWindowStyle;
private static ExtendedWindowStyle? _defaultExtendedWindowStyle;
public static void HideWindow(this Window window)
{
@@ -81,9 +81,9 @@ namespace BetterLyrics.WinUI3.Hooks
{
return frameworkElement.XamlRoot.ContentIslandEnvironment.AppWindowId.GetWindowHandle();
}
else if (obj != null)
else if (obj is Window window)
{
return WindowNative.GetWindowHandle(obj);
return WindowNative.GetWindowHandle(window);
}
else
{
@@ -141,17 +141,19 @@ namespace BetterLyrics.WinUI3.Hooks
TrackWindow(window);
var castedWindow = (Window)window;
if (typeof(T) != typeof(SystemTrayWindow))
castedWindow.Restore();
castedWindow.Activate();
if (typeof(T) == typeof(SystemTrayWindow))
{
castedWindow.Restore();
castedWindow.Activate();
_defaultWindowStyle = castedWindow.GetWindowStyle();
_defaultExtendedWindowStyle = castedWindow.GetExtendedWindowStyle();
castedWindow.HideWindow();
}
if (typeof(T) == typeof(NowPlayingWindow))
{
var hwnd = WindowNative.GetWindowHandle(castedWindow);
_defaultWindowStyle.Add(hwnd, castedWindow.GetWindowStyle());
_defaultExtendedWindowStyle.Add(hwnd, castedWindow.GetExtendedWindowStyle());
var lyricsWindow = (NowPlayingWindow)window;
lyricsWindow.InitStatus();
@@ -222,14 +224,7 @@ namespace BetterLyrics.WinUI3.Hooks
private static void WindowHelper_Closed(object sender, WindowEventArgs args)
{
if (_activeWindows.Contains(sender))
{
_activeWindows.Remove(sender);
var hwnd = WindowNative.GetWindowHandle(sender);
_defaultWindowStyle.Remove(hwnd);
_defaultExtendedWindowStyle.Remove(hwnd);
}
_activeWindows.Remove(sender);
}
public static void SetIsWorkArea(this NowPlayingWindow window, bool enable)
@@ -256,9 +251,7 @@ namespace BetterLyrics.WinUI3.Hooks
public static void SetIsClickThrough(this Window window, bool enable)
{
IntPtr hwnd = WindowNative.GetWindowHandle(window);
if (_defaultExtendedWindowStyle.TryGetValue(hwnd, out var style))
if (_defaultExtendedWindowStyle is ExtendedWindowStyle style)
{
if (enable)
{
@@ -273,9 +266,7 @@ namespace BetterLyrics.WinUI3.Hooks
public static void SetIsBorderless(this Window window, bool enable)
{
var hwnd = WindowNative.GetWindowHandle(window);
if (_defaultWindowStyle.TryGetValue(hwnd, out var style))
if (_defaultWindowStyle is WindowStyle style)
{
if (enable)
{
@@ -288,23 +279,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)
{
@@ -314,10 +309,14 @@ namespace BetterLyrics.WinUI3.Hooks
{
window.Restore();
}
return true;
}
public static void SetIsShowInSwitchers(this Window window, bool enable)
{
if (window.AppWindow == null) return;
window.AppWindow.IsShownInSwitchers = enable;
}
@@ -333,6 +332,8 @@ namespace BetterLyrics.WinUI3.Hooks
public static void MoveAndResize(this Window window, Rect rect)
{
if (window.AppWindow == null) return;
window.AppWindow.Move(new Windows.Graphics.PointInt32((int)rect.X, (int)rect.Y));
window.AppWindow.Resize(new Windows.Graphics.SizeInt32((int)rect.Width, (int)rect.Height));
}

View File

@@ -92,27 +92,30 @@ namespace BetterLyrics.WinUI3.Logic
line.ScaleTransition.SetDuration(yScrollDuration);
line.ScaleTransition.SetDelay(yScrollDelay);
line.ScaleTransition.StartTransition(_highlightedScale - distanceFactor * (_highlightedScale - _defaultScale));
line.ScaleTransition.StartTransition(
lyricsEffect.IsLyricsOutOfSightEffectEnabled ?
(_highlightedScale - distanceFactor * (_highlightedScale - _defaultScale)) :
_highlightedScale);
line.PhoneticOpacityTransition.SetDuration(yScrollDuration);
line.PhoneticOpacityTransition.SetDelay(yScrollDelay);
line.PhoneticOpacityTransition.StartTransition(
absLineCountDelta == 0 ? phoneticOpacity : (isMouseScrolling ? phoneticOpacity : (1 - distanceFactor) * phoneticOpacity));
CalculateTargetOpacity(phoneticOpacity, phoneticOpacity, distanceFactor, isMouseScrolling, lyricsEffect));
line.PlayedOriginalOpacityTransition.SetDuration(yScrollDuration);
line.PlayedOriginalOpacityTransition.SetDelay(yScrollDelay);
line.PlayedOriginalOpacityTransition.StartTransition(
absLineCountDelta == 0 ? 1 : (isMouseScrolling ? 1.0 : (1 - distanceFactor) * originalOpacity));
CalculateTargetOpacity(originalOpacity, 1.0, distanceFactor, isMouseScrolling, lyricsEffect));
line.UnplayedOriginalOpacityTransition.SetDuration(yScrollDuration);
line.UnplayedOriginalOpacityTransition.SetDelay(yScrollDelay);
line.UnplayedOriginalOpacityTransition.StartTransition(
absLineCountDelta == 0 ? originalOpacity : (isMouseScrolling ? originalOpacity : (1 - distanceFactor) * originalOpacity));
CalculateTargetOpacity(originalOpacity, originalOpacity, distanceFactor, isMouseScrolling, lyricsEffect));
line.TranslatedOpacityTransition.SetDuration(yScrollDuration);
line.TranslatedOpacityTransition.SetDelay(yScrollDelay);
line.TranslatedOpacityTransition.StartTransition(
absLineCountDelta == 0 ? translatedOpacity : (isMouseScrolling ? translatedOpacity : (1 - distanceFactor) * translatedOpacity));
CalculateTargetOpacity(translatedOpacity, translatedOpacity, distanceFactor, isMouseScrolling, lyricsEffect));
line.ColorTransition.SetDuration(yScrollDuration);
line.ColorTransition.SetDelay(yScrollDelay);
@@ -143,5 +146,33 @@ namespace BetterLyrics.WinUI3.Logic
line.ColorTransition.Update(elapsedTime);
}
}
private static double CalculateTargetOpacity(double baseOpacity, double baseOpacityWhenZeroDistanceFactor, double distanceFactor, bool isMouseScrolling, LyricsEffectSettings lyricsEffect)
{
double targetOpacity;
if (distanceFactor == 0)
{
targetOpacity = baseOpacityWhenZeroDistanceFactor;
}
else
{
if (isMouseScrolling)
{
targetOpacity = baseOpacity;
}
else
{
if (lyricsEffect.IsLyricsFadeOutEffectEnabled)
{
targetOpacity = (1 - distanceFactor) * baseOpacity;
}
else
{
targetOpacity = baseOpacity;
}
}
}
return targetOpacity;
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json.Serialization;
namespace BetterLyrics.WinUI3.Models
{
public class CutletDockerRequest
{
[JsonPropertyName("text")]
public string Text { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json.Serialization;
namespace BetterLyrics.WinUI3.Models
{
public class CutletDockerResponse
{
[JsonPropertyName("romaji")]
public string RomajiText { get; set; }
}
}

View File

@@ -2,7 +2,7 @@
namespace BetterLyrics.WinUI3.Models
{
public class TranslateResponse
public class LibreTranslateResponse
{
[JsonPropertyName("translatedText")]
public string TranslatedText { get; set; }

View File

@@ -90,6 +90,24 @@ namespace BetterLyrics.WinUI3.Models
}
}
public void SetTransliteration(string transliteration)
{
List<string> transliterationArr = transliteration.Split(StringHelper.NewLine).ToList();
int i = 0;
foreach (var line in LyricsLines)
{
if (i >= transliterationArr.Count)
{
line.PhoneticText = ""; // No transliteration available, keep empty
}
else
{
line.PhoneticText = transliterationArr[i];
}
i++;
}
}
public static LyricsData GetNotfoundPlaceholder()
{
return new LyricsData([new LyricsLine

View File

@@ -22,6 +22,11 @@ namespace BetterLyrics.WinUI3.Models
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsAlwaysOnTopPolling { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsShownInSwitchers { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLocked { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsAlwaysHideUnlockButton { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsPinToTaskbar { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TaskbarPlacement TaskbarPlacement { get; set; } = TaskbarPlacement.Right;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsMaximized { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsFullscreen { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsLayoutOrientation LyricsLayoutOrientation { get; set; } = LyricsLayoutOrientation.Horizontal;
@@ -48,15 +53,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();
@@ -137,6 +201,11 @@ namespace BetterLyrics.WinUI3.Models
IsAlwaysOnTopPolling = this.IsAlwaysOnTopPolling,
IsShownInSwitchers = this.IsShownInSwitchers,
IsLocked = this.IsLocked,
IsAlwaysHideUnlockButton = this.IsAlwaysHideUnlockButton,
IsPinToTaskbar = this.IsPinToTaskbar,
TaskbarPlacement = this.TaskbarPlacement,
IsMaximized = this.IsMaximized,
IsFullscreen = this.IsFullscreen,

View File

@@ -12,6 +12,11 @@ namespace BetterLyrics.WinUI3.Models.Settings
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsPureColorOverlayEnabled { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int PureColorOverlayOpacity { get; set; } = 100; // 100 % = 1.0
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsCoverOverlayEnabled { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int CoverOverlayOpacity { get; set; } = 100; // 100 % = 1.0
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int CoverOverlaySpeed { get; set; } = 50;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int CoverOverlayBlurAmount { get; set; } = 100;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsFluidOverlayEnabled { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int FluidOverlayOpacity { get; set; } = 100;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial PaletteGeneratorType PaletteGeneratorType { get; set; } = PaletteGeneratorType.MedianCut;
@@ -39,14 +44,25 @@ namespace BetterLyrics.WinUI3.Models.Settings
IsPureColorOverlayEnabled = this.IsPureColorOverlayEnabled,
PureColorOverlayOpacity = this.PureColorOverlayOpacity,
IsCoverOverlayEnabled = this.IsCoverOverlayEnabled,
CoverOverlayOpacity = this.CoverOverlayOpacity,
CoverOverlaySpeed = this.CoverOverlaySpeed,
CoverOverlayBlurAmount = this.CoverOverlayBlurAmount,
IsFluidOverlayEnabled = this.IsFluidOverlayEnabled,
FluidOverlayOpacity = this.FluidOverlayOpacity,
PaletteGeneratorType = this.PaletteGeneratorType,
IsSpectrumOverlayEnabled = this.IsSpectrumOverlayEnabled,
SpectrumPlacement = this.SpectrumPlacement,
SpectrumStyle = this.SpectrumStyle,
SpectrumCount = this.SpectrumCount,
IsSnowFlakeOverlayEnabled = this.IsSnowFlakeOverlayEnabled,
SnowFlakeOverlayAmount = this.SnowFlakeOverlayAmount,
SnowFlakeOverlaySpeed = this.SnowFlakeOverlaySpeed,
IsFogOverlayEnabled = this.IsFogOverlayEnabled,
};
}
}

View File

@@ -7,6 +7,8 @@ namespace BetterLyrics.WinUI3.Models.Settings
public partial class LyricsEffectSettings : ObservableRecipient, ICloneable
{
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsBlurEffectEnabled { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsFadeOutEffectEnabled { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsOutOfSightEffectEnabled { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsGlowEffectEnabled { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsEffectScope LyricsGlowEffectScope { get; set; } = LyricsEffectScope.LongDurationSyllable;
@@ -52,11 +54,14 @@ namespace BetterLyrics.WinUI3.Models.Settings
return new LyricsEffectSettings(this.LyricsScrollTopDuration, this.LyricsScrollDuration, this.LyricsScrollBottomDuration, this.LyricsScrollEasingType)
{
IsLyricsBlurEffectEnabled = this.IsLyricsBlurEffectEnabled,
IsLyricsFadeOutEffectEnabled = this.IsLyricsFadeOutEffectEnabled,
IsLyricsOutOfSightEffectEnabled = this.IsLyricsOutOfSightEffectEnabled,
IsLyricsGlowEffectEnabled = this.IsLyricsGlowEffectEnabled,
LyricsGlowEffectLongSyllableDuration = this.LyricsGlowEffectLongSyllableDuration,
IsLyricsGlowEffectAmountAutoAdjust = this.IsLyricsGlowEffectAmountAutoAdjust,
LyricsGlowEffectAmount = this.LyricsGlowEffectAmount,
LyricsGlowEffectScope = this.LyricsGlowEffectScope,
IsLyricsScaleEffectEnabled = this.IsLyricsScaleEffectEnabled,
LyricsScaleEffectLongSyllableDuration = this.LyricsScaleEffectLongSyllableDuration,

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

@@ -13,6 +13,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool AutoPlay { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsWindowStatus LyricsWindowStatus { get; set; } = new();
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ExitOnWindowClosed { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool StopOnWindowClosed { get; set; } = false;
public MusicGallerySettings() { }
}

View File

@@ -13,6 +13,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
[ObservableProperty][NotifyPropertyChangedRecipients] public partial ChineseRomanization ChineseRomanization { get; set; }
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsChineseRomanizationEnabled { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsJapaneseRomanizationEnabled { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string CutletDockerServer { get; set; } = string.Empty;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsTraditionalChineseEnabled { get; set; } = false;
public TranslationSettings() { }

View File

@@ -5,7 +5,8 @@ using BetterLyrics.WinUI3.Extensions;
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
using BetterLyrics.WinUI3.Models.Settings;
using BetterLyrics.WinUI3.Services.TranslateService;
using BetterLyrics.WinUI3.Services.TranslationService;
using BetterLyrics.WinUI3.Services.TransliterationService;
using CommunityToolkit.Mvvm.DependencyInjection;
using Lyricify.Lyrics.Helpers.General;
using Lyricify.Lyrics.Parsers;
@@ -70,7 +71,13 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
return _lyricsDataArr;
}
public async Task<(LyricsData, TransliterationSearchProvider?, TranslationSearchProvider?)> Parse(ITranslateService translateService, TranslationSettings settings, LyricsSearchResult? lyricsSearchResult, CancellationToken token)
public async Task<(LyricsData, TransliterationSearchProvider?, TranslationSearchProvider?)> Parse(
ITranslationService translationService,
ITransliterationService transliterationService,
TranslationSettings settings,
LyricsSearchResult? lyricsSearchResult,
CancellationToken token
)
{
TransliterationSearchProvider? transliterationSearchProvider = null;
TranslationSearchProvider? translationSearchProvider = null;
@@ -81,6 +88,7 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
// 应用音译
LyricsData? phoneticLyricsData = null;
// 已解析歌词内寻找
if (settings.IsChineseRomanizationEnabled && main.LanguageCode == LanguageHelper.ChineseCode)
{
phoneticLyricsData = settings.ChineseRomanization switch
@@ -89,21 +97,41 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
ChineseRomanization.Jyutping => _lyricsDataArr.FirstOrDefault(x => x.LanguageCode == PhoneticHelper.JyutpingCode),
_ => null,
};
if (phoneticLyricsData != null)
{
main.SetPhoneticText(phoneticLyricsData);
if (phoneticLyricsData.AutoGenerated)
{
transliterationSearchProvider = TransliterationSearchProvider.BetterLyrics;
}
else
{
transliterationSearchProvider = lyricsSearchResult?.Provider.ToTransliterationSearchProvider();
}
}
}
else if (settings.IsJapaneseRomanizationEnabled && main.LanguageCode == LanguageHelper.JapaneseCode)
{
phoneticLyricsData = _lyricsDataArr.FirstOrDefault(x => x.LanguageCode == PhoneticHelper.RomanCode);
}
if (phoneticLyricsData != null)
{
main.SetPhoneticText(phoneticLyricsData);
if (phoneticLyricsData.AutoGenerated)
if (phoneticLyricsData != null)
{
transliterationSearchProvider = TransliterationSearchProvider.BetterLyrics;
main.SetPhoneticText(phoneticLyricsData);
transliterationSearchProvider = lyricsSearchResult?.Provider.ToTransliterationSearchProvider();
}
else
{
transliterationSearchProvider = lyricsSearchResult?.Provider.ToTransliterationSearchProvider();
string romaji = string.Empty;
try
{
romaji = await transliterationService.TransliterateText(main.WrappedOriginalText, PhoneticHelper.RomanCode, token);
_lyricsDataArr.FirstOrDefault()?.SetTransliteration(romaji);
transliterationSearchProvider = TransliterationSearchProvider.CutletDocker;
}
catch (TaskCanceledException) { }
catch (Exception)
{
ToastHelper.ShowToast("CutletDockerFailed", null, InfoBarSeverity.Error);
}
}
}
@@ -121,7 +149,7 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
string translated = string.Empty;
try
{
translated = await translateService.TranslateTextAsync(main.WrappedOriginalText, settings.SelectedTargetLanguageCode, token);
translated = await translationService.TranslateTextAsync(main.WrappedOriginalText, settings.SelectedTargetLanguageCode, token);
_lyricsDataArr.FirstOrDefault()?.SetTranslation(translated);
translationSearchProvider = TranslationSearchProvider.LibreTranslate;
}
@@ -239,30 +267,6 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
});
}
}
else if (languageCode == LanguageHelper.JapaneseCode)
{
if (!_lyricsDataArr.Any(x => x.LanguageCode == PhoneticHelper.RomanCode))
{
_lyricsDataArr.Add(new LyricsData
{
LanguageCode = PhoneticHelper.RomanCode,
AutoGenerated = true,
LyricsLines = main.LyricsLines.Select(line => new LyricsLine
{
StartMs = line.StartMs,
EndMs = line.EndMs,
OriginalText = PhoneticHelper.ToRomaji(line.OriginalText),
LyricsSyllables = line.LyricsSyllables.Select(c => new LyricsSyllable
{
StartMs = c.StartMs,
EndMs = c.EndMs,
Text = PhoneticHelper.ToRomaji(c.Text),
StartIndex = c.StartIndex
}).ToList()
}).ToList()
});
}
}
}
}

View File

@@ -0,0 +1,249 @@
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Helper;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using System.Numerics;
using Windows.Foundation;
namespace BetterLyrics.WinUI3.Renderer
{
public partial class CoverBackgroundRenderer : IDisposable
{
private CanvasBitmap? _currentBitmap;
private CanvasBitmap? _previousBitmap;
private CanvasRenderTarget? _currentTargetCache;
private CanvasRenderTarget? _previousTargetCache;
private Size _lastScreenSize;
private bool _lastWasRotating = false;
private readonly ValueTransition<double> _crossfadeTransition;
private float _rotationAngle = 0f;
public bool IsEnabled { get; set; } = false;
public int Opacity { get; set; } = 100;
private bool _needsCacheUpdate = false;
private int _blurAmount = 100;
public int BlurAmount
{
get => _blurAmount;
set
{
if (_blurAmount != value)
{
_blurAmount = value;
_needsCacheUpdate = true;
}
}
}
private int _speed = 100;
public int Speed
{
get => _speed;
set
{
if (_speed != value)
{
_speed = value;
_needsCacheUpdate = true;
}
}
}
public CoverBackgroundRenderer()
{
_crossfadeTransition = new ValueTransition<double>(1.0, 0.7, easingType: EasingType.Linear);
}
public void SetCoverBitmap(CanvasBitmap? newBitmap)
{
if (_currentBitmap == newBitmap) return;
_previousBitmap = _currentBitmap;
_previousTargetCache = _currentTargetCache;
_currentTargetCache = null;
_currentBitmap = newBitmap;
if (_currentBitmap == null)
{
_crossfadeTransition.StartTransition(1.0, jumpTo: true);
}
else
{
if (_previousBitmap == null)
{
_crossfadeTransition.StartTransition(1.0, jumpTo: true);
}
else
{
_crossfadeTransition.Reset(0.0);
_crossfadeTransition.StartTransition(1.0);
}
}
_needsCacheUpdate = true;
}
public void Update(TimeSpan deltaTime)
{
if (!IsEnabled) return;
_crossfadeTransition.Update(deltaTime);
if (Speed > 0)
{
float baseSpeed = 0.6f;
float currentSpeed = (Speed / 100.0f) * baseSpeed;
_rotationAngle += currentSpeed * (float)deltaTime.TotalSeconds;
_rotationAngle %= (float)(2 * Math.PI);
}
if (_crossfadeTransition.Value >= 1.0 && _previousBitmap != null)
{
_previousBitmap = null;
_previousTargetCache?.Dispose();
_previousTargetCache = null;
}
}
public void Draw(ICanvasAnimatedControl control, CanvasDrawingSession ds)
{
if (!IsEnabled || Opacity <= 0) return;
if (_lastScreenSize != control.Size)
{
_lastScreenSize = control.Size;
_needsCacheUpdate = true;
}
bool isRotating = Speed > 0;
if (_lastWasRotating != isRotating)
{
_lastWasRotating = isRotating;
_needsCacheUpdate = true;
}
EnsureCachedLayer(control, _currentBitmap, ref _currentTargetCache);
float baseAlpha = Opacity / 100.0f;
float angle = isRotating ? _rotationAngle : 0f;
double fadeProgress = _crossfadeTransition.Value;
bool isCrossfading = fadeProgress < 1.0 && _previousTargetCache != null;
Vector2 screenCenter = new Vector2((float)control.Size.Width / 2f, (float)control.Size.Height / 2f);
if (isCrossfading)
{
DrawCachedLayer(ds, _previousTargetCache, screenCenter, angle, baseAlpha);
float newLayerAlpha = baseAlpha * (float)fadeProgress;
DrawCachedLayer(ds, _currentTargetCache, screenCenter, angle, newLayerAlpha);
}
else if (_currentTargetCache != null)
{
DrawCachedLayer(ds, _currentTargetCache, screenCenter, angle, baseAlpha);
}
}
private void EnsureCachedLayer(ICanvasResourceCreator resourceCreator, CanvasBitmap? sourceBitmap, ref CanvasRenderTarget? targetCache)
{
if (sourceBitmap == null)
{
targetCache?.Dispose();
targetCache = null;
return;
}
bool deviceMismatch = targetCache != null && targetCache.Device != resourceCreator.Device;
if (_needsCacheUpdate || targetCache == null || deviceMismatch)
{
targetCache?.Dispose();
float imgW = sourceBitmap.SizeInPixels.Width;
float imgH = sourceBitmap.SizeInPixels.Height;
Size screenSize = _lastScreenSize;
float scale;
if (_lastWasRotating) // Speed > 0
{
float screenDiagonal = (float)Math.Sqrt(screenSize.Width * screenSize.Width + screenSize.Height * screenSize.Height);
scale = Math.Max(screenDiagonal / imgW, screenDiagonal / imgH);
}
else
{
float scaleX = (float)screenSize.Width / imgW;
float scaleY = (float)screenSize.Height / imgH;
scale = Math.Max(scaleX, scaleY);
}
float targetW = imgW * scale;
float targetH = imgH * scale;
targetCache = new CanvasRenderTarget(resourceCreator, targetW, targetH, sourceBitmap.Dpi);
using (var ds = targetCache.CreateDrawingSession())
{
ds.Clear(Windows.UI.Color.FromArgb(0, 0, 0, 0));
using (var transformEffect = new Transform2DEffect())
using (var blurEffect = new GaussianBlurEffect())
{
transformEffect.Source = sourceBitmap;
transformEffect.TransformMatrix = Matrix3x2.CreateScale(scale);
transformEffect.InterpolationMode = CanvasImageInterpolation.Linear;
blurEffect.Source = transformEffect;
blurEffect.BlurAmount = BlurAmount;
blurEffect.BorderMode = EffectBorderMode.Hard;
ds.DrawImage(blurEffect);
}
}
if (sourceBitmap == _currentBitmap)
{
_needsCacheUpdate = false;
}
}
}
private void DrawCachedLayer(CanvasDrawingSession ds, CanvasRenderTarget? cachedTexture, Vector2 screenCenter, float rotationRadians, float alpha)
{
if (cachedTexture == null) return;
Vector2 textureCenter = new Vector2((float)cachedTexture.Size.Width / 2f, (float)cachedTexture.Size.Height / 2f);
Matrix3x2 transform =
Matrix3x2.CreateTranslation(-textureCenter) * Matrix3x2.CreateRotation(rotationRadians) * Matrix3x2.CreateTranslation(screenCenter);
Matrix3x2 previousTransform = ds.Transform;
ds.Transform = transform * previousTransform;
ds.DrawImage(cachedTexture, 0, 0, new Rect(0, 0, cachedTexture.Size.Width, cachedTexture.Size.Height), alpha);
ds.Transform = previousTransform;
}
public void Dispose()
{
_currentBitmap?.Dispose();
_previousBitmap?.Dispose();
_currentTargetCache?.Dispose();
_previousTargetCache?.Dispose();
_currentBitmap = null;
_previousBitmap = null;
_currentTargetCache = null;
_previousTargetCache = null;
}
}
}

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

@@ -7,7 +7,9 @@ using System.Text.Json.Serialization;
namespace BetterLyrics.WinUI3.Serialization
{
[JsonSerializable(typeof(TranslateResponse))]
[JsonSerializable(typeof(LibreTranslateResponse))]
[JsonSerializable(typeof(CutletDockerRequest))]
[JsonSerializable(typeof(CutletDockerResponse))]
[JsonSerializable(typeof(JsonElement))]
[JsonSerializable(typeof(AppSettings))]
[JsonSerializable(typeof(LyricsSearchResult))]

View File

@@ -5,7 +5,7 @@ using Microsoft.UI.Xaml.Media.Imaging;
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Storage.Streams;
using Windows.UI;
namespace BetterLyrics.WinUI3.Services.MediaSessionsService
@@ -29,6 +29,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
LyricsData? CurrentLyricsData { get; }
BitmapImage? AlbumArtBitmapImage { get; }
IRandomAccessStream? AlbumArtBitmapStream { get; }
AlbumArtThemeColors CalculateAlbumArtThemeColors(LyricsWindowStatus lyricsWindowStatus, Color backdropAccentColor);

View File

@@ -12,7 +12,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Vanara.PInvoke;
using Windows.Graphics.Imaging;
using Windows.Storage.Streams;
using Windows.UI;
@@ -22,15 +21,16 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
public partial class MediaSessionsService : IMediaSessionsService
{
private readonly LatestOnlyTaskRunner _albumArtRefreshRunner = new();
private List<Color> _lightAccentColorsMedianCut = Enumerable.Repeat(Colors.Black, 4).ToList();
private List<Color> _darkAccentColorsMedianCut = Enumerable.Repeat(Colors.Black, 4).ToList();
private List<Color> _lightAccentColorsOctTree = Enumerable.Repeat(Colors.Black, 4).ToList();
private List<Color> _darkAccentColorsOctTree = Enumerable.Repeat(Colors.Black, 4).ToList();
private BitmapDecoder? _albumArtBitmapDecoder = null;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial BitmapImage? AlbumArtBitmapImage { get; set; }
[ObservableProperty][NotifyPropertyChangedRecipients] public partial IRandomAccessStream? AlbumArtBitmapStream { get; set; }
private void UpdateAlbumArt()
{
@@ -63,16 +63,16 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
_albumArtBitmapDecoder = await ImageHelper.GetBitmapDecoder(buffer);
if (token.IsCancellationRequested) return;
_lightAccentColorsMedianCut =
_lightAccentColorsMedianCut =
(await ImageHelper.GetAccentColorsAsync(_albumArtBitmapDecoder, 4, PaletteGeneratorType.MedianCut, false))
.Palette.Select(Helper.ColorHelper.FromVector3).ToList();
_darkAccentColorsMedianCut =
_darkAccentColorsMedianCut =
(await ImageHelper.GetAccentColorsAsync(_albumArtBitmapDecoder, 4, PaletteGeneratorType.MedianCut, true))
.Palette.Select(Helper.ColorHelper.FromVector3).ToList();
_lightAccentColorsOctTree =
_lightAccentColorsOctTree =
(await ImageHelper.GetAccentColorsAsync(_albumArtBitmapDecoder, 4, PaletteGeneratorType.OctTree, false))
.Palette.Select(Helper.ColorHelper.FromVector3).ToList();
_darkAccentColorsOctTree =
_darkAccentColorsOctTree =
(await ImageHelper.GetAccentColorsAsync(_albumArtBitmapDecoder, 4, PaletteGeneratorType.OctTree, true))
.Palette.Select(Helper.ColorHelper.FromVector3).ToList();
@@ -81,6 +81,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
if (token.IsCancellationRequested) return;
AlbumArtBitmapImage = bitmapImage;
AlbumArtBitmapStream = ImageHelper.ToIRandomAccessStream(buffer);
}
public AlbumArtThemeColors CalculateAlbumArtThemeColors(LyricsWindowStatus lyricsWindowStatus, Color backdropAccentColor)

View File

@@ -40,7 +40,8 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
(CurrentLyricsData, CurrentLyricsSearchResult.TransliterationProvider, CurrentLyricsSearchResult.TranslationProvider) =
await Task.Run(async () => await lyricsParser.Parse(
_translateService,
_translationService,
_transliterationService,
_settingsService.AppSettings.TranslationSettings,
CurrentLyricsSearchResult,
token),

View File

@@ -14,7 +14,8 @@ using BetterLyrics.WinUI3.Services.DiscordService;
using BetterLyrics.WinUI3.Services.LibWatcherService;
using BetterLyrics.WinUI3.Services.LyricsSearchService;
using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.Services.TranslateService;
using BetterLyrics.WinUI3.Services.TranslationService;
using BetterLyrics.WinUI3.Services.TransliterationService;
using BetterLyrics.WinUI3.ViewModels;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.ComponentModel;
@@ -48,7 +49,8 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
private readonly IAlbumArtSearchService _albumArtSearchService;
private readonly ILyricsSearchService _lyrcsSearchService;
private readonly ITranslateService _translateService;
private readonly ITranslationService _translationService;
private readonly ITransliterationService _transliterationService;
private readonly ISettingsService _settingsService;
private readonly ILibWatcherService _libWatcherService;
private readonly IDiscordService _discordService;
@@ -71,14 +73,16 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
ILyricsSearchService lyricsSearchService,
ILibWatcherService libWatcherService,
IDiscordService discordService,
ITranslateService libreTranslateService,
ITranslationService libreTranslateService,
ITransliterationService transliterationService,
ILogger<MediaSessionsService> logger)
{
_settingsService = settingsService;
_albumArtSearchService = albumArtSearchService;
_lyrcsSearchService = lyricsSearchService;
_libWatcherService = libWatcherService;
_translateService = libreTranslateService;
_translationService = libreTranslateService;
_transliterationService = transliterationService;
_discordService = discordService;
_logger = logger;
@@ -201,28 +205,32 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
private void MediaManager_OnAnyTimelinePropertyChanged(MediaManager.MediaSession? mediaSession, GlobalSystemMediaTransportControlsSessionTimelineProperties? timelineProperties)
{
if (!_mediaManager.IsStarted) return;
if (mediaSession == null)
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
CurrentPosition = TimeSpan.Zero;
return;
}
var desiredSession = GetCurrentSession();
if (mediaSession != desiredSession) return;
if (!IsMediaSourceEnabled(mediaSession.Id))
{
CurrentPosition = TimeSpan.Zero;
}
else
{
if (IsMediaSourceTimelineSyncEnabled(mediaSession.Id))
if (!_mediaManager.IsStarted) return;
if (mediaSession == null)
{
CurrentPosition = timelineProperties?.Position ?? TimeSpan.Zero;
CurrentPosition = TimeSpan.Zero;
return;
}
}
var desiredSession = GetCurrentSession();
if (mediaSession != desiredSession) return;
if (!IsMediaSourceEnabled(mediaSession.Id))
{
CurrentPosition = TimeSpan.Zero;
}
else
{
if (IsMediaSourceTimelineSyncEnabled(mediaSession.Id))
{
CurrentPosition = timelineProperties?.Position ?? TimeSpan.Zero;
CurrentSongInfo?.DurationMs = timelineProperties?.EndTime.TotalMilliseconds ?? 0;
}
}
});
}
private void MediaManager_OnAnyPlaybackStateChanged(MediaManager.MediaSession? mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo? playbackInfo)
@@ -696,8 +704,15 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
_logger.LogInformation("Target LibreTranslate language code changed: {code}", _settingsService.AppSettings.TranslationSettings.SelectedTargetLanguageCode);
UpdateLyrics();
}
else if (message.PropertyName == nameof(TranslationSettings.CutletDockerServer))
{
UpdateLyrics();
}
else if (message.PropertyName == nameof(TranslationSettings.LibreTranslateServer))
{
UpdateLyrics();
}
}
}
public void Receive(PropertyChangedMessage<ChineseRomanization> message)

View File

@@ -3,12 +3,10 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace BetterLyrics.WinUI3.Services.TranslateService
namespace BetterLyrics.WinUI3.Services.TranslationService
{
public interface ITranslateService
public interface ITranslationService
{
Task<string> TranslateTextAsync(string text, string targetLangCode, CancellationToken token);
int SearchTranslatedLyricsItself(List<LyricsData> lyricsDataArr, string targetLangCode);
}
}

View File

@@ -9,14 +9,14 @@ using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace BetterLyrics.WinUI3.Services.TranslateService
namespace BetterLyrics.WinUI3.Services.TranslationService
{
public partial class TranslateService : BaseViewModel, ITranslateService
public partial class TranslationService : BaseViewModel, ITranslationService
{
private readonly ISettingsService _settingsService;
private readonly HttpClient _httpClient;
public TranslateService(ISettingsService settingsService)
public TranslationService(ISettingsService settingsService)
{
_settingsService = settingsService;
_httpClient = new HttpClient();
@@ -51,31 +51,8 @@ namespace BetterLyrics.WinUI3.Services.TranslateService
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync(token);
var result = System.Text.Json.JsonSerializer.Deserialize(json, SourceGenerationContext.Default.TranslateResponse);
var result = System.Text.Json.JsonSerializer.Deserialize(json, SourceGenerationContext.Default.LibreTranslateResponse);
return result?.TranslatedText ?? string.Empty;
}
public int SearchTranslatedLyricsItself(List<LyricsData> lyricsDataArr, string targetLangCode)
{
int ret = -1;
float maxTranslatinRate = 0.0f;
if (lyricsDataArr.Count > 1)
{
for (int i = 1; i < lyricsDataArr.Count; i++)
{
if (lyricsDataArr[i].LanguageCode == targetLangCode)
{
float translationRate = lyricsDataArr[i].LyricsLines.Count / (float)lyricsDataArr[0].LyricsLines.Count;
if (translationRate > maxTranslatinRate)
{
maxTranslatinRate = translationRate;
ret = i;
}
}
}
}
return ret;
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace BetterLyrics.WinUI3.Services.TransliterationService
{
public interface ITransliterationService
{
Task<string> TransliterateText(string text, string targetLangCode, CancellationToken token);
}
}

View File

@@ -0,0 +1,52 @@
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
using BetterLyrics.WinUI3.Serialization;
using BetterLyrics.WinUI3.Services.SettingsService;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Vanara.PInvoke;
namespace BetterLyrics.WinUI3.Services.TransliterationService
{
public class TransliterationService : ITransliterationService
{
private readonly ISettingsService _settingsService;
private readonly HttpClient _httpClient;
public TransliterationService(ISettingsService settingsService)
{
_settingsService = settingsService;
_httpClient = new HttpClient();
}
public async Task<string> TransliterateText(string text, string targetLangCode, CancellationToken token)
{
if (string.IsNullOrWhiteSpace(text))
{
throw new Exception(text + " is empty or null.");
}
if (string.IsNullOrEmpty(_settingsService.AppSettings.TranslationSettings.CutletDockerServer))
{
throw new Exception("cutlet-docker server URL is not set in settings.");
}
var request = new CutletDockerRequest { Text = text };
var reqJson = System.Text.Json.JsonSerializer.Serialize(request, SourceGenerationContext.Default.CutletDockerRequest);
var url = $"{_settingsService.AppSettings.TranslationSettings.CutletDockerServer}/convert";
var response = await _httpClient.PostAsync(url, new StringContent(reqJson, Encoding.UTF8, "application/json"));
response.EnsureSuccessStatusCode();
var resJson = await response.Content.ReadAsStringAsync(token);
var result = System.Text.Json.JsonSerializer.Deserialize(resJson, SourceGenerationContext.Default.CutletDockerResponse);
return result?.RomajiText ?? string.Empty;
}
}
}

View File

@@ -150,6 +150,12 @@
<data name="CreatePlaylistSuccessfully" xml:space="preserve">
<value>Playlist was created successfully</value>
</data>
<data name="CutletDockerFailed" xml:space="preserve">
<value>Failed to request transliteration from cutlet-docker, please check settings or native cutlet-docker configuration</value>
</data>
<data name="CutletServerTextBox.PlaceholderText" xml:space="preserve">
<value>For example http://localhost:23333</value>
</data>
<data name="DemoWindowControlDefault.Text" xml:space="preserve">
<value>Default</value>
</data>
@@ -237,6 +243,9 @@
<data name="LyricsPageCachePath.Value" xml:space="preserve">
<value>Cache path</value>
</data>
<data name="LyricsPageLanguageCode.Header" xml:space="preserve">
<value>Lyric language</value>
</data>
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
<value>Lyrics provider</value>
</data>
@@ -544,7 +553,7 @@
<value>Contributors</value>
</data>
<data name="SetingsPageDeps.Text" xml:space="preserve">
<value>Dependent package</value>
<value>Code Reference</value>
</data>
<data name="SetingsPageDonation.Text" xml:space="preserve">
<value>Donation</value>
@@ -555,9 +564,15 @@
<data name="SetingsPageInstructions.Text" xml:space="preserve">
<value>Instructions</value>
</data>
<data name="SetingsPageSpecialThanks.Text" xml:space="preserve">
<value>Special Thanks</value>
</data>
<data name="SetingsPageThanks.Text" xml:space="preserve">
<value>If you like this project, please consider supporting it by donating. Your support will help keep the project alive and encourage further development.</value>
</data>
<data name="SetingsPageUIUXRef.Text" xml:space="preserve">
<value>UI/UX Design Reference</value>
</data>
<data name="SettingsPage3DLyrics.Header" xml:space="preserve">
<value>[Experimental] Depth effect</value>
</data>
@@ -624,6 +639,9 @@
<data name="SettingsPageAlignment.Header" xml:space="preserve">
<value>Alignment</value>
</data>
<data name="SettingsPageAlwaysHideUnlockButton.Header" xml:space="preserve">
<value>Always hide unlock button</value>
</data>
<data name="SettingsPageAmllTtmlDbBaseUrl.Header" xml:space="preserve">
<value>Base URL</value>
</data>
@@ -675,6 +693,9 @@
<data name="SettingsPageBackgroundOverlay.Text" xml:space="preserve">
<value>Lyrics background</value>
</data>
<data name="SettingsPageBlurAmount.Header" xml:space="preserve">
<value>Blur amount</value>
</data>
<data name="SettingsPageBorderless.Header" xml:space="preserve">
<value>Borderless window</value>
</data>
@@ -750,6 +771,9 @@
<data name="SettingsPageCurrentLyricsWindowStatus.Text" xml:space="preserve">
<value>Current lyrics window status</value>
</data>
<data name="SettingsPageCutletDockerServer.Header" xml:space="preserve">
<value>cutlet-docker transliteration service</value>
</data>
<data name="SettingsPageDark.Content" xml:space="preserve">
<value>Dark</value>
</data>
@@ -945,6 +969,9 @@
<data name="SettingsPageJA.Content" xml:space="preserve">
<value>日本語</value>
</data>
<data name="SettingsPageJapanese.Description" xml:space="preserve">
<value>The transliteration of the lyrics will be read first, and if there is no match, the machine transliteration will be requested from the cutlet-docker server</value>
</data>
<data name="SettingsPageJapanese.Header" xml:space="preserve">
<value>Japanese annotation</value>
</data>
@@ -1068,6 +1095,12 @@
<data name="SettingsPageLyricsExtraLight.Content" xml:space="preserve">
<value>Extra Light</value>
</data>
<data name="SettingsPageLyricsFadeOutEffect.Description" xml:space="preserve">
<value>Enable fade effect for non-current rows</value>
</data>
<data name="SettingsPageLyricsFadeOutEffect.Header" xml:space="preserve">
<value>Fadeout effect</value>
</data>
<data name="SettingsPageLyricsFgFontColor.Header" xml:space="preserve">
<value>Current Play Row</value>
</data>
@@ -1137,6 +1170,12 @@
<data name="SettingsPageLyricsOpacity.Header" xml:space="preserve">
<value>Font opacity</value>
</data>
<data name="SettingsPageLyricsOutOfSightEffect.Description" xml:space="preserve">
<value>Gradually move non-current rows out of view</value>
</data>
<data name="SettingsPageLyricsOutOfSightEffect.Header" xml:space="preserve">
<value>Stay out of sight</value>
</data>
<data name="SettingsPageLyricsRowFactor.Header" xml:space="preserve">
<value>Lyrics area height factor</value>
</data>
@@ -1297,7 +1336,7 @@
<value>The path cannot be found on your computer</value>
</data>
<data name="SettingsPagePatrons.Text" xml:space="preserve">
<value>Special Thanks</value>
<value>Sponsor</value>
</data>
<data name="SettingsPagePhonetic.Text" xml:space="preserve">
<value>Lyric annotation</value>
@@ -1305,6 +1344,9 @@
<data name="SettingsPagePhoneticText.Header" xml:space="preserve">
<value>Phonetic symbols</value>
</data>
<data name="SettingsPagePinToTaskbar.Header" xml:space="preserve">
<value>Pin to taskbar</value>
</data>
<data name="SettingsPagePinyin.Content" xml:space="preserve">
<value>Pinyin of Mandarin</value>
</data>
@@ -1497,6 +1539,9 @@
<data name="SettingsPageStartup.Text" xml:space="preserve">
<value>Start</value>
</data>
<data name="SettingsPageStopTrackOnGalleryWindowClosed.Header" xml:space="preserve">
<value>Stop playing when music library is closed</value>
</data>
<data name="SettingsPageStrokeFontColor.Header" xml:space="preserve">
<value>Stroke color</value>
</data>
@@ -1506,6 +1551,12 @@
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
<value>Target language</value>
</data>
<data name="SettingsPageTaskbarMode.Text" xml:space="preserve">
<value>Taskbar mode</value>
</data>
<data name="SettingsPageTaskbarPlacement.Header" xml:space="preserve">
<value>Taskbar fixed position</value>
</data>
<data name="SettingsPageTC.Content" xml:space="preserve">
<value>繁體中文</value>
</data>
@@ -1563,6 +1614,9 @@
<data name="SettingsPageTransparent.Content" xml:space="preserve">
<value>Transparent</value>
</data>
<data name="SettingsPageUserWhoPurchased.Text" xml:space="preserve">
<value>And buy users who support BetterLyrics</value>
</data>
<data name="SettingsPageVersion.Text" xml:space="preserve">
<value>Version</value>
</data>
@@ -1620,6 +1674,9 @@
<data name="SystemTraySwitch.Text" xml:space="preserve">
<value>Lyrics window switcher</value>
</data>
<data name="TaskbarMode" xml:space="preserve">
<value>Taskbar mode</value>
</data>
<data name="TermsOfService.Content" xml:space="preserve">
<value>Terms of service</value>
</data>

View File

@@ -150,6 +150,12 @@
<data name="CreatePlaylistSuccessfully" xml:space="preserve">
<value>正常に作成されました</value>
</data>
<data name="CutletDockerFailed" xml:space="preserve">
<value>cutlet - dockerからの音訳のリクエストに失敗しました。設定またはネイティブのcutlet - docker設定を確認してください</value>
</data>
<data name="CutletServerTextBox.PlaceholderText" xml:space="preserve">
<value>たとえば、http://localhost:23333</value>
</data>
<data name="DemoWindowControlDefault.Text" xml:space="preserve">
<value>デフォルト</value>
</data>
@@ -237,6 +243,9 @@
<data name="LyricsPageCachePath.Value" xml:space="preserve">
<value>キャッシュパス</value>
</data>
<data name="LyricsPageLanguageCode.Header" xml:space="preserve">
<value>リリックランゲージ</value>
</data>
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
<value>歌詞プロバイダー</value>
</data>
@@ -544,7 +553,7 @@
<value>投稿者</value>
</data>
<data name="SetingsPageDeps.Text" xml:space="preserve">
<value>依存パッケージ</value>
<value>コードリファレンス</value>
</data>
<data name="SetingsPageDonation.Text" xml:space="preserve">
<value>寄付</value>
@@ -555,9 +564,15 @@
<data name="SetingsPageInstructions.Text" xml:space="preserve">
<value>手順</value>
</data>
<data name="SetingsPageSpecialThanks.Text" xml:space="preserve">
<value>スペシャルサンクス</value>
</data>
<data name="SetingsPageThanks.Text" xml:space="preserve">
<value>このプロジェクトが気に入っている場合は、寄付してサポートすることを検討してください。あなたのサポートは、プロジェクトを生かし続け、さらなる開発を促進するのに役立ちます。</value>
</data>
<data name="SetingsPageUIUXRef.Text" xml:space="preserve">
<value>UI/UXデザインリファレンス</value>
</data>
<data name="SettingsPage3DLyrics.Header" xml:space="preserve">
<value>[実験的] 奥行き効果</value>
</data>
@@ -624,6 +639,9 @@
<data name="SettingsPageAlignment.Header" xml:space="preserve">
<value>アライメント</value>
</data>
<data name="SettingsPageAlwaysHideUnlockButton.Header" xml:space="preserve">
<value>ロック解除ボタンは常に隠しておきましょう</value>
</data>
<data name="SettingsPageAmllTtmlDbBaseUrl.Header" xml:space="preserve">
<value>ベースURL</value>
</data>
@@ -675,6 +693,9 @@
<data name="SettingsPageBackgroundOverlay.Text" xml:space="preserve">
<value>歌詞の背景</value>
</data>
<data name="SettingsPageBlurAmount.Header" xml:space="preserve">
<value>あいまい</value>
</data>
<data name="SettingsPageBorderless.Header" xml:space="preserve">
<value>ボーダーレスウィンドウ</value>
</data>
@@ -750,6 +771,9 @@
<data name="SettingsPageCurrentLyricsWindowStatus.Text" xml:space="preserve">
<value>現在の歌詞ウィンドウステータス</value>
</data>
<data name="SettingsPageCutletDockerServer.Header" xml:space="preserve">
<value>cutlet-docker 音声翻訳サービス</value>
</data>
<data name="SettingsPageDark.Content" xml:space="preserve">
<value>暗い</value>
</data>
@@ -945,6 +969,9 @@
<data name="SettingsPageJA.Content" xml:space="preserve">
<value>日本語</value>
</data>
<data name="SettingsPageJapanese.Description" xml:space="preserve">
<value>歌詞の音訳が最初に読み込まれ、一致しない場合は機械音訳がcutlet - dockerサーバーから要求されます</value>
</data>
<data name="SettingsPageJapanese.Header" xml:space="preserve">
<value>日本の注釈</value>
</data>
@@ -1027,7 +1054,7 @@
<value>LX Music Server</value>
</data>
<data name="SettingsPageLXMusicServerInput.PlaceholderText" xml:space="preserve">
<value>例http://127.0.0.1: 23330</value>
<value>例http://127.0.0.1:23330</value>
</data>
<data name="SettingsPageLyricsAlignment.Header" xml:space="preserve">
<value>アライメント</value>
@@ -1068,6 +1095,12 @@
<data name="SettingsPageLyricsExtraLight.Content" xml:space="preserve">
<value>余分な光</value>
</data>
<data name="SettingsPageLyricsFadeOutEffect.Description" xml:space="preserve">
<value>非現在の行にフェード効果を有効にします</value>
</data>
<data name="SettingsPageLyricsFadeOutEffect.Header" xml:space="preserve">
<value>フェード効果</value>
</data>
<data name="SettingsPageLyricsFgFontColor.Header" xml:space="preserve">
<value>現在のプレイ行</value>
</data>
@@ -1137,6 +1170,12 @@
<data name="SettingsPageLyricsOpacity.Header" xml:space="preserve">
<value>フォントの不透明度</value>
</data>
<data name="SettingsPageLyricsOutOfSightEffect.Description" xml:space="preserve">
<value>現在ではない行を徐々に外に移動してください</value>
</data>
<data name="SettingsPageLyricsOutOfSightEffect.Header" xml:space="preserve">
<value>目につかないように</value>
</data>
<data name="SettingsPageLyricsRowFactor.Header" xml:space="preserve">
<value>歌詞エリアの高さ係数</value>
</data>
@@ -1297,7 +1336,7 @@
<value>パスはコンピューターでは見つかりません</value>
</data>
<data name="SettingsPagePatrons.Text" xml:space="preserve">
<value>スペシャルサンクス</value>
<value>後援しました</value>
</data>
<data name="SettingsPagePhonetic.Text" xml:space="preserve">
<value>リリックアノテーション</value>
@@ -1305,6 +1344,9 @@
<data name="SettingsPagePhoneticText.Header" xml:space="preserve">
<value>発音</value>
</data>
<data name="SettingsPagePinToTaskbar.Header" xml:space="preserve">
<value>タスクバーに移動</value>
</data>
<data name="SettingsPagePinyin.Content" xml:space="preserve">
<value>マンダリンのピンイン</value>
</data>
@@ -1497,6 +1539,9 @@
<data name="SettingsPageStartup.Text" xml:space="preserve">
<value>起動</value>
</data>
<data name="SettingsPageStopTrackOnGalleryWindowClosed.Header" xml:space="preserve">
<value>音楽ライブラリが閉じられたら、再生を停止してください</value>
</data>
<data name="SettingsPageStrokeFontColor.Header" xml:space="preserve">
<value>ストロークカラー</value>
</data>
@@ -1506,6 +1551,12 @@
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
<value>ターゲット言語</value>
</data>
<data name="SettingsPageTaskbarMode.Text" xml:space="preserve">
<value>タスクバーモード</value>
</data>
<data name="SettingsPageTaskbarPlacement.Header" xml:space="preserve">
<value>タスクバーの位置が固定されました</value>
</data>
<data name="SettingsPageTC.Content" xml:space="preserve">
<value>繁體中文</value>
</data>
@@ -1563,6 +1614,9 @@
<data name="SettingsPageTransparent.Content" xml:space="preserve">
<value>透明</value>
</data>
<data name="SettingsPageUserWhoPurchased.Text" xml:space="preserve">
<value>そして、BetterLyricsをサポートするユーザーを購入しましょう</value>
</data>
<data name="SettingsPageVersion.Text" xml:space="preserve">
<value>バージョン</value>
</data>
@@ -1620,6 +1674,9 @@
<data name="SystemTraySwitch.Text" xml:space="preserve">
<value>歌詞ウィンドウスイッチャー</value>
</data>
<data name="TaskbarMode" xml:space="preserve">
<value>タスクバーモード</value>
</data>
<data name="TermsOfService.Content" xml:space="preserve">
<value>利用規約</value>
</data>

View File

@@ -150,6 +150,12 @@
<data name="CreatePlaylistSuccessfully" xml:space="preserve">
<value>재생 목록이 성공적으로 생성되었습니다</value>
</data>
<data name="CutletDockerFailed" xml:space="preserve">
<value>커틀릿 도커에서 음역을 요청하지 못했습니다. 설정 또는 기본 커틀릿 도커 구성을 확인하십시오</value>
</data>
<data name="CutletServerTextBox.PlaceholderText" xml:space="preserve">
<value>예: http://localhost:23333</value>
</data>
<data name="DemoWindowControlDefault.Text" xml:space="preserve">
<value>기본</value>
</data>
@@ -237,6 +243,9 @@
<data name="LyricsPageCachePath.Value" xml:space="preserve">
<value>캐시</value>
</data>
<data name="LyricsPageLanguageCode.Header" xml:space="preserve">
<value>가사 언어</value>
</data>
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
<value>가사 제공자</value>
</data>
@@ -544,7 +553,7 @@
<value>기여자</value>
</data>
<data name="SetingsPageDeps.Text" xml:space="preserve">
<value>종속 패키지</value>
<value>코드 참조</value>
</data>
<data name="SetingsPageDonation.Text" xml:space="preserve">
<value>기부</value>
@@ -555,9 +564,15 @@
<data name="SetingsPageInstructions.Text" xml:space="preserve">
<value>지침</value>
</data>
<data name="SetingsPageSpecialThanks.Text" xml:space="preserve">
<value>특별 감사 인사</value>
</data>
<data name="SetingsPageThanks.Text" xml:space="preserve">
<value>이 프로젝트가 마음에 들면 기부하여 지원을 고려하십시오. 귀하의 지원은 프로젝트를 계속 유지하고 추가 개발을 장려하는 데 도움이 될 것입니다.</value>
</data>
<data name="SetingsPageUIUXRef.Text" xml:space="preserve">
<value>UI/UX 디자인 참조</value>
</data>
<data name="SettingsPage3DLyrics.Header" xml:space="preserve">
<value>[실험] 깊이 효과</value>
</data>
@@ -624,6 +639,9 @@
<data name="SettingsPageAlignment.Header" xml:space="preserve">
<value>조정</value>
</data>
<data name="SettingsPageAlwaysHideUnlockButton.Header" xml:space="preserve">
<value>항상 잠금 해제 버튼을 숨깁니다</value>
</data>
<data name="SettingsPageAmllTtmlDbBaseUrl.Header" xml:space="preserve">
<value>기본 URL</value>
</data>
@@ -675,6 +693,9 @@
<data name="SettingsPageBackgroundOverlay.Text" xml:space="preserve">
<value>가사 배경</value>
</data>
<data name="SettingsPageBlurAmount.Header" xml:space="preserve">
<value>모호함</value>
</data>
<data name="SettingsPageBorderless.Header" xml:space="preserve">
<value>창문</value>
</data>
@@ -750,6 +771,9 @@
<data name="SettingsPageCurrentLyricsWindowStatus.Text" xml:space="preserve">
<value>현재 가사 창 상태</value>
</data>
<data name="SettingsPageCutletDockerServer.Header" xml:space="preserve">
<value>커틀릿 도커 음역 서비스</value>
</data>
<data name="SettingsPageDark.Content" xml:space="preserve">
<value>어두운</value>
</data>
@@ -945,6 +969,9 @@
<data name="SettingsPageJA.Content" xml:space="preserve">
<value>日本語</value>
</data>
<data name="SettingsPageJapanese.Description" xml:space="preserve">
<value>가사의 음역이 먼저 읽히고 일치하지 않으면 커틀릿 도커 서버에서 기계 음역이 요청됩니다</value>
</data>
<data name="SettingsPageJapanese.Header" xml:space="preserve">
<value>일본 주석</value>
</data>
@@ -1027,7 +1054,7 @@
<value>LX 음악 서버</value>
</data>
<data name="SettingsPageLXMusicServerInput.PlaceholderText" xml:space="preserve">
<value>예: http://127.0.0.1: 23330</value>
<value>예: http://127.0.0.1:23330</value>
</data>
<data name="SettingsPageLyricsAlignment.Header" xml:space="preserve">
<value>조정</value>
@@ -1068,6 +1095,12 @@
<data name="SettingsPageLyricsExtraLight.Content" xml:space="preserve">
<value>여분의 빛</value>
</data>
<data name="SettingsPageLyricsFadeOutEffect.Description" xml:space="preserve">
<value>비전류 행에 페이드 효과 활성화</value>
</data>
<data name="SettingsPageLyricsFadeOutEffect.Header" xml:space="preserve">
<value>페이드 효과</value>
</data>
<data name="SettingsPageLyricsFgFontColor.Header" xml:space="preserve">
<value>현재 플레이 행</value>
</data>
@@ -1137,6 +1170,12 @@
<data name="SettingsPageLyricsOpacity.Header" xml:space="preserve">
<value>글꼴 불투명도</value>
</data>
<data name="SettingsPageLyricsOutOfSightEffect.Description" xml:space="preserve">
<value>현재 행이 아닌 행을 점진적으로 보이지 않게 이동합니다</value>
</data>
<data name="SettingsPageLyricsOutOfSightEffect.Header" xml:space="preserve">
<value>눈에 띄지 마세요</value>
</data>
<data name="SettingsPageLyricsRowFactor.Header" xml:space="preserve">
<value>가사 영역 높이 계수</value>
</data>
@@ -1297,7 +1336,7 @@
<value>경로는 컴퓨터에서 찾을 수 없습니다</value>
</data>
<data name="SettingsPagePatrons.Text" xml:space="preserve">
<value>특별 감사 인사</value>
<value>스폰서</value>
</data>
<data name="SettingsPagePhonetic.Text" xml:space="preserve">
<value>가사 주석</value>
@@ -1305,6 +1344,9 @@
<data name="SettingsPagePhoneticText.Header" xml:space="preserve">
<value>발성</value>
</data>
<data name="SettingsPagePinToTaskbar.Header" xml:space="preserve">
<value>작업 표시줄에 고정</value>
</data>
<data name="SettingsPagePinyin.Content" xml:space="preserve">
<value>만다린의 피니 인</value>
</data>
@@ -1497,6 +1539,9 @@
<data name="SettingsPageStartup.Text" xml:space="preserve">
<value>시작</value>
</data>
<data name="SettingsPageStopTrackOnGalleryWindowClosed.Header" xml:space="preserve">
<value>음악 라이브러리가 닫히면 재생을 중지하십시오</value>
</data>
<data name="SettingsPageStrokeFontColor.Header" xml:space="preserve">
<value>윤곽선 색상</value>
</data>
@@ -1506,6 +1551,12 @@
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
<value>대상 언어</value>
</data>
<data name="SettingsPageTaskbarMode.Text" xml:space="preserve">
<value>작업 표시줄</value>
</data>
<data name="SettingsPageTaskbarPlacement.Header" xml:space="preserve">
<value>작업 표시줄 고정 위치</value>
</data>
<data name="SettingsPageTC.Content" xml:space="preserve">
<value>繁體中文</value>
</data>
@@ -1563,6 +1614,9 @@
<data name="SettingsPageTransparent.Content" xml:space="preserve">
<value>투명한</value>
</data>
<data name="SettingsPageUserWhoPurchased.Text" xml:space="preserve">
<value>그리고 BetterLyrics를 지원하는 사용자를 구입하세요</value>
</data>
<data name="SettingsPageVersion.Text" xml:space="preserve">
<value>버전</value>
</data>
@@ -1620,6 +1674,9 @@
<data name="SystemTraySwitch.Text" xml:space="preserve">
<value>가사 창 전환기</value>
</data>
<data name="TaskbarMode" xml:space="preserve">
<value>작업 표시줄</value>
</data>
<data name="TermsOfService.Content" xml:space="preserve">
<value>서비스 약관</value>
</data>

View File

@@ -150,6 +150,12 @@
<data name="CreatePlaylistSuccessfully" xml:space="preserve">
<value>播放列表创建成功</value>
</data>
<data name="CutletDockerFailed" xml:space="preserve">
<value>向 cutlet-docker 请求音译失败,请检查设置或本机 cutlet-docker 配置</value>
</data>
<data name="CutletServerTextBox.PlaceholderText" xml:space="preserve">
<value>例如 http://localhost:23333</value>
</data>
<data name="DemoWindowControlDefault.Text" xml:space="preserve">
<value>默认</value>
</data>
@@ -237,6 +243,9 @@
<data name="LyricsPageCachePath.Value" xml:space="preserve">
<value>缓存路径</value>
</data>
<data name="LyricsPageLanguageCode.Header" xml:space="preserve">
<value>歌词语言</value>
</data>
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
<value>歌词来源</value>
</data>
@@ -544,7 +553,7 @@
<value>贡献者</value>
</data>
<data name="SetingsPageDeps.Text" xml:space="preserve">
<value>依赖包</value>
<value>代码参考</value>
</data>
<data name="SetingsPageDonation.Text" xml:space="preserve">
<value>捐贈</value>
@@ -555,9 +564,15 @@
<data name="SetingsPageInstructions.Text" xml:space="preserve">
<value>操作指南</value>
</data>
<data name="SetingsPageSpecialThanks.Text" xml:space="preserve">
<value>特别鸣谢</value>
</data>
<data name="SetingsPageThanks.Text" xml:space="preserve">
<value>如果您喜欢这个项目,请考虑通过捐赠来支持它。您的支持将有助于保持项目的生命并鼓励进一步的发展。</value>
</data>
<data name="SetingsPageUIUXRef.Text" xml:space="preserve">
<value>UI/UX 设计参考</value>
</data>
<data name="SettingsPage3DLyrics.Header" xml:space="preserve">
<value>[实验性] 纵深效果</value>
</data>
@@ -624,6 +639,9 @@
<data name="SettingsPageAlignment.Header" xml:space="preserve">
<value>对齐方式</value>
</data>
<data name="SettingsPageAlwaysHideUnlockButton.Header" xml:space="preserve">
<value>总是隐藏解锁按钮</value>
</data>
<data name="SettingsPageAmllTtmlDbBaseUrl.Header" xml:space="preserve">
<value>基本 URL</value>
</data>
@@ -675,6 +693,9 @@
<data name="SettingsPageBackgroundOverlay.Text" xml:space="preserve">
<value>歌词背景</value>
</data>
<data name="SettingsPageBlurAmount.Header" xml:space="preserve">
<value>模糊度</value>
</data>
<data name="SettingsPageBorderless.Header" xml:space="preserve">
<value>无边框窗口</value>
</data>
@@ -750,6 +771,9 @@
<data name="SettingsPageCurrentLyricsWindowStatus.Text" xml:space="preserve">
<value>当前歌词窗口状态</value>
</data>
<data name="SettingsPageCutletDockerServer.Header" xml:space="preserve">
<value>cutlet-docker 音译服务</value>
</data>
<data name="SettingsPageDark.Content" xml:space="preserve">
<value>深色</value>
</data>
@@ -945,6 +969,9 @@
<data name="SettingsPageJA.Content" xml:space="preserve">
<value>日本語</value>
</data>
<data name="SettingsPageJapanese.Description" xml:space="preserve">
<value>将优先读取歌词内音译,若无匹配则向 cutlet-docker 服务器请求机器音译</value>
</data>
<data name="SettingsPageJapanese.Header" xml:space="preserve">
<value>日语注音</value>
</data>
@@ -1027,7 +1054,7 @@
<value>LX 音乐服务器</value>
</data>
<data name="SettingsPageLXMusicServerInput.PlaceholderText" xml:space="preserve">
<value>例如 http://127.0.0.1: 23330</value>
<value>例如 http://127.0.0.1:23330</value>
</data>
<data name="SettingsPageLyricsAlignment.Header" xml:space="preserve">
<value>对齐方式</value>
@@ -1068,6 +1095,12 @@
<data name="SettingsPageLyricsExtraLight.Content" xml:space="preserve">
<value>超细</value>
</data>
<data name="SettingsPageLyricsFadeOutEffect.Description" xml:space="preserve">
<value>为非当前行启用淡出效果</value>
</data>
<data name="SettingsPageLyricsFadeOutEffect.Header" xml:space="preserve">
<value>淡出效果</value>
</data>
<data name="SettingsPageLyricsFgFontColor.Header" xml:space="preserve">
<value>当前播放行</value>
</data>
@@ -1137,6 +1170,12 @@
<data name="SettingsPageLyricsOpacity.Header" xml:space="preserve">
<value>字体不透明度</value>
</data>
<data name="SettingsPageLyricsOutOfSightEffect.Description" xml:space="preserve">
<value>使非当前行逐渐远离视野</value>
</data>
<data name="SettingsPageLyricsOutOfSightEffect.Header" xml:space="preserve">
<value>远离视野</value>
</data>
<data name="SettingsPageLyricsRowFactor.Header" xml:space="preserve">
<value>歌词区域高度因子</value>
</data>
@@ -1297,7 +1336,7 @@
<value>无法在您的计算机中找到该路径</value>
</data>
<data name="SettingsPagePatrons.Text" xml:space="preserve">
<value>特别鸣谢</value>
<value>赞助</value>
</data>
<data name="SettingsPagePhonetic.Text" xml:space="preserve">
<value>歌词注音</value>
@@ -1305,6 +1344,9 @@
<data name="SettingsPagePhoneticText.Header" xml:space="preserve">
<value>注音</value>
</data>
<data name="SettingsPagePinToTaskbar.Header" xml:space="preserve">
<value>固定到任务栏</value>
</data>
<data name="SettingsPagePinyin.Content" xml:space="preserve">
<value>普通话拼音</value>
</data>
@@ -1497,6 +1539,9 @@
<data name="SettingsPageStartup.Text" xml:space="preserve">
<value>启动</value>
</data>
<data name="SettingsPageStopTrackOnGalleryWindowClosed.Header" xml:space="preserve">
<value>关闭音乐库时停止播放</value>
</data>
<data name="SettingsPageStrokeFontColor.Header" xml:space="preserve">
<value>描边颜色</value>
</data>
@@ -1506,6 +1551,12 @@
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
<value>目标语言</value>
</data>
<data name="SettingsPageTaskbarMode.Text" xml:space="preserve">
<value>任务栏模式</value>
</data>
<data name="SettingsPageTaskbarPlacement.Header" xml:space="preserve">
<value>任务栏固定位置</value>
</data>
<data name="SettingsPageTC.Content" xml:space="preserve">
<value>繁體中文</value>
</data>
@@ -1563,6 +1614,9 @@
<data name="SettingsPageTransparent.Content" xml:space="preserve">
<value>透明</value>
</data>
<data name="SettingsPageUserWhoPurchased.Text" xml:space="preserve">
<value>以及购买支持 BetterLyrics 的用户</value>
</data>
<data name="SettingsPageVersion.Text" xml:space="preserve">
<value>版本号</value>
</data>
@@ -1620,6 +1674,9 @@
<data name="SystemTraySwitch.Text" xml:space="preserve">
<value>歌词窗口切换器</value>
</data>
<data name="TaskbarMode" xml:space="preserve">
<value>任务栏模式</value>
</data>
<data name="TermsOfService.Content" xml:space="preserve">
<value>服务条款</value>
</data>

View File

@@ -150,6 +150,12 @@
<data name="CreatePlaylistSuccessfully" xml:space="preserve">
<value>已成功建立播放清單</value>
</data>
<data name="CutletDockerFailed" xml:space="preserve">
<value>向 cutlet-docker 請求音譯失敗,請檢查設定或本機 cutlet-docker 設定</value>
</data>
<data name="CutletServerTextBox.PlaceholderText" xml:space="preserve">
<value>例如 http://localhost:23333</value>
</data>
<data name="DemoWindowControlDefault.Text" xml:space="preserve">
<value>預設</value>
</data>
@@ -237,6 +243,9 @@
<data name="LyricsPageCachePath.Value" xml:space="preserve">
<value>檔案路徑緩存</value>
</data>
<data name="LyricsPageLanguageCode.Header" xml:space="preserve">
<value>歌詞語言</value>
</data>
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
<value>歌詞來源</value>
</data>
@@ -544,7 +553,7 @@
<value>貢獻者</value>
</data>
<data name="SetingsPageDeps.Text" xml:space="preserve">
<value>依賴包</value>
<value>代碼參考</value>
</data>
<data name="SetingsPageDonation.Text" xml:space="preserve">
<value>捐贈</value>
@@ -555,9 +564,15 @@
<data name="SetingsPageInstructions.Text" xml:space="preserve">
<value>說明</value>
</data>
<data name="SetingsPageSpecialThanks.Text" xml:space="preserve">
<value>特别鸣谢</value>
</data>
<data name="SetingsPageThanks.Text" xml:space="preserve">
<value>如果您喜歡這個項目,請考慮通過捐贈來支持它。您的支持將有助於保持項目的生命並鼓勵進一步的發展。</value>
</data>
<data name="SetingsPageUIUXRef.Text" xml:space="preserve">
<value>UI/UX 設計參考</value>
</data>
<data name="SettingsPage3DLyrics.Header" xml:space="preserve">
<value>[實驗性] 縱深效果</value>
</data>
@@ -624,6 +639,9 @@
<data name="SettingsPageAlignment.Header" xml:space="preserve">
<value>對齊方式</value>
</data>
<data name="SettingsPageAlwaysHideUnlockButton.Header" xml:space="preserve">
<value>總是隱藏解鎖按鈕</value>
</data>
<data name="SettingsPageAmllTtmlDbBaseUrl.Header" xml:space="preserve">
<value>基本網址</value>
</data>
@@ -675,6 +693,9 @@
<data name="SettingsPageBackgroundOverlay.Text" xml:space="preserve">
<value>歌詞背景</value>
</data>
<data name="SettingsPageBlurAmount.Header" xml:space="preserve">
<value>模糊度</value>
</data>
<data name="SettingsPageBorderless.Header" xml:space="preserve">
<value>無邊框窗口</value>
</data>
@@ -750,6 +771,9 @@
<data name="SettingsPageCurrentLyricsWindowStatus.Text" xml:space="preserve">
<value>當前歌詞窗口狀態</value>
</data>
<data name="SettingsPageCutletDockerServer.Header" xml:space="preserve">
<value>cutlet-docker 音譯服務</value>
</data>
<data name="SettingsPageDark.Content" xml:space="preserve">
<value>深色</value>
</data>
@@ -945,6 +969,9 @@
<data name="SettingsPageJA.Content" xml:space="preserve">
<value>日本語</value>
</data>
<data name="SettingsPageJapanese.Description" xml:space="preserve">
<value>將優先讀取歌詞內音譯,若無匹配則向 cutlet-docker 伺服器請求機器音譯</value>
</data>
<data name="SettingsPageJapanese.Header" xml:space="preserve">
<value>日語注音</value>
</data>
@@ -1027,7 +1054,7 @@
<value>LX 音樂服務器</value>
</data>
<data name="SettingsPageLXMusicServerInput.PlaceholderText" xml:space="preserve">
<value>例如 http://127.0.0.1: 23330</value>
<value>例如 http://127.0.0.1:23330</value>
</data>
<data name="SettingsPageLyricsAlignment.Header" xml:space="preserve">
<value>對齊方式</value>
@@ -1068,6 +1095,12 @@
<data name="SettingsPageLyricsExtraLight.Content" xml:space="preserve">
<value>超細</value>
</data>
<data name="SettingsPageLyricsFadeOutEffect.Description" xml:space="preserve">
<value>為非目前行啟用淡出效果</value>
</data>
<data name="SettingsPageLyricsFadeOutEffect.Header" xml:space="preserve">
<value>淡出效果</value>
</data>
<data name="SettingsPageLyricsFgFontColor.Header" xml:space="preserve">
<value>目前播放行</value>
</data>
@@ -1137,6 +1170,12 @@
<data name="SettingsPageLyricsOpacity.Header" xml:space="preserve">
<value>字體不透明度</value>
</data>
<data name="SettingsPageLyricsOutOfSightEffect.Description" xml:space="preserve">
<value>使非當前行逐漸遠離視野</value>
</data>
<data name="SettingsPageLyricsOutOfSightEffect.Header" xml:space="preserve">
<value>遠離視野</value>
</data>
<data name="SettingsPageLyricsRowFactor.Header" xml:space="preserve">
<value>歌詞區域高度因子</value>
</data>
@@ -1297,7 +1336,7 @@
<value>無法在您的電腦中找到該路徑</value>
</data>
<data name="SettingsPagePatrons.Text" xml:space="preserve">
<value>特別鳴謝</value>
<value>贊助</value>
</data>
<data name="SettingsPagePhonetic.Text" xml:space="preserve">
<value>歌詞注音</value>
@@ -1305,6 +1344,9 @@
<data name="SettingsPagePhoneticText.Header" xml:space="preserve">
<value>注音</value>
</data>
<data name="SettingsPagePinToTaskbar.Header" xml:space="preserve">
<value>釘選到任務列</value>
</data>
<data name="SettingsPagePinyin.Content" xml:space="preserve">
<value>普通話拼音</value>
</data>
@@ -1497,6 +1539,9 @@
<data name="SettingsPageStartup.Text" xml:space="preserve">
<value>啟動</value>
</data>
<data name="SettingsPageStopTrackOnGalleryWindowClosed.Header" xml:space="preserve">
<value>關閉音樂庫時停止播放</value>
</data>
<data name="SettingsPageStrokeFontColor.Header" xml:space="preserve">
<value>描邊顏色</value>
</data>
@@ -1506,6 +1551,12 @@
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
<value>目標語言</value>
</data>
<data name="SettingsPageTaskbarMode.Text" xml:space="preserve">
<value>任務列模式</value>
</data>
<data name="SettingsPageTaskbarPlacement.Header" xml:space="preserve">
<value>工作列固定位置</value>
</data>
<data name="SettingsPageTC.Content" xml:space="preserve">
<value>繁體中文</value>
</data>
@@ -1563,6 +1614,9 @@
<data name="SettingsPageTransparent.Content" xml:space="preserve">
<value>透明</value>
</data>
<data name="SettingsPageUserWhoPurchased.Text" xml:space="preserve">
<value>以及購買支援BetterLyrics 的用戶</value>
</data>
<data name="SettingsPageVersion.Text" xml:space="preserve">
<value>版本號</value>
</data>
@@ -1620,6 +1674,9 @@
<data name="SystemTraySwitch.Text" xml:space="preserve">
<value>歌詞視窗切換器</value>
</data>
<data name="TaskbarMode" xml:space="preserve">
<value>任務列模式</value>
</data>
<data name="TermsOfService.Content" xml:space="preserve">
<value>服務條款</value>
</data>

View File

@@ -2,7 +2,6 @@
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Hooks;
using BetterLyrics.WinUI3.Models.Settings;
using BetterLyrics.WinUI3.Services.ResourceService;
using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.ComponentModel;
@@ -10,8 +9,6 @@ using CommunityToolkit.Mvvm.Input;
using Microsoft.UI.Xaml.Controls;
using System;
using System.Threading.Tasks;
using Windows.Services.Store;
using Windows.System;
namespace BetterLyrics.WinUI3.ViewModels
{

View File

@@ -69,6 +69,12 @@ namespace BetterLyrics.WinUI3.ViewModels
AppSettings.WindowBoundsRecords.Add(LyricsWindowStatusExtensions.NarrowMode());
}
[RelayCommand]
private void CreateTaskbarLyricsWindowStatus()
{
AppSettings.WindowBoundsRecords.Add(LyricsWindowStatusExtensions.TaskbarMode());
}
public void OpenConfigPanel()
{
IsConfigPanelOpened = true;

View File

@@ -5,7 +5,8 @@ using BetterLyrics.WinUI3.Services.LastFMService;
using BetterLyrics.WinUI3.Services.MediaSessionsService;
using BetterLyrics.WinUI3.Services.ResourceService;
using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.Services.TranslateService;
using BetterLyrics.WinUI3.Services.TranslationService;
using BetterLyrics.WinUI3.Services.TransliterationService;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Hqub.Lastfm.Entities;
@@ -20,10 +21,10 @@ namespace BetterLyrics.WinUI3.ViewModels
public partial class PlaybackSettingsControlViewModel : BaseViewModel
{
public IMediaSessionsService MediaSessionsService;
private readonly ITranslateService _libreTranslateService;
private readonly ITranslationService _translationService;
private readonly ILastFMService _lastFMService;
private readonly ISettingsService _settingsService;
private readonly IResourceService _resourceService;
private readonly ITransliterationService _transliterationService;
[ObservableProperty]
public partial AppSettings AppSettings { get; set; }
@@ -40,6 +41,9 @@ namespace BetterLyrics.WinUI3.ViewModels
[ObservableProperty]
public partial bool IsLibreTranslateServerTesting { get; set; } = false;
[ObservableProperty]
public partial bool IsCutletDockerServerTesting { get; set; } = false;
[ObservableProperty]
public partial bool IsLXMusicServerTesting { get; set; } = false;
@@ -52,15 +56,15 @@ namespace BetterLyrics.WinUI3.ViewModels
public PlaybackSettingsControlViewModel(
ISettingsService settingsService,
IMediaSessionsService mediaSessionsService,
ITranslateService libreTranslateService,
ITranslationService libreTranslationService,
ILastFMService lastFMService,
IResourceService resourceService)
ITransliterationService transliterationService)
{
MediaSessionsService = mediaSessionsService;
_settingsService = settingsService;
_libreTranslateService = libreTranslateService;
_resourceService = resourceService;
_translationService = libreTranslationService;
_transliterationService = transliterationService;
_lastFMService = lastFMService;
_lastFMService.UserChanged += LastFMService_UserChanged;
@@ -107,7 +111,7 @@ namespace BetterLyrics.WinUI3.ViewModels
{
try
{
string result = await _libreTranslateService.TranslateTextAsync(
string result = await _translationService.TranslateTextAsync(
"Hello, world!", AppSettings.TranslationSettings.SelectedTargetLanguageCode, new System.Threading.CancellationToken());
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
@@ -128,6 +132,35 @@ namespace BetterLyrics.WinUI3.ViewModels
});
}
[RelayCommand]
private void CutletDockerServerTest()
{
IsCutletDockerServerTesting = true;
Task.Run(async () =>
{
try
{
string result = await _transliterationService.TransliterateText(
"こんにちは", PhoneticHelper.RomanCode, new System.Threading.CancellationToken());
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
ToastHelper.ShowToast("SettingsPageServerTestSuccessInfo", null, InfoBarSeverity.Success);
});
}
catch (Exception)
{
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
ToastHelper.ShowToast("SettingsPageServerTestFailedInfo", null, InfoBarSeverity.Error);
});
}
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
IsCutletDockerServerTesting = false;
});
});
}
[RelayCommand]
private async Task LastFMAuthAsync()
{
@@ -171,6 +204,7 @@ namespace BetterLyrics.WinUI3.ViewModels
[RelayCommand]
private void SaveAppleMusicMediaUserToken()
{
PasswordVaultHelper.Delete(Constants.App.AppName, Constants.AppleMusic.MediaUserTokenKey);
PasswordVaultHelper.Save(Constants.App.AppName, Constants.AppleMusic.MediaUserTokenKey, AppleMusicMediaUserToken);
MediaSessionsService.UpdateLyrics();
}

View File

@@ -178,7 +178,10 @@ namespace BetterLyrics.WinUI3.Views
private void Page_Unloaded(object sender, RoutedEventArgs e)
{
ViewModel.CancelRefreshSongs();
ViewModel.StopTrackCommand.Execute(null);
if (ViewModel.AppSettings.MusicGallerySettings.StopOnWindowClosed)
{
ViewModel.StopTrackCommand.Execute(null);
}
}
private void PlaylistFavButton_Click(object sender, RoutedEventArgs e)

View File

@@ -11,7 +11,6 @@ using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media.Imaging;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.

View File

@@ -6,6 +6,7 @@
xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors"
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:dev="using:DevWinUI"
xmlns:local="using:BetterLyrics.WinUI3.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:media="using:CommunityToolkit.WinUI.Media"
@@ -14,6 +15,7 @@
mc:Ignorable="d">
<Grid x:Name="RootGrid" SizeChanged="RootGrid_SizeChanged">
<Grid
x:Name="PlaceholderGrid"
Width="1"
@@ -27,7 +29,7 @@
<Grid
x:Name="TopCommandGrid"
VerticalAlignment="Top"
Background="{ThemeResource AcrylicInAppFillColorDefaultBrush}"
Background="{ThemeResource LayerOnMicaBaseAltFillColorDefaultBrush}"
Opacity="{x:Bind ViewModel.TopCommandGridOpacity, Mode=OneWay}"
PointerEntered="TopCommandGrid_PointerEntered"
PointerExited="TopCommandGrid_PointerExited">

View File

@@ -17,9 +17,7 @@ using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media.Imaging;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Graphics.Imaging;
using Windows.UI;
using WinRT.Interop;
@@ -34,10 +32,13 @@ namespace BetterLyrics.WinUI3.Views
IRecipient<PropertyChangedMessage<ElementTheme>>,
IRecipient<PropertyChangedMessage<BitmapImage?>>,
IRecipient<PropertyChangedMessage<LyricsFontColorType>>,
IRecipient<PropertyChangedMessage<Color>>
IRecipient<PropertyChangedMessage<Color>>,
IRecipient<PropertyChangedMessage<TaskbarPlacement>>
{
private ForegroundWindowHook? _fgWindowWatcher = null;
private OverlayInputHelper? _overlayInputHelper = null;
private OverlayInputHelper? _overlayInputHelper;
private TaskbarHook? _taskbarHook;
private DispatcherQueueTimer? _fgWindowWatcherTimer = null;
private Color _backdropAccentColor = Colors.Transparent;
@@ -62,13 +63,16 @@ namespace BetterLyrics.WinUI3.Views
AppWindow.Changed += AppWindow_Changed;
AppWindow.Closing += AppWindow_Closing;
SystemBackdrop = SystemBackdropHelper.CreateSystemBackdrop(BackdropType.Transparent);
WeakReferenceMessenger.Default.RegisterAll(this);
UpdateAlbumArtThemeColors();
}
private void OnTaskbarFreeBoundsChanged(Events.TaskbarFreeBoundsChangedEventArgs obj)
{
this.MoveAndResize(obj.TaskbarFreeBounds);
}
public void InitStatus()
{
LyricsWindowStatus.UpdateMonitorBounds();
@@ -82,6 +86,8 @@ namespace BetterLyrics.WinUI3.Views
OnIsLockedChanged();
OnAutoShowOrHideWindowChanged();
OnTitleBarAreaChanged();
OnIsPinToTaskbarChanged();
OnIsAlwaysHideUnlockButtonChanged();
LyricsWindowStatus.UpdateDemoWindowAndMonitorBounds();
}
@@ -150,6 +156,11 @@ namespace BetterLyrics.WinUI3.Views
LyricsWindowStatus.IsLocked = true;
this.MoveAndResize(LyricsWindowStatus.GetWindowBoundsWhenWorkArea());
}
else
{
// ǿ<>ƴ<EFBFBD><C6B4><EFBFBD>һ<EFBFBD>θ<EFBFBD><CEB8>£<EFBFBD>ˢ<EFBFBD>½<EFBFBD><C2BD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ɼ<EFBFBD><C9BC><EFBFBD>״̬
OnIsLockedChanged();
}
}
private void OnIsShownInSwitchersChanged()
@@ -165,8 +176,7 @@ namespace BetterLyrics.WinUI3.Views
private void OnIsLockedChanged()
{
this.SetIsLocked(LyricsWindowStatus.IsLocked);
if (LyricsWindowStatus.IsLocked)
if (LyricsWindowStatus.IsLocked && !LyricsWindowStatus.IsWorkArea)
{
LockToggleButtonContainer.Visibility = Visibility.Visible;
StartOverlayInputHelper();
@@ -177,24 +187,45 @@ namespace BetterLyrics.WinUI3.Views
UnlockButton.Opacity = 0;
StopOverlayInputHelper();
}
this.SetIsLocked(LyricsWindowStatus.IsLocked);
}
private void OnIsPinToTaskbarChanged()
{
_taskbarHook?.Dispose();
_taskbarHook = null;
if (LyricsWindowStatus.IsPinToTaskbar)
{
_taskbarHook = new(LyricsWindowStatus.TaskbarPlacement, OnTaskbarFreeBoundsChanged);
}
}
private void OnIsAlwaysHideUnlockButtonChanged()
{
UnlockButton.Visibility = LyricsWindowStatus.IsAlwaysHideUnlockButton ? Visibility.Collapsed : Visibility.Visible;
}
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()
@@ -361,6 +392,8 @@ namespace BetterLyrics.WinUI3.Views
private void StartOverlayInputHelper()
{
if (_overlayInputHelper != null) return;
_overlayInputHelper = new(this);
_overlayInputHelper.Register(RootGrid);
_overlayInputHelper.Register(LockToggleButtonContainer);
@@ -473,6 +506,14 @@ namespace BetterLyrics.WinUI3.Views
{
OnIsAdaptToEnvironmentChanged();
}
else if (message.PropertyName == nameof(LyricsWindowStatus.IsPinToTaskbar))
{
OnIsPinToTaskbarChanged();
}
else if (message.PropertyName == nameof(LyricsWindowStatus.IsAlwaysHideUnlockButton))
{
OnIsAlwaysHideUnlockButtonChanged();
}
}
}
@@ -580,5 +621,15 @@ namespace BetterLyrics.WinUI3.Views
}
}
public void Receive(PropertyChangedMessage<TaskbarPlacement> message)
{
if (message.Sender == LyricsWindowStatus)
{
if (message.PropertyName == nameof(LyricsWindowStatus.TaskbarPlacement))
{
_taskbarHook?.UpdatePlacement(LyricsWindowStatus.TaskbarPlacement);
}
}
}
}
}

View File

@@ -73,6 +73,7 @@ public sealed partial class SystemTrayWindow : Window, IRecipient<PropertyChange
records.Add(LyricsWindowStatusExtensions.DockedMode(this));
records.Add(LyricsWindowStatusExtensions.NarrowMode(this));
records.Add(LyricsWindowStatusExtensions.FullscreenMode(this));
records.Add(LyricsWindowStatusExtensions.TaskbarMode(this));
}
}

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!
同时,向 **所有在商店购买应用的用户** 表达最诚挚的感谢。你们的支持是本项目不断前行的动力!

View File

@@ -3,34 +3,37 @@
"IsDefault": false,
"MonitorDeviceName": "\\\\.\\DISPLAY1",
"IsWorkArea": false,
"IsBorderless": true,
"IsAlwaysOnTop": true,
"IsAlwaysOnTopPolling": true,
"IsShownInSwitchers": false,
"IsClickThrough": true,
"IsLocked": true,
"IsPinToTaskbar": true,
"TaskbarPlacement": 1,
"IsMaximized": false,
"IsFullscreen": false,
"LyricsLayoutOrientation": 0,
"LyricsDisplayType": 1,
"WindowBounds": {
"X": 0,
"Y": 1020,
"Width": 600,
"Height": 64,
"Left": 0,
"Top": 1020,
"Right": 600,
"Bottom": 1084,
"X": 100,
"Y": 100,
"Width": 800,
"Height": 500,
"Left": 100,
"Top": 100,
"Right": 900,
"Bottom": 600,
"IsEmpty": false
},
"DockHeight": 64,
"DemoWindowBounds": {
"X": 0,
"Y": 102,
"Width": 60,
"Height": 6.400000095367432,
"Left": 0,
"Top": 102,
"Right": 60,
"Bottom": 108.4000015258789,
"X": 10,
"Y": 10,
"Width": 80,
"Height": 50,
"Left": 10,
"Top": 10,
"Right": 90,
"Bottom": 60,
"IsEmpty": false
},
"MonitorBounds": {
@@ -57,12 +60,14 @@
},
"DockPlacement": 0,
"LyricsStyleSettings": {
"IsDynamicLyricsFontSize": false,
"IsDynamicLyricsFontSize": true,
"PhoneticLyricsFontSize": 12,
"OriginalLyricsFontSize": 16,
"OriginalLyricsFontSize": 24,
"TranslatedLyricsFontSize": 12,
"LyricsAlignmentType": 0,
"LyricsBgFontOpacity": 30,
"PhoneticLyricsOpacity": 60,
"OriginalLyricsOpacity": 30,
"TranslatedLyricsOpacity": 60,
"LyricsAlignmentType": 1,
"LyricsFontStrokeWidth": 0,
"LyricsCustomBgFontColor": {
"A": 255,
@@ -87,33 +92,31 @@
"LyricsStrokeFontColorType": 1,
"LyricsFontWeight": 7,
"LyricsLineSpacingFactor": 0.5,
"LyricsTranslationSeparator": "\n",
"LyricsCJKFontFamily": "Arial",
"LyricsWesternFontFamily": "Arial",
"PlayingLineTopOffset": 50,
"IsActive": false
},
"LyricsEffectSettings": {
"LyricsBlurAmount": 5,
"IsLyricsLineFadeEnabled": true,
"IsLyricsBlurEffectEnabled": true,
"IsLyricsGlowEffectEnabled": true,
"LyricsGlowEffectScope": 0,
"LyricsGlowEffectLongSyllableDuration": 700,
"IsLyricsGlowEffectAmountAutoAdjust": true,
"LyricsGlowEffectAmount": 8,
"IsLyricsShadowEnabled": false,
"LyricsShadowScope": 1,
"LyricsShadowAmount": 8,
"OriginalLyricsHighlightScope": 1,
"PhoneticLyricsHighlightAmount": 60,
"OriginalLyricsHighlightAmount": 100,
"TranslatedLyricsHighlightAmount": 60,
"IsLyricsScaleEffectEnabled": true,
"LyricsScaleEffectLongSyllableDuration": 700,
"IsLyricsScaleEffectAmountAutoAdjust": true,
"LyricsScaleEffectAmount": 115,
"IsLyricsFloatAnimationEnabled": true,
"LyricsFloatAmount": 1,
"IsLyricsFloatAnimationAmountAutoAdjust": true,
"LyricsFloatAnimationAmount": 8,
"LyricsScrollEasingType": 3,
"LyricsScrollDuration": 500,
"LyricsScrollTopDuration": 500,
"LyricsScrollBottomDuration": 500,
"LyricsScrollTopDelay": 0,
"LyricsScrollBottomDelay": 0,
"LyricsVerticalEdgeOpacity": 0,
"IsFanLyricsEnabled": false,
"FanLyricsAngle": 30,
"Is3DLyricsEnabled": false,
@@ -127,21 +130,23 @@
"LyricsBackgroundTheme": 2,
"IsPureColorOverlayEnabled": false,
"PureColorOverlayOpacity": 100,
"IsCoverOverlayEnabled": false,
"CoverOverlayBlurAmount": 100,
"CoverOverlayOpacity": 100,
"CoverOverlaySpeed": 50,
"CoverAcrylicEffectAmount": 0,
"IsFluidOverlayEnabled": false,
"FluidOverlayOpacity": 100,
"PaletteGeneratorType": 0,
"IsSpectrumOverlayEnabled": false,
"SpectrumPlacement": 1,
"SpectrumStyle": 1,
"SpectrumCount": 128,
"IsSnowFlakeOverlayEnabled": false,
"SnowFlakeOverlayAmount": 50,
"SnowFlakeOverlayAmount": 10,
"SnowFlakeOverlaySpeed": 1,
"IsFogOverlayEnabled": false,
"IsActive": false
},
"AlbumArtLayoutSettings": {
"SongInfoAlignmentType": 0,
"IsAutoCoverImageHeight": true,
"CoverImageHeight": 128,
"CoverImageRadius": 12,
"CoverImageShadowAmount": 12,
"IsAutoSongInfoFontSize": true,
@@ -149,17 +154,15 @@
"ShowTitle": true,
"ShowArtists": true,
"ShowAlbum": false,
"AlbumArtSize": 64,
"AutoAlbumArtSize": true,
"IsActive": false
},
"AlbumArtAreaEffectSettings": {
"ImageSwitchType": 1,
"IsActive": false
},
"IsAdaptToEnvironment": true,
"EnvironmentSampleMode": 3,
"AutoShowOrHideWindow": false,
"TitleBarArea": 1,
"WindowX": 0,
"WindowY": 1020,
"WindowWidth": 600,
"WindowHeight": 64,
"IsActive": false
}
}