mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-13 03:34:55 +08:00
Compare commits
50 Commits
v1.2.253.0
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f735170961 | ||
|
|
a215abc41b | ||
|
|
2ddd7d19ab | ||
|
|
4d270df594 | ||
|
|
7fdb7ed870 | ||
|
|
aad648d078 | ||
|
|
d93fad6f3b | ||
|
|
a6bdf92341 | ||
|
|
96229d4346 | ||
|
|
bea29bdf9f | ||
|
|
4ad4959c39 | ||
|
|
7457cb1139 | ||
|
|
b6a6cd8659 | ||
|
|
6173dae1fa | ||
|
|
b6aac2b968 | ||
|
|
290f84cea0 | ||
|
|
3031d298d5 | ||
|
|
ed74e96aeb | ||
|
|
affa55b057 | ||
|
|
305f5e2cac | ||
|
|
b8d4fc4130 | ||
|
|
da5fd90d44 | ||
|
|
f4a6aa78b6 | ||
|
|
52b81cd959 | ||
|
|
d79933d41e | ||
|
|
a82f1bdb53 | ||
|
|
2cac55b55e | ||
|
|
4efe897ab2 | ||
|
|
173f808a88 | ||
|
|
e73c27c705 | ||
|
|
3724ef5f7e | ||
|
|
7ca0ecde16 | ||
|
|
2e0700dba5 | ||
|
|
9ec12e3a08 | ||
|
|
d042993eb7 | ||
|
|
fea7367671 | ||
|
|
2b3169e5f6 | ||
|
|
9d2e245a99 | ||
|
|
0513c3a128 | ||
|
|
5082c4c245 | ||
|
|
659b4d0e60 | ||
|
|
85f67c2ec6 | ||
|
|
bdbeb391ea | ||
|
|
3357e7aaf4 | ||
|
|
e43461d624 | ||
|
|
3e1907ad8c | ||
|
|
74eeffc8a6 | ||
|
|
c32eb3b877 | ||
|
|
047e53b830 | ||
|
|
fdb7bd16f6 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -408,3 +408,6 @@ FodyWeavers.xsd
|
||||
/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/BetterLyrics.WinUI3 (Package)_TemporaryKey.pfx
|
||||
/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/LastFM.cs
|
||||
/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/Discord.cs
|
||||
/BetterLyrics.Plugins.Romaji/unidic
|
||||
/Plugins/BetterLyrics.Plugins.Romaji/unidic
|
||||
/Plugins/BetterLyrics.Plugins.Transliteration.Romaji/unidic
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Interfaces\" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<Private>false</Private>
|
||||
<ExcludeAssets>runtime</ExcludeAssets>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace BetterLyrics.Core
|
||||
{
|
||||
public class Class1
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
12
BetterLyrics.Core/Interfaces/Features/ILyricsSource.cs
Normal file
12
BetterLyrics.Core/Interfaces/Features/ILyricsSource.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using BetterLyrics.Core.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.Core.Interfaces.Features
|
||||
{
|
||||
public interface ILyricsSource
|
||||
{
|
||||
Task<LyricsSearchResult> GetLyricsAsync(string title, string artist, string album, double duration);
|
||||
}
|
||||
}
|
||||
11
BetterLyrics.Core/Interfaces/Features/ILyricsTranslator.cs
Normal file
11
BetterLyrics.Core/Interfaces/Features/ILyricsTranslator.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.Core.Interfaces.Features
|
||||
{
|
||||
public interface ILyricsTranslator
|
||||
{
|
||||
Task<string?> GetTranslationAsync(string text, string targetLangCode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.Core.Interfaces.Features
|
||||
{
|
||||
public interface ILyricsTransliterator
|
||||
{
|
||||
Task<string?> GetTransliterationAsync(string text, string targetLangCode);
|
||||
}
|
||||
}
|
||||
20
BetterLyrics.Core/Interfaces/IPlugin.cs
Normal file
20
BetterLyrics.Core/Interfaces/IPlugin.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using BetterLyrics.Core.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.Core.Interfaces
|
||||
{
|
||||
public interface IPlugin
|
||||
{
|
||||
string Id { get; }
|
||||
string Name { get; }
|
||||
string Description { get; }
|
||||
string Author { get; }
|
||||
string Version { get; }
|
||||
DateTime LastUpdated { get; }
|
||||
|
||||
void OnLoad(IPluginContext context);
|
||||
void OnUnload();
|
||||
}
|
||||
}
|
||||
14
BetterLyrics.Core/Interfaces/IPluginContext.cs
Normal file
14
BetterLyrics.Core/Interfaces/IPluginContext.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using BetterLyrics.Core.Interfaces.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.Core.Interfaces
|
||||
{
|
||||
public interface IPluginContext
|
||||
{
|
||||
string PluginDirectory { get; }
|
||||
|
||||
IAIService? AIService { get; }
|
||||
}
|
||||
}
|
||||
11
BetterLyrics.Core/Interfaces/Services/IAIService.cs
Normal file
11
BetterLyrics.Core/Interfaces/Services/IAIService.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.Core.Interfaces.Services
|
||||
{
|
||||
public interface IAIService
|
||||
{
|
||||
Task<string> ChatAsync(string systemPrompt, string userPrompt);
|
||||
}
|
||||
}
|
||||
16
BetterLyrics.Core/Models/LyricsSearchResult.cs
Normal file
16
BetterLyrics.Core/Models/LyricsSearchResult.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.Core.Models
|
||||
{
|
||||
public record LyricsSearchResult(
|
||||
string? Title,
|
||||
string? Artist,
|
||||
string? Album,
|
||||
double? Duration,
|
||||
string Raw,
|
||||
string? Translation = null,
|
||||
string? Transliteration = null,
|
||||
string? Reference = null);
|
||||
}
|
||||
@@ -143,7 +143,7 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.7175" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.7463" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.8.251106002" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<Identity
|
||||
Name="37412.BetterLyrics"
|
||||
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
|
||||
Version="1.2.253.0" />
|
||||
Version="1.2.260.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ using BetterLyrics.WinUI3.Services.LocalizationService;
|
||||
using BetterLyrics.WinUI3.Services.LyricsCacheService;
|
||||
using BetterLyrics.WinUI3.Services.LyricsSearchService;
|
||||
using BetterLyrics.WinUI3.Services.PlayHistoryService;
|
||||
using BetterLyrics.WinUI3.Services.PluginService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using BetterLyrics.WinUI3.Services.SMTCService;
|
||||
using BetterLyrics.WinUI3.Services.SongSearchMapService;
|
||||
@@ -22,7 +23,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.Windows.AppLifecycle; // 关键:App生命周期管理
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Linq;
|
||||
@@ -154,6 +155,10 @@ namespace BetterLyrics.WinUI3
|
||||
}
|
||||
fileSystemService.StartAllFolderTimers();
|
||||
|
||||
// Ensure plugins
|
||||
var pluginService = Ioc.Default.GetRequiredService<IPluginService>();
|
||||
pluginService.LoadPlugins();
|
||||
|
||||
// Init system tray
|
||||
m_window = WindowHook.OpenOrShowWindow<SystemTrayWindow>();
|
||||
|
||||
@@ -248,6 +253,7 @@ namespace BetterLyrics.WinUI3
|
||||
.AddSingleton<IPlayHistoryService, PlayHistoryService>()
|
||||
.AddSingleton<ILyricsCacheService, LyricsCacheService>()
|
||||
.AddSingleton<ISongSearchMapService, SongSearchMapService>()
|
||||
.AddSingleton<IPluginService, PluginService>()
|
||||
|
||||
// ViewModels
|
||||
.AddSingleton<AppSettingsControlViewModel>()
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<None Remove="Controls\PatronControl.xaml" />
|
||||
<None Remove="Controls\PlaybackSettingsControl.xaml" />
|
||||
<None Remove="Controls\PlayQueue.xaml" />
|
||||
<None Remove="Controls\PluginManagerControl.xaml" />
|
||||
<None Remove="Controls\PropertyRow.xaml" />
|
||||
<None Remove="Controls\RemoteServerConfigControl.xaml" />
|
||||
<None Remove="Controls\ShortcutTextBox.xaml" />
|
||||
@@ -82,7 +83,7 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Triggers" Version="8.2.251219" />
|
||||
<PackageReference Include="ComputeSharp.D2D1.WinUI" Version="3.2.0" />
|
||||
<PackageReference Include="csharp-pinyin" Version="1.0.1" />
|
||||
<PackageReference Include="DevWinUI.Controls" Version="9.8.1" />
|
||||
<PackageReference Include="DevWinUI.Controls" Version="9.9.2" />
|
||||
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.6" />
|
||||
<PackageReference Include="F23.StringSimilarity" Version="7.0.1" />
|
||||
<PackageReference Include="FlaUI.UIA3" Version="5.0.0" />
|
||||
@@ -96,10 +97,14 @@
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<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.Windows.SDK.BuildTools" Version="10.0.26100.7463" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.8.251106002" />
|
||||
<PackageReference Include="NAudio.Wasapi" Version="2.2.1" />
|
||||
<PackageReference Include="NTextCat" Version="0.3.65" />
|
||||
@@ -118,11 +123,12 @@
|
||||
<PackageReference Include="VCollab.DiscordRichPresence" Version="1.7.0" />
|
||||
<PackageReference Include="WebDav.Client" Version="2.9.0" />
|
||||
<PackageReference Include="WinUIEx" Version="2.9.0" />
|
||||
<PackageReference Include="z440.atl.core" Version="7.9.0" />
|
||||
<PackageReference Include="z440.atl.core" Version="7.10.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\ColorThief.WinUI3\ColorThief.WinUI3.csproj" />
|
||||
<ProjectReference Include="..\..\Impressionist\Impressionist\Impressionist.csproj" />
|
||||
<ProjectReference Include="..\..\BetterLyrics.Core\BetterLyrics.Core.csproj" />
|
||||
<ProjectReference Include="..\..\ColorThief.WinUI3\ColorThief.WinUI3.csproj" />
|
||||
<ProjectReference Include="..\..\Impressionist\Impressionist\Impressionist.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Rendering\InAppLyricsRenderer.xaml">
|
||||
@@ -134,252 +140,245 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<!--Disable Trimming for Specific Packages-->
|
||||
<ItemGroup>
|
||||
<TrimmerRootAssembly Include="FlaUI.UIA3" />
|
||||
<TrimmerRootAssembly Include="Interop.UIAutomationClient" />
|
||||
<TrimmerRootAssembly Include="Microsoft.EntityFrameworkCore" />
|
||||
<TrimmerRootAssembly Include="Microsoft.EntityFrameworkCore.Abstractions" />
|
||||
<TrimmerRootAssembly Include="Microsoft.EntityFrameworkCore.Relational" />
|
||||
<TrimmerRootAssembly Include="Microsoft.EntityFrameworkCore.Sqlite" />
|
||||
<TrimmerRootAssembly Include="NAudio.Wasapi" />
|
||||
<TrimmerRootAssembly Include="TagLibSharp" />
|
||||
<TrimmerRootAssembly Include="Vanara.PInvoke.DwmApi" />
|
||||
<TrimmerRootAssembly Include="Vanara.PInvoke.Gdi32" />
|
||||
<TrimmerRootAssembly Include="Vanara.PInvoke.Shell32" />
|
||||
<TrimmerRootAssembly Include="Vanara.PInvoke.User32" />
|
||||
<TrimmerRootAssembly Include="Vanara.Windows.Shell" />
|
||||
<TrimmerRootDescriptor Include="PluginConfigs\**\*_TrimmerRoots.xml" />
|
||||
<TrimmerRootDescriptor Include="Core_TrimmerRoots.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Update="Assets\AIMP.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\AlbumArtPlaceholder.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Alipay.jpg">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\AMLLPlayer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\AppleMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Chrome.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Edge.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\FluidEffect.bin">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Empty.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\EmptyBox.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\EmptyState.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Folder.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\foobar2000.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\HyPlayer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\iTunes.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\KugouMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\LastFM.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Leaf.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Listen1.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Logo.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Logo.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\LXMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\MediaPlayerWindows11.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\MoeKoeMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\MusicBee.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\NetEaseCloudMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\OriginalSoundHQPlayer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Page.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\PlanetMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\PotPlayer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\QQMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Question.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\RevolvingHearts.gif">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\SaltPlayerForWindows.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Segoe Fluent Icons.ttf">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Spotify.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\WeChatReward.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Wiki82.profile.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\AIMP.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\AlbumArtPlaceholder.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Alipay.jpg">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\AMLLPlayer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\AppleMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Chrome.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Edge.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\FluidEffect.bin">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Empty.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\EmptyBox.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\EmptyState.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Folder.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\foobar2000.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\HyPlayer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\iTunes.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\KugouMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\LastFM.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Leaf.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Listen1.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Logo.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Logo.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\LXMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\MediaPlayerWindows11.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\MoeKoeMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\MusicBee.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\NetEaseCloudMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\OriginalSoundHQPlayer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Page.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\PlanetMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\PotPlayer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\QQMusic.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Question.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\RevolvingHearts.gif">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\SaltPlayerForWindows.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Segoe Fluent Icons.ttf">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Spotify.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\WeChatReward.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Wiki82.profile.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\PatronControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\PluginManagerControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Styles\GhostSliderStyle.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\PatronControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Styles\Converters.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Styles\GhostSliderStyle.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\PlayQueue.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Styles\Converters.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\StatsDashboardControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\PlayQueue.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\FontFamilyAutoSuggestBox.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\StatsDashboardControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\LyricsStyleSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\FontFamilyAutoSuggestBox.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\LyricsWindowSwitchWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\LyricsStyleSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\LyricsWindowSwitchControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Views\LyricsWindowSwitchWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\DemoWindowGrid.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\LyricsWindowSwitchControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\LyricsWindowSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\DemoWindowGrid.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\LyricsSearchWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\LyricsWindowSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\LyricsSearchControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Views\LyricsSearchWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\ShortcutTextBox.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\LyricsSearchControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\ExtendedSlider.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\ShortcutTextBox.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\LyricsEffectSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\ExtendedSlider.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\MediaSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\LyricsEffectSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\PlaybackSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\MediaSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\AlbumArtAreaStyleSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\PlaybackSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\LyricsBackgroundSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\AlbumArtAreaStyleSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\AppSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\LyricsBackgroundSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\MusicGalleryWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\AppSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\MusicGalleryPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Views\MusicGalleryWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\MusicGalleryPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\SettingsWindow.xaml">
|
||||
@@ -392,54 +391,57 @@
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\RemoteServerConfigControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\RemoteServerConfigControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\NowPlayingBar.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\NowPlayingBar.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\SystemTrayWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Views\SystemTrayWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\WindowSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\WindowSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\AlbumArtAreaEffectSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\AlbumArtAreaEffectSettingsControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\ImageSwitcher.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\ImageSwitcher.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\ShadowImage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\ShadowImage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\PropertyRow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\PropertyRow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\AboutControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\AboutControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Styles\InteractiveListViewHeaderStyle.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Styles\InteractiveListViewHeaderStyle.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="PluginConfigs\" />
|
||||
</ItemGroup>
|
||||
<!-- Publish Properties -->
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace BetterLyrics.WinUI3.Controls
|
||||
);
|
||||
private readonly ValueTransition<double> _immersiveBgOpacityTransition = new(
|
||||
initialValue: 1f,
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: 0.3f
|
||||
);
|
||||
private readonly ValueTransition<Color> _accentColor1Transition = new(
|
||||
@@ -87,13 +88,13 @@ namespace BetterLyrics.WinUI3.Controls
|
||||
);
|
||||
private readonly ValueTransition<double> _canvasYScrollTransition = new(
|
||||
initialValue: 0f,
|
||||
defaultTotalDuration: 0.3f,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: 0.3f
|
||||
);
|
||||
private readonly ValueTransition<double> _mouseYScrollTransition = new(
|
||||
initialValue: 0f,
|
||||
defaultTotalDuration: 0.3f,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: 0.3f
|
||||
);
|
||||
|
||||
private TimeSpan _songPositionWithOffset;
|
||||
@@ -492,7 +493,7 @@ namespace BetterLyrics.WinUI3.Controls
|
||||
else
|
||||
{
|
||||
_canvasYScrollTransition.SetDurationMs(lyricsEffect.LyricsScrollDuration);
|
||||
_canvasYScrollTransition.SetEasingType(lyricsEffect.LyricsScrollEasingType);
|
||||
_canvasYScrollTransition.SetInterpolator(EasingHelper.GetInterpolatorByEasingType<double>(lyricsEffect.LyricsScrollEasingType, lyricsEffect.LyricsScrollEasingMode));
|
||||
_canvasYScrollTransition.Start(_canvasTargetScrollOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,18 +196,25 @@
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsEffectSettings.LyricsScrollEasingType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeLinear" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeSmoothStep" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutSine" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutQuad" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutCubic" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutQuart" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutQuint" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutExpo" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutCirc" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutBack" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutElastic" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseInOutBounce" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseSine" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseQuad" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseCubic" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseQuart" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseQuint" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseExpo" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseCirc" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseBack" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseElastic" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingTypeEaseBounce" />
|
||||
</ComboBox>
|
||||
<dev:SettingsExpander.Items>
|
||||
<dev:SettingsCard x:Uid="SettingsPageEasingMode">
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsEffectSettings.LyricsScrollEasingMode, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingModeIn" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingModeOut" />
|
||||
<ComboBoxItem x:Uid="SettingsPageEasingModeInOut" />
|
||||
</ComboBox>
|
||||
</dev:SettingsCard>
|
||||
<dev:SettingsCard x:Uid="SettingsPageScrollTopDuration">
|
||||
<local:ExtendedSlider
|
||||
Default="500"
|
||||
|
||||
@@ -424,30 +424,6 @@
|
||||
</dev:SettingsExpander>
|
||||
<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: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>
|
||||
|
||||
<!-- 中文简体繁体偏好 -->
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="BetterLyrics.WinUI3.Controls.PluginManagerControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:dev="using:DevWinUI"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:models="using:BetterLyrics.WinUI3.Models"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Padding="36,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<TextBlock x:Uid="PluginManagerControlTitle" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
</Grid>
|
||||
|
||||
<ListView
|
||||
Grid.Row="1"
|
||||
ItemContainerStyle="{StaticResource ListViewStretchedItemContainerStyle}"
|
||||
ItemsSource="{x:Bind Plugins, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:PluginDisplayModel">
|
||||
<dev:SettingsExpander
|
||||
Description="{x:Bind Description}"
|
||||
Header="{x:Bind Name}"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}">
|
||||
<TextBlock Text="{x:Bind Version}" />
|
||||
<dev:SettingsExpander.Items>
|
||||
<dev:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left">
|
||||
<StackPanel Spacing="6">
|
||||
<local:PropertyRow Header="Author" Value="{x:Bind Author}" />
|
||||
<local:PropertyRow Header="ID" Value="{x:Bind Id}" />
|
||||
</StackPanel>
|
||||
</dev:SettingsCard>
|
||||
<dev:SettingsCard>
|
||||
<Button
|
||||
x:Uid="PluginManagerControlUninstall"
|
||||
Click="OnUninstallClick"
|
||||
Tag="{x:Bind Plugin}" />
|
||||
</dev:SettingsCard>
|
||||
</dev:SettingsExpander.Items>
|
||||
</dev:SettingsExpander>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{x:Bind IsListEmpty, Mode=OneWay}">
|
||||
<FontIcon
|
||||
FontSize="48"
|
||||
Glyph=""
|
||||
Opacity="0.3" />
|
||||
<TextBlock
|
||||
x:Uid="PluginManagerControlNoPluginsInstalled"
|
||||
Margin="0,12,0,0"
|
||||
Opacity="0.5" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="2" Margin="0,6,0,20">
|
||||
<Button
|
||||
x:Uid="PluginManagerControlInstall"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Click="OnInstallPluginClick"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,149 @@
|
||||
using BetterLyrics.Core.Interfaces;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services.PluginService;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace BetterLyrics.WinUI3.Controls
|
||||
{
|
||||
public sealed partial class PluginManagerControl : UserControl
|
||||
{
|
||||
public ObservableCollection<PluginDisplayModel> Plugins { get; } = new();
|
||||
|
||||
public Visibility IsListEmpty => Plugins.Count == 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
private readonly IPluginService _pluginService;
|
||||
|
||||
public PluginManagerControl()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
_pluginService = Ioc.Default.GetRequiredService<IPluginService>();
|
||||
|
||||
this.Loaded += (s, e) =>
|
||||
{
|
||||
RefreshPluginList();
|
||||
};
|
||||
}
|
||||
|
||||
private void RefreshPluginList()
|
||||
{
|
||||
Plugins.Clear();
|
||||
|
||||
var allPlugins = _pluginService.Plugins;
|
||||
|
||||
foreach (var plugin in allPlugins)
|
||||
{
|
||||
Plugins.Add(new PluginDisplayModel(plugin));
|
||||
}
|
||||
|
||||
Bindings.Update();
|
||||
}
|
||||
|
||||
private async void OnInstallPluginClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var file = await Helper.PickerHelper.PickSingleFileAsync<SettingsWindow>([".zip"]);
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 显示加载条...
|
||||
|
||||
// 3. 调用我们在上一步写的 InstallPlugin 方法
|
||||
_pluginService.InstallPlugin(file.Path);
|
||||
|
||||
// 4. 重新加载所有插件 (这会触发热重载)
|
||||
_pluginService.LoadPlugins();
|
||||
|
||||
// 5. 刷新界面
|
||||
RefreshPluginList();
|
||||
|
||||
ShowTip("安装成功", $"插件 {file.Name} 已安装。");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError("安装失败", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 卸载按钮点击事件
|
||||
private async void OnUninstallClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag is IPlugin plugin)
|
||||
{
|
||||
// 二次确认对话框
|
||||
ContentDialog deleteDialog = new ContentDialog
|
||||
{
|
||||
XamlRoot = this.XamlRoot,
|
||||
Title = "卸载插件",
|
||||
Content = $"确定要删除 \"{plugin.Name}\" 吗?此操作无法撤销。",
|
||||
PrimaryButtonText = "删除",
|
||||
CloseButtonText = "取消",
|
||||
DefaultButton = ContentDialogButton.Close
|
||||
};
|
||||
|
||||
var result = await deleteDialog.ShowAsync();
|
||||
|
||||
if (result == ContentDialogResult.Primary)
|
||||
{
|
||||
try
|
||||
{
|
||||
_pluginService.UninstallPlugin(plugin.Id);
|
||||
|
||||
// 暂时我们只能刷新列表演示
|
||||
RefreshPluginList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError("卸载失败", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 简单的弹窗辅助方法
|
||||
private async void ShowTip(string title, string content)
|
||||
{
|
||||
ContentDialog dialog = new ContentDialog
|
||||
{
|
||||
XamlRoot = this.XamlRoot,
|
||||
Title = title,
|
||||
Content = content,
|
||||
CloseButtonText = "关闭"
|
||||
};
|
||||
await dialog.ShowAsync();
|
||||
}
|
||||
|
||||
private async void ShowError(string title, string content)
|
||||
{
|
||||
ContentDialog dialog = new ContentDialog
|
||||
{
|
||||
XamlRoot = this.XamlRoot,
|
||||
Title = title,
|
||||
Content = content,
|
||||
CloseButtonText = "关闭"
|
||||
};
|
||||
await dialog.ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<linker>
|
||||
<assembly fullname="FlaUI.UIA3" preserve="all" />
|
||||
<assembly fullname="Interop.UIAutomationClient" preserve="all" />
|
||||
|
||||
<assembly fullname="Microsoft.EntityFrameworkCore" preserve="all" />
|
||||
<assembly fullname="Microsoft.EntityFrameworkCore.Abstractions" preserve="all" />
|
||||
<assembly fullname="Microsoft.EntityFrameworkCore.Relational" preserve="all" />
|
||||
<assembly fullname="Microsoft.EntityFrameworkCore.Sqlite" preserve="all" />
|
||||
|
||||
<assembly fullname="NAudio.Wasapi" preserve="all" />
|
||||
<assembly fullname="TagLibSharp" preserve="all" />
|
||||
|
||||
<assembly fullname="Vanara.PInvoke.DwmApi" preserve="all" />
|
||||
<assembly fullname="Vanara.PInvoke.Gdi32" preserve="all" />
|
||||
<assembly fullname="Vanara.PInvoke.Shell32" preserve="all" />
|
||||
<assembly fullname="Vanara.PInvoke.User32" preserve="all" />
|
||||
<assembly fullname="Vanara.Windows.Shell" preserve="all" />
|
||||
|
||||
</linker>
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace BetterLyrics.WinUI3.Enums;
|
||||
|
||||
public enum EaseMode
|
||||
{
|
||||
In,
|
||||
Out,
|
||||
InOut,
|
||||
}
|
||||
@@ -6,15 +6,15 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
Linear,
|
||||
SmoothStep,
|
||||
EaseInOutSine,
|
||||
EaseInOutQuad,
|
||||
EaseInOutCubic,
|
||||
EaseInOutQuart,
|
||||
EaseInOutQuint,
|
||||
EaseInOutExpo,
|
||||
EaseInOutCirc,
|
||||
EaseInOutBack,
|
||||
EaseInOutElastic,
|
||||
EaseInOutBounce,
|
||||
Sine,
|
||||
Quad,
|
||||
Cubic,
|
||||
Quart,
|
||||
Quint,
|
||||
Expo,
|
||||
Circle,
|
||||
Back,
|
||||
Elastic,
|
||||
Bounce,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,5 +14,6 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
LocalEslrcFile,
|
||||
LocalTtmlFile,
|
||||
AppleMusic,
|
||||
Plugin = 999,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,6 @@
|
||||
LocalEslrcFile,
|
||||
LocalTtmlFile,
|
||||
LibreTranslate,
|
||||
Plugin = 999,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
LocalEslrcFile,
|
||||
LocalTtmlFile,
|
||||
BetterLyrics,
|
||||
CutletDocker
|
||||
CutletDocker,
|
||||
Plugin = 999,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,10 @@ namespace BetterLyrics.WinUI3.Extensions
|
||||
new LyricsLine
|
||||
{
|
||||
StartMs = 0,
|
||||
EndMs = (int)TimeSpan.FromMinutes(99).TotalMilliseconds,
|
||||
EndMs = (int)TimeSpan.FromSeconds(30).TotalMilliseconds,
|
||||
PrimaryText = "● ● ●",
|
||||
PrimarySyllables = [new BaseLyrics { Text = "● ● ●", StartMs = 0, EndMs = (int)TimeSpan.FromMinutes(99).TotalMilliseconds }],
|
||||
PrimarySyllables = [new BaseLyrics { Text = "● ● ●", StartMs = 0, EndMs = (int)TimeSpan.FromSeconds(30).TotalMilliseconds }],
|
||||
IsPrimaryHasRealSyllableInfo = true,
|
||||
},
|
||||
],
|
||||
LanguageCode = "N/A",
|
||||
|
||||
@@ -1,114 +1,170 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public class EasingHelper
|
||||
{
|
||||
public static double EaseInOutSine(double t)
|
||||
{
|
||||
return -(Math.Cos(Math.PI * t) - 1f) / 2f;
|
||||
}
|
||||
public static double EaseInOutQuad(double t)
|
||||
{
|
||||
return t < 0.5f ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
||||
}
|
||||
#region Interpolators
|
||||
|
||||
public static double EaseInOutCubic(double t)
|
||||
public static Func<T, T, double, T> GetInterpolatorByEasingType<T>(EasingType? type, EaseMode easingMode = EaseMode.Out)
|
||||
where T : INumber<T>, IFloatingPointIeee754<T>
|
||||
{
|
||||
return t < 0.5f ? 4 * t * t * t : 1 - Math.Pow(-2 * t + 2, 3) / 2;
|
||||
}
|
||||
public static double EaseInOutQuart(double t)
|
||||
{
|
||||
return t < 0.5f ? 8 * t * t * t * t : 1 - Math.Pow(-2 * t + 2, 4) / 2;
|
||||
}
|
||||
|
||||
public static double EaseInOutQuint(double t)
|
||||
{
|
||||
return t < 0.5f ? 16 * t * t * t * t * t : 1 - Math.Pow(-2 * t + 2, 5) / 2;
|
||||
}
|
||||
|
||||
public static double EaseInOutExpo(double t)
|
||||
{
|
||||
return t == 0
|
||||
? 0
|
||||
: t == 1
|
||||
? 1
|
||||
: t < 0.5 ? Math.Pow(2, 20 * t - 10) / 2
|
||||
: (2 - Math.Pow(2, -20 * t + 10)) / 2;
|
||||
}
|
||||
|
||||
public static double EaseInOutCirc(double t)
|
||||
{
|
||||
return t < 0.5f
|
||||
? (1 - Math.Sqrt(1 - Math.Pow(2 * t, 2))) / 2
|
||||
: (Math.Sqrt(1 - Math.Pow(-2 * t + 2, 2)) + 1) / 2;
|
||||
}
|
||||
|
||||
public static double EaseInOutBack(double t)
|
||||
{
|
||||
double c1 = 1.70158f;
|
||||
double c2 = c1 * 1.525f;
|
||||
|
||||
return t < 0.5
|
||||
? (Math.Pow(2 * t, 2) * ((c2 + 1) * 2 * t - c2)) / 2
|
||||
: (Math.Pow(2 * t - 2, 2) * ((c2 + 1) * (t * 2 - 2) + c2) + 2) / 2;
|
||||
}
|
||||
|
||||
public static double EaseInOutElastic(double t)
|
||||
{
|
||||
if (t == 0 || t == 1) return t;
|
||||
double p = 0.3f;
|
||||
double s = p / 4;
|
||||
return t < 0.5f
|
||||
? -(Math.Pow(2, 20 * t - 10) * Math.Sin((20 * t - 11.125f) * (2 * Math.PI) / p)) / 2
|
||||
: (Math.Pow(2, -20 * t + 10) * Math.Sin((20 * t - 11.125f) * (2 * Math.PI) / p)) / 2 + 1;
|
||||
}
|
||||
|
||||
private static double EaseOutBounce(double t)
|
||||
{
|
||||
if (t < 4 / 11f)
|
||||
return (start, end, progress) =>
|
||||
{
|
||||
return (121 * t * t) / 16f;
|
||||
Func<T, T> easeInFunc = type switch
|
||||
{
|
||||
EasingType.Sine => EaseInSine,
|
||||
EasingType.Quad => EaseInQuad,
|
||||
EasingType.Cubic => EaseInCubic,
|
||||
EasingType.Quart => EaseInQuart,
|
||||
EasingType.Quint => EaseInQuint,
|
||||
EasingType.Expo => EaseInExpo,
|
||||
EasingType.Circle => EaseInCircle,
|
||||
EasingType.Back => EaseInBack,
|
||||
EasingType.Elastic => EaseInElastic,
|
||||
EasingType.Bounce => EaseInBounce,
|
||||
EasingType.SmoothStep => SmoothStep,
|
||||
EasingType.Linear => Linear,
|
||||
_ => EaseInQuad,
|
||||
};
|
||||
double t = Ease(progress, easingMode, easeInFunc);
|
||||
return start + ((end - start) * T.CreateChecked(t));
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static double Ease<T>(double t, EaseMode mode, Func<T, T> easeIn)
|
||||
where T : IFloatingPointIeee754<T>
|
||||
{
|
||||
t = Math.Clamp(t, 0.0, 1.0);
|
||||
|
||||
T tt = T.CreateChecked(t);
|
||||
T half = T.CreateChecked(0.5);
|
||||
T two = T.CreateChecked(2);
|
||||
T tResult = mode switch
|
||||
{
|
||||
EaseMode.In => easeIn(tt),
|
||||
EaseMode.Out => T.One - easeIn(T.One - tt),
|
||||
EaseMode.InOut => tt < half
|
||||
? easeIn(tt * two) / two
|
||||
: T.One - (easeIn((T.One - tt) * two) / two),
|
||||
_ => easeIn(tt),
|
||||
};
|
||||
|
||||
return double.CreateChecked(tResult);
|
||||
}
|
||||
|
||||
public static T EaseInSine<T>(T t) where T : IFloatingPointIeee754<T>
|
||||
{
|
||||
return T.One - T.Cos((t * T.Pi) / T.CreateChecked(2));
|
||||
}
|
||||
|
||||
public static T EaseInQuad<T>(T t) where T : INumber<T>
|
||||
{
|
||||
return t * t;
|
||||
}
|
||||
|
||||
public static T EaseInCubic<T>(T t) where T : INumber<T>
|
||||
{
|
||||
return t * t * t;
|
||||
}
|
||||
|
||||
public static T EaseInQuart<T>(T t) where T : INumber<T>
|
||||
{
|
||||
return t * t * t * t;
|
||||
}
|
||||
|
||||
public static T EaseInQuint<T>(T t) where T : INumber<T>
|
||||
{
|
||||
return t * t * t * t * t;
|
||||
}
|
||||
|
||||
public static T EaseInExpo<T>(T t) where T : IFloatingPointIeee754<T>
|
||||
{
|
||||
if (t == T.Zero)
|
||||
{
|
||||
return T.Zero;
|
||||
}
|
||||
else if (t < 8 / 11f)
|
||||
|
||||
return T.Pow(T.CreateChecked(2), (T.CreateChecked(10) * t) - T.CreateChecked(10));
|
||||
}
|
||||
|
||||
public static T EaseInCircle<T>(T t) where T : IFloatingPointIeee754<T>
|
||||
{
|
||||
return T.One - T.Sqrt(T.One - (t * t));
|
||||
}
|
||||
|
||||
public static T EaseInBack<T>(T t) where T : IFloatingPointIeee754<T>
|
||||
{
|
||||
T c1 = T.CreateChecked(1.70158);
|
||||
T c3 = c1 + T.One;
|
||||
|
||||
return (c3 * t * t * t) - (c1 * t * t);
|
||||
}
|
||||
|
||||
public static T EaseInElastic<T>(T t) where T : IFloatingPointIeee754<T>
|
||||
{
|
||||
if (t == T.Zero || t == T.One)
|
||||
{
|
||||
return (363 / 40f * t * t) - (99 / 10f * t) + 17 / 5f;
|
||||
return t;
|
||||
}
|
||||
else if (t < 9 / 10f)
|
||||
|
||||
const double springiness = 6;
|
||||
const double oscillations = 1;
|
||||
|
||||
double td = double.CreateChecked(t);
|
||||
|
||||
double expo = (Math.Exp(springiness * td) - 1.0) / (Math.Exp(springiness) - 1.0);
|
||||
double result = 0.7 * expo * Math.Sin((Math.PI * 2.0 * oscillations + (Math.PI * 0.5)) * td);
|
||||
|
||||
return T.CreateChecked(result);
|
||||
}
|
||||
|
||||
private static T EaseOutBounce<T>(T t) where T : IFloatingPointIeee754<T>
|
||||
{
|
||||
if (t < T.CreateChecked(4.0 / 11.0))
|
||||
{
|
||||
return (4356 / 361f * t * t) - (35442 / 1805f * t) + 16061 / 1805f;
|
||||
return (T.CreateChecked(121) * t * t) / T.CreateChecked(16);
|
||||
}
|
||||
else if (t < T.CreateChecked(8.0 / 11.0))
|
||||
{
|
||||
return ((T.CreateChecked(363.0 / 40.0) * t * t) - (T.CreateChecked(99.0 / 10.0) * t)) + T.CreateChecked(17.0 / 5.0);
|
||||
}
|
||||
else if (t < T.CreateChecked(9.0 / 10.0))
|
||||
{
|
||||
return ((T.CreateChecked(4356.0 / 361.0) * t * t) - (T.CreateChecked(35442.0 / 1805.0) * t)) + T.CreateChecked(16061.0 / 1805.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (54 / 5f * t * t) - (513 / 25f * t) + 268 / 25f;
|
||||
return ((T.CreateChecked(54.0 / 5.0) * t * t) - (T.CreateChecked(513.0 / 25.0) * t)) + T.CreateChecked(268.0 / 25.0);
|
||||
}
|
||||
}
|
||||
|
||||
public static double EaseInOutBounce(double t)
|
||||
public static T EaseInBounce<T>(T t) where T : IFloatingPointIeee754<T>
|
||||
{
|
||||
if (t < 0.5f)
|
||||
{
|
||||
return (1 - EaseOutBounce(1 - 2 * t)) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (1 + EaseOutBounce(2 * t - 1)) / 2;
|
||||
}
|
||||
return T.One - EaseOutBounce(T.One - t);
|
||||
}
|
||||
|
||||
public static double SmoothStep(double t)
|
||||
public static T SmoothStep<T>(T t) where T : IFloatingPointIeee754<T>
|
||||
{
|
||||
return t * t * (3f - 2f * t);
|
||||
return t * t * (T.CreateChecked(3) - (T.CreateChecked(2) * t));
|
||||
}
|
||||
|
||||
public static double CubicBezier(double t, double p0, double p1, double p2, double p3)
|
||||
public static T CubicBezier<T>(T t, T p0, T p1, T p2, T p3) where T : IFloatingPointIeee754<T>
|
||||
{
|
||||
double u = 1 - t;
|
||||
return u * u * u * p0 + 3 * u * u * t * p1 + 3 * u * t * t * p2 + t * t * t * p3;
|
||||
T u = T.One - t;
|
||||
|
||||
return (u * u * u * p0)
|
||||
+ (T.CreateChecked(3) * u * u * t * p1)
|
||||
+ (T.CreateChecked(3) * u * t * t * p2)
|
||||
+ (t * t * t * p3);
|
||||
}
|
||||
|
||||
public static double Linear(double t) => t;
|
||||
public static T Linear<T>(T t) where T : INumber<T> => t;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static BetterLyrics.WinUI3.Helper.EasingHelper;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
@@ -21,7 +22,6 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
private double _configuredDelaySeconds; // 配置的延迟时长
|
||||
|
||||
// 动画状态
|
||||
private Enums.EasingType? _easingType;
|
||||
private Func<T, T, double, T> _interpolator;
|
||||
private bool _isTransitioning;
|
||||
private double _progress; // 当前段的进度 (0.0 ~ 1.0)
|
||||
@@ -30,10 +30,11 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
public T Value => _currentValue;
|
||||
public bool IsTransitioning => _isTransitioning;
|
||||
public T TargetValue => _targetValue; // 获取当前段的目标值
|
||||
public Enums.EasingType? EasingType => _easingType;
|
||||
public double DurationSeconds => _totalDurationForAutoSplit;
|
||||
|
||||
public ValueTransition(T initialValue, double defaultTotalDuration = 0.3, EasingType? defaultEasingType = null, Func<T, T, double, T>? interpolator = null)
|
||||
public Func<T, T, double, T> Interpolator => _interpolator;
|
||||
|
||||
public ValueTransition(T initialValue, Func<T, T, double, T>? interpolator, double defaultTotalDuration = 0.3)
|
||||
{
|
||||
_currentValue = initialValue;
|
||||
_startValue = initialValue;
|
||||
@@ -43,15 +44,6 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
if (interpolator != null)
|
||||
{
|
||||
_interpolator = interpolator;
|
||||
_easingType = null;
|
||||
}
|
||||
else if (defaultEasingType != null)
|
||||
{
|
||||
SetEasingType(defaultEasingType);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetEasingType(Enums.EasingType.EaseInOutQuad);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,10 +66,9 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
_configuredDelaySeconds = seconds;
|
||||
}
|
||||
|
||||
public void SetEasingType(Enums.EasingType? easingType)
|
||||
public void SetInterpolator(Func<T, T, double, T> interpolator)
|
||||
{
|
||||
_easingType = easingType;
|
||||
_interpolator = GetInterpolatorByEasingType(easingType);
|
||||
_interpolator = interpolator;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -235,7 +226,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
#region Interpolators
|
||||
|
||||
private Func<T, T, double, T> GetInterpolatorByEasingType(Enums.EasingType? type)
|
||||
public static Func<T, T, double, T> GetInterpolatorByEasingType(EasingType? type, EaseMode easingMode)
|
||||
{
|
||||
if (typeof(T) == typeof(double))
|
||||
{
|
||||
@@ -243,25 +234,24 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
double s = (double)(object)start;
|
||||
double e = (double)(object)end;
|
||||
double t = progress;
|
||||
|
||||
// 使用 EasingHelper (假设您的项目中已有此辅助类)
|
||||
switch (type)
|
||||
Func<double, double> easeInFunc = type switch
|
||||
{
|
||||
case Enums.EasingType.EaseInOutSine: t = EasingHelper.EaseInOutSine(t); break;
|
||||
case Enums.EasingType.EaseInOutQuad: t = EasingHelper.EaseInOutQuad(t); break;
|
||||
case Enums.EasingType.EaseInOutCubic: t = EasingHelper.EaseInOutCubic(t); break;
|
||||
case Enums.EasingType.EaseInOutQuart: t = EasingHelper.EaseInOutQuart(t); break;
|
||||
case Enums.EasingType.EaseInOutQuint: t = EasingHelper.EaseInOutQuint(t); break;
|
||||
case Enums.EasingType.EaseInOutExpo: t = EasingHelper.EaseInOutExpo(t); break;
|
||||
case Enums.EasingType.EaseInOutCirc: t = EasingHelper.EaseInOutCirc(t); break;
|
||||
case Enums.EasingType.EaseInOutBack: t = EasingHelper.EaseInOutBack(t); break;
|
||||
case Enums.EasingType.EaseInOutElastic: t = EasingHelper.EaseInOutElastic(t); break;
|
||||
case Enums.EasingType.EaseInOutBounce: t = EasingHelper.EaseInOutBounce(t); break;
|
||||
case Enums.EasingType.SmoothStep: t = EasingHelper.SmoothStep(t); break;
|
||||
case Enums.EasingType.Linear: t = EasingHelper.Linear(t); break;
|
||||
default: t = EasingHelper.EaseInOutQuad(t); break;
|
||||
}
|
||||
Enums.EasingType.Sine => EaseInSine,
|
||||
Enums.EasingType.Quad => EaseInQuad,
|
||||
Enums.EasingType.Cubic => EaseInCubic,
|
||||
Enums.EasingType.Quart => EaseInQuart,
|
||||
Enums.EasingType.Quint => EaseInQuint,
|
||||
Enums.EasingType.Expo => EaseInExpo,
|
||||
Enums.EasingType.Circle => EaseInCircle,
|
||||
Enums.EasingType.Back => EaseInBack,
|
||||
Enums.EasingType.Elastic => EaseInElastic,
|
||||
Enums.EasingType.Bounce => EaseInBounce,
|
||||
Enums.EasingType.SmoothStep => SmoothStep,
|
||||
Enums.EasingType.Linear => Linear,
|
||||
_ => EaseInQuad,
|
||||
};
|
||||
double t = Ease(progress, easingMode, easeInFunc);
|
||||
|
||||
return (T)(object)(s + (e - s) * t);
|
||||
};
|
||||
|
||||
@@ -68,11 +68,17 @@ namespace BetterLyrics.WinUI3.Logic
|
||||
for (int i = safeStart; i <= safeEnd; i++)
|
||||
{
|
||||
var line = lines[i];
|
||||
|
||||
var lineHeight = line.PrimaryLineHeight;
|
||||
|
||||
if (lineHeight == null || lineHeight <= 0) continue;
|
||||
|
||||
bool isWordAnimationEnabled = lyricsEffect.WordByWordEffectMode switch
|
||||
{
|
||||
Enums.WordByWordEffectMode.Auto => line.IsPrimaryHasRealSyllableInfo,
|
||||
Enums.WordByWordEffectMode.Always => true,
|
||||
Enums.WordByWordEffectMode.Never => false,
|
||||
_ => line.IsPrimaryHasRealSyllableInfo
|
||||
};
|
||||
|
||||
double targetCharFloat = lyricsEffect.IsLyricsFloatAnimationAmountAutoAdjust
|
||||
? lineHeight.Value * 0.1
|
||||
: lyricsEffect.LyricsFloatAnimationAmount;
|
||||
@@ -83,7 +89,7 @@ namespace BetterLyrics.WinUI3.Logic
|
||||
? 1.15
|
||||
: lyricsEffect.LyricsScaleEffectAmount / 100.0;
|
||||
|
||||
var maxAnimationDurationMs = Math.Max(line.EndMs - currentPositionMs, 0);
|
||||
var maxAnimationDurationMs = Math.Max(line.EndMs ?? 0 - currentPositionMs, 0);
|
||||
|
||||
bool isSecondaryLinePlaying = line.GetIsPlaying(currentPositionMs);
|
||||
bool isSecondaryLinePlayingChanged = line.IsPlayingLastFrame != isSecondaryLinePlaying;
|
||||
@@ -171,15 +177,15 @@ namespace BetterLyrics.WinUI3.Logic
|
||||
line.ColorTransition.SetDelay(yScrollDelay);
|
||||
line.ColorTransition.Start(isSecondaryLinePlaying ? fgColor : bgColor);
|
||||
|
||||
line.AngleTransition.SetEasingType(canvasYScrollTransition.EasingType);
|
||||
line.AngleTransition.SetInterpolator(canvasYScrollTransition.Interpolator);
|
||||
line.AngleTransition.SetDuration(yScrollDuration);
|
||||
line.AngleTransition.SetDelay(yScrollDelay);
|
||||
line.AngleTransition.Start(
|
||||
(isFanEnabled && !isMouseScrolling) ?
|
||||
Math.PI * (fanAngleRad / 180.0) * distanceFactor * (i > primaryPlayingLineIndex ? 1 : -1) :
|
||||
fanAngleRad * distanceFactor * (i > primaryPlayingLineIndex ? 1 : -1) :
|
||||
0);
|
||||
|
||||
line.YOffsetTransition.SetEasingType(canvasYScrollTransition.EasingType);
|
||||
line.YOffsetTransition.SetInterpolator(canvasYScrollTransition.Interpolator);
|
||||
line.YOffsetTransition.SetDuration(yScrollDuration);
|
||||
line.YOffsetTransition.SetDelay(yScrollDelay);
|
||||
// 设计之初是当 isLayoutChanged 为真时 jumpTo
|
||||
@@ -187,98 +193,100 @@ namespace BetterLyrics.WinUI3.Logic
|
||||
line.YOffsetTransition.Start(targetYScrollOffset);
|
||||
}
|
||||
|
||||
if (isLayoutChanged || isSecondaryLinePlayingChanged)
|
||||
if (isWordAnimationEnabled)
|
||||
{
|
||||
// 辉光动画
|
||||
if (isGlowEnabled && lyricsEffect.LyricsGlowEffectScope == Enums.LyricsEffectScope.LineStartToCurrentChar
|
||||
&& isSecondaryLinePlaying)
|
||||
if (isSecondaryLinePlayingChanged)
|
||||
{
|
||||
foreach (var renderChar in line.PrimaryRenderChars)
|
||||
// 辉光动画
|
||||
if (isGlowEnabled && lyricsEffect.LyricsGlowEffectScope == Enums.LyricsEffectScope.LineStartToCurrentChar
|
||||
&& isSecondaryLinePlaying)
|
||||
{
|
||||
var stepInOutDuration = Math.Min(Time.AnimationDuration.TotalMilliseconds, maxAnimationDurationMs) / 2.0 / 1000.0;
|
||||
var stepLastingDuration = Math.Max(maxAnimationDurationMs / 1000.0 - stepInOutDuration * 2, 0);
|
||||
renderChar.GlowTransition.Start(
|
||||
new Models.Keyframe<double>(targetCharGlow, stepInOutDuration),
|
||||
new Models.Keyframe<double>(targetCharGlow, stepLastingDuration),
|
||||
new Models.Keyframe<double>(0, stepInOutDuration)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 浮动动画
|
||||
if (isFloatEnabled)
|
||||
{
|
||||
foreach (var renderChar in line.PrimaryRenderChars)
|
||||
{
|
||||
renderChar.FloatTransition.Start(isSecondaryLinePlaying ? targetCharFloat : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 字符动画
|
||||
foreach (var renderChar in line.PrimaryRenderChars)
|
||||
{
|
||||
renderChar.ProgressPlayed = renderChar.GetPlayProgress(currentPositionMs);
|
||||
|
||||
bool isCharPlaying = renderChar.GetIsPlaying(currentPositionMs);
|
||||
bool isCharPlayingChanged = renderChar.IsPlayingLastFrame != isCharPlaying;
|
||||
|
||||
if (isCharPlayingChanged)
|
||||
{
|
||||
if (isFloatEnabled)
|
||||
{
|
||||
renderChar.FloatTransition.SetDurationMs(Math.Min(lyricsEffect.LyricsFloatAnimationDuration, maxAnimationDurationMs));
|
||||
renderChar.FloatTransition.Start(0);
|
||||
}
|
||||
|
||||
renderChar.IsPlayingLastFrame = isCharPlaying;
|
||||
}
|
||||
}
|
||||
|
||||
// 音节动画
|
||||
foreach (var syllable in line.PrimaryRenderSyllables)
|
||||
{
|
||||
bool isSyllablePlaying = syllable.GetIsPlaying(currentPositionMs);
|
||||
bool isSyllablePlayingChanged = syllable.IsPlayingLastFrame != isSyllablePlaying;
|
||||
|
||||
if (isSyllablePlayingChanged)
|
||||
{
|
||||
if (isScaleEnabled && isSyllablePlaying)
|
||||
{
|
||||
foreach (var renderChar in syllable.ChildrenRenderLyricsChars)
|
||||
foreach (var renderChar in line.PrimaryRenderChars)
|
||||
{
|
||||
if (syllable.DurationMs >= lyricsEffect.LyricsScaleEffectLongSyllableDuration)
|
||||
{
|
||||
var stepDuration = Math.Min(syllable.DurationMs, maxAnimationDurationMs) / 2.0 / 1000.0;
|
||||
renderChar.ScaleTransition.Start(
|
||||
new Models.Keyframe<double>(targetCharScale, stepDuration),
|
||||
new Models.Keyframe<double>(1.0, stepDuration)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isGlowEnabled && isSyllablePlaying && lyricsEffect.LyricsGlowEffectScope == Enums.LyricsEffectScope.LongDurationSyllable
|
||||
&& syllable.DurationMs >= lyricsEffect.LyricsGlowEffectLongSyllableDuration)
|
||||
{
|
||||
foreach (var renderChar in syllable.ChildrenRenderLyricsChars)
|
||||
{
|
||||
var stepDuration = Math.Min(syllable.DurationMs, maxAnimationDurationMs) / 2.0 / 1000.0;
|
||||
var stepInOutDuration = Math.Min(Time.AnimationDuration.TotalMilliseconds, maxAnimationDurationMs) / 2.0 / 1000.0;
|
||||
var stepLastingDuration = Math.Max(maxAnimationDurationMs / 1000.0 - stepInOutDuration * 2, 0);
|
||||
renderChar.GlowTransition.Start(
|
||||
new Models.Keyframe<double>(targetCharGlow, stepDuration),
|
||||
new Models.Keyframe<double>(0, stepDuration)
|
||||
new Models.Keyframe<double>(targetCharGlow, stepInOutDuration),
|
||||
new Models.Keyframe<double>(targetCharGlow, stepLastingDuration),
|
||||
new Models.Keyframe<double>(0, stepInOutDuration)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
syllable.IsPlayingLastFrame = isSyllablePlaying;
|
||||
// 浮动动画
|
||||
if (isFloatEnabled)
|
||||
{
|
||||
foreach (var renderChar in line.PrimaryRenderChars)
|
||||
{
|
||||
renderChar.FloatTransition.Start(isSecondaryLinePlaying ? targetCharFloat : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 使动画步进一帧
|
||||
foreach (var renderChar in line.PrimaryRenderChars)
|
||||
{
|
||||
renderChar.Update(elapsedTime);
|
||||
// 字符动画
|
||||
foreach (var renderChar in line.PrimaryRenderChars)
|
||||
{
|
||||
renderChar.ProgressPlayed = renderChar.GetPlayProgress(currentPositionMs);
|
||||
|
||||
bool isCharPlaying = renderChar.GetIsPlaying(currentPositionMs);
|
||||
bool isCharPlayingChanged = renderChar.IsPlayingLastFrame != isCharPlaying;
|
||||
|
||||
if (isCharPlayingChanged)
|
||||
{
|
||||
if (isFloatEnabled)
|
||||
{
|
||||
renderChar.FloatTransition.SetDurationMs(Math.Min(lyricsEffect.LyricsFloatAnimationDuration, maxAnimationDurationMs));
|
||||
renderChar.FloatTransition.Start(0);
|
||||
}
|
||||
|
||||
renderChar.IsPlayingLastFrame = isCharPlaying;
|
||||
}
|
||||
}
|
||||
|
||||
// 音节动画
|
||||
foreach (var syllable in line.PrimaryRenderSyllables)
|
||||
{
|
||||
bool isSyllablePlaying = syllable.GetIsPlaying(currentPositionMs);
|
||||
bool isSyllablePlayingChanged = syllable.IsPlayingLastFrame != isSyllablePlaying;
|
||||
|
||||
if (isSyllablePlayingChanged)
|
||||
{
|
||||
if (isScaleEnabled && isSyllablePlaying)
|
||||
{
|
||||
foreach (var renderChar in syllable.ChildrenRenderLyricsChars)
|
||||
{
|
||||
if (syllable.DurationMs >= lyricsEffect.LyricsScaleEffectLongSyllableDuration)
|
||||
{
|
||||
var stepDuration = Math.Min(syllable.DurationMs, maxAnimationDurationMs) / 2.0 / 1000.0;
|
||||
renderChar.ScaleTransition.Start(
|
||||
new Models.Keyframe<double>(targetCharScale, stepDuration),
|
||||
new Models.Keyframe<double>(1.0, stepDuration)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isGlowEnabled && isSyllablePlaying && lyricsEffect.LyricsGlowEffectScope == Enums.LyricsEffectScope.LongDurationSyllable
|
||||
&& syllable.DurationMs >= lyricsEffect.LyricsGlowEffectLongSyllableDuration)
|
||||
{
|
||||
foreach (var renderChar in syllable.ChildrenRenderLyricsChars)
|
||||
{
|
||||
var stepDuration = Math.Min(syllable.DurationMs, maxAnimationDurationMs) / 2.0 / 1000.0;
|
||||
renderChar.GlowTransition.Start(
|
||||
new Models.Keyframe<double>(targetCharGlow, stepDuration),
|
||||
new Models.Keyframe<double>(0, stepDuration)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
syllable.IsPlayingLastFrame = isSyllablePlaying;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var renderChar in line.PrimaryRenderChars)
|
||||
{
|
||||
renderChar.Update(elapsedTime);
|
||||
}
|
||||
}
|
||||
|
||||
line.Update(elapsedTime);
|
||||
|
||||
@@ -215,7 +215,7 @@ namespace BetterLyrics.WinUI3.Logic
|
||||
lanesEndMs.Add(0);
|
||||
}
|
||||
|
||||
lanesEndMs[assignedLane] = end;
|
||||
lanesEndMs[assignedLane] = end ?? 0;
|
||||
line.LaneIndex = assignedLane;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace BetterLyrics.WinUI3.Logic
|
||||
|
||||
if (line == null) return state;
|
||||
|
||||
double lineEndMs = line.EndMs;
|
||||
double lineEndMs = line.EndMs ?? 0;
|
||||
|
||||
// 还没到
|
||||
if (currentTimeMs < line.StartMs) return state;
|
||||
@@ -91,7 +91,7 @@ namespace BetterLyrics.WinUI3.Logic
|
||||
switch (wordByWordEffectMode)
|
||||
{
|
||||
case WordByWordEffectMode.Auto:
|
||||
if (line.PrimaryRenderSyllables.Count > 1)
|
||||
if (line.IsPrimaryHasRealSyllableInfo)
|
||||
{
|
||||
return CalculateSyllableProgress(currentTimeMs, line, lineEndMs);
|
||||
}
|
||||
@@ -106,7 +106,7 @@ namespace BetterLyrics.WinUI3.Logic
|
||||
state.SyllableProgress = 1f;
|
||||
return state;
|
||||
case WordByWordEffectMode.Always:
|
||||
if (line.PrimaryRenderSyllables.Count > 1)
|
||||
if (line.IsPrimaryHasRealSyllableInfo)
|
||||
{
|
||||
return CalculateSyllableProgress(currentTimeMs, line, lineEndMs);
|
||||
}
|
||||
@@ -129,8 +129,7 @@ namespace BetterLyrics.WinUI3.Logic
|
||||
var timing = line.PrimaryRenderSyllables[i];
|
||||
var nextTiming = (i + 1 < count) ? line.PrimaryRenderSyllables[i + 1] : null;
|
||||
|
||||
//double timingEndMs = timing.EndMs ?? nextTiming?.StartMs ?? lineEndMs;
|
||||
double timingEndMs = timing.EndMs;
|
||||
double timingEndMs = timing.EndMs ?? 0;
|
||||
|
||||
// 在当前字范围内
|
||||
if (time >= timing.StartMs && time <= timingEndMs)
|
||||
|
||||
@@ -7,8 +7,8 @@ namespace BetterLyrics.WinUI3.Models.Lyrics
|
||||
public class BaseLyrics
|
||||
{
|
||||
public int StartMs { get; set; }
|
||||
public int EndMs { get; set; }
|
||||
public int DurationMs => EndMs - StartMs;
|
||||
public int? EndMs { get; set; } = null;
|
||||
public int DurationMs => Math.Max((EndMs ?? 0) - StartMs, 0);
|
||||
|
||||
public string Text { get; set; } = "";
|
||||
public int Length => Text.Length;
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace BetterLyrics.WinUI3.Models.Lyrics
|
||||
public new string Text => PrimaryText;
|
||||
public new int StartIndex = 0;
|
||||
|
||||
public bool IsPrimaryHasRealSyllableInfo { get; set; } = false;
|
||||
|
||||
public LyricsLine()
|
||||
{
|
||||
for (int charStartIndex = 0; charStartIndex < PrimaryText.Length; charStartIndex++)
|
||||
|
||||
@@ -20,18 +20,18 @@ namespace BetterLyrics.WinUI3.Models.Lyrics
|
||||
{
|
||||
ScaleTransition = new(
|
||||
initialValue: 1.0,
|
||||
defaultTotalDuration: Time.AnimationDuration.TotalSeconds,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: Time.AnimationDuration.TotalSeconds
|
||||
);
|
||||
GlowTransition = new(
|
||||
initialValue: 0,
|
||||
defaultTotalDuration: Time.AnimationDuration.TotalSeconds,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: Time.AnimationDuration.TotalSeconds
|
||||
);
|
||||
FloatTransition = new(
|
||||
initialValue: 0,
|
||||
defaultTotalDuration: Time.LongAnimationDuration.TotalSeconds,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: Time.LongAnimationDuration.TotalSeconds
|
||||
);
|
||||
LayoutRect = layoutRect;
|
||||
}
|
||||
|
||||
@@ -76,47 +76,49 @@ namespace BetterLyrics.WinUI3.Models.Lyrics
|
||||
|
||||
public double? PrimaryLineHeight => PrimaryRenderChars.FirstOrDefault()?.LayoutRect.Height;
|
||||
|
||||
public bool IsPrimaryHasRealSyllableInfo { get; set; }
|
||||
|
||||
public RenderLyricsLine(LyricsLine lyricsLine) : base(lyricsLine)
|
||||
{
|
||||
AngleTransition = new(
|
||||
initialValue: 0,
|
||||
defaultTotalDuration: AnimationDuration,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: AnimationDuration
|
||||
);
|
||||
BlurAmountTransition = new(
|
||||
initialValue: 0,
|
||||
defaultTotalDuration: AnimationDuration,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: AnimationDuration
|
||||
);
|
||||
PhoneticOpacityTransition = new(
|
||||
initialValue: 0,
|
||||
defaultTotalDuration: AnimationDuration,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: AnimationDuration
|
||||
);
|
||||
PlayedOriginalOpacityTransition = new(
|
||||
initialValue: 0,
|
||||
defaultTotalDuration: AnimationDuration,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: AnimationDuration
|
||||
);
|
||||
UnplayedOriginalOpacityTransition = new(
|
||||
initialValue: 0,
|
||||
defaultTotalDuration: AnimationDuration,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: AnimationDuration
|
||||
);
|
||||
TranslatedOpacityTransition = new(
|
||||
initialValue: 0,
|
||||
defaultTotalDuration: AnimationDuration,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: AnimationDuration
|
||||
);
|
||||
ScaleTransition = new(
|
||||
initialValue: 0,
|
||||
defaultTotalDuration: AnimationDuration,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: AnimationDuration
|
||||
);
|
||||
YOffsetTransition = new(
|
||||
initialValue: 0,
|
||||
defaultTotalDuration: AnimationDuration,
|
||||
defaultEasingType: EasingType.EaseInOutSine
|
||||
EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Sine),
|
||||
defaultTotalDuration: AnimationDuration
|
||||
);
|
||||
ColorTransition = new(
|
||||
initialValue: Colors.Transparent,
|
||||
@@ -130,6 +132,7 @@ namespace BetterLyrics.WinUI3.Models.Lyrics
|
||||
PrimaryText = lyricsLine.PrimaryText;
|
||||
SecondaryText = lyricsLine.SecondaryText;
|
||||
PrimaryRenderSyllables = lyricsLine.PrimarySyllables.Select(x => new RenderLyricsSyllable(x)).ToList();
|
||||
IsPrimaryHasRealSyllableInfo = lyricsLine.IsPrimaryHasRealSyllableInfo;
|
||||
}
|
||||
|
||||
public void UpdateCenterPosition(double maxWidth, TextAlignmentType type)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using BetterLyrics.Core.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public class PluginDisplayModel
|
||||
{
|
||||
public IPlugin Plugin { get; }
|
||||
|
||||
public string Name => Plugin.Name;
|
||||
public string Description => Plugin.Description;
|
||||
public string Id => Plugin.Id;
|
||||
public string Author => Plugin.Author;
|
||||
public string Version => "v1.0.0"; // 如果您的接口有 Version 字段就读接口的
|
||||
|
||||
public string Glyph => !string.IsNullOrEmpty(Name) ? Name.Substring(0, 1) : "?";
|
||||
|
||||
public PluginDisplayModel(IPlugin plugin)
|
||||
{
|
||||
Plugin = plugin;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using static BetterLyrics.WinUI3.Helper.EasingHelper;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
{
|
||||
@@ -29,6 +30,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsFloatAnimationDuration { get; set; } = 450; // 450ms
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial EasingType LyricsScrollEasingType { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial EaseMode LyricsScrollEasingMode { get; set; } = EaseMode.Out;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollDuration { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollTopDuration { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollBottomDuration { get; set; }
|
||||
@@ -79,6 +81,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
LyricsFloatAnimationDuration = this.LyricsFloatAnimationDuration,
|
||||
|
||||
LyricsScrollEasingType = this.LyricsScrollEasingType,
|
||||
LyricsScrollEasingMode = this.LyricsScrollEasingMode,
|
||||
LyricsScrollDuration = this.LyricsScrollDuration,
|
||||
LyricsScrollTopDuration = this.LyricsScrollTopDuration,
|
||||
LyricsScrollBottomDuration = this.LyricsScrollBottomDuration,
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
[ObservableProperty] public partial Rect DemoMonitorBounds { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial DockPlacement DockPlacement { get; set; } = DockPlacement.Top;
|
||||
[ObservableProperty] public partial LyricsStyleSettings LyricsStyleSettings { get; set; } = new();
|
||||
[ObservableProperty] public partial LyricsEffectSettings LyricsEffectSettings { get; set; } = new(500, 500, 500, EasingType.EaseInOutQuad);
|
||||
[ObservableProperty] public partial LyricsEffectSettings LyricsEffectSettings { get; set; } = new(500, 500, 500, EasingType.Quad);
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsBackgroundSettings LyricsBackgroundSettings { get; set; } = new();
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial AlbumArtAreaStyleSettings AlbumArtLayoutSettings { get; set; } = new();
|
||||
[ObservableProperty] public partial AlbumArtAreaEffectSettings AlbumArtAreaEffectSettings { get; set; } = new();
|
||||
|
||||
@@ -13,7 +13,6 @@ 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() { }
|
||||
|
||||
@@ -40,26 +40,14 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
|
||||
startIndex += text.Length;
|
||||
}
|
||||
|
||||
int lineEndMs = 0;
|
||||
|
||||
if (syllables.Count > 0)
|
||||
{
|
||||
var lastSyllable = syllables[syllables.Count - 1];
|
||||
if (string.IsNullOrWhiteSpace(lastSyllable.Text))
|
||||
{
|
||||
lineEndMs = lastSyllable.StartMs;
|
||||
syllables.RemoveAt(syllables.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (syllables.Count > 1)
|
||||
{
|
||||
lrcLines.Add(new LyricsLine
|
||||
{
|
||||
StartMs = syllables[0].StartMs,
|
||||
EndMs = lineEndMs,
|
||||
PrimaryText = string.Concat(syllables.Select(s => s.Text)),
|
||||
PrimarySyllables = syllables
|
||||
PrimarySyllables = syllables,
|
||||
IsPrimaryHasRealSyllableInfo = true
|
||||
});
|
||||
}
|
||||
else
|
||||
@@ -81,7 +69,13 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
|
||||
content = bracketRegex!.Replace(line, "").Trim();
|
||||
if (content == "//") content = "";
|
||||
|
||||
lrcLines.Add(new LyricsLine { StartMs = lineStartMs, PrimaryText = content });
|
||||
var lyricsLine = new LyricsLine
|
||||
{
|
||||
StartMs = lineStartMs,
|
||||
PrimaryText = content,
|
||||
IsPrimaryHasRealSyllableInfo = false
|
||||
};
|
||||
lrcLines.Add(lyricsLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,5 +119,6 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,8 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
|
||||
var lineWrite = new LyricsLine
|
||||
{
|
||||
StartMs = lineRead.StartTime ?? 0,
|
||||
EndMs = lineRead.EndTime ?? (nextLineRead?.StartTime ?? 0),
|
||||
PrimaryText = lineRead.Text,
|
||||
PrimarySyllables = [],
|
||||
IsPrimaryHasRealSyllableInfo = true,
|
||||
};
|
||||
|
||||
var syllables = (lineRead as Lyricify.Lyrics.Models.SyllableLineInfo)?.Syllables;
|
||||
|
||||
@@ -127,7 +127,8 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
|
||||
StartMs = containerStartMs,
|
||||
EndMs = containerEndMs,
|
||||
PrimaryText = fullOriginalText,
|
||||
PrimarySyllables = syllables
|
||||
PrimarySyllables = syllables,
|
||||
IsPrimaryHasRealSyllableInfo = true,
|
||||
});
|
||||
|
||||
var transSpan = container.Elements()
|
||||
@@ -151,7 +152,8 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
|
||||
{
|
||||
StartMs = startMs,
|
||||
EndMs = endMs,
|
||||
PrimaryText = text
|
||||
PrimaryText = text,
|
||||
IsPrimaryHasRealSyllableInfo = false,
|
||||
});
|
||||
}
|
||||
else
|
||||
@@ -160,7 +162,8 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
|
||||
{
|
||||
StartMs = startMs,
|
||||
EndMs = endMs,
|
||||
PrimaryText = ""
|
||||
PrimaryText = "",
|
||||
IsPrimaryHasRealSyllableInfo = false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,9 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
|
||||
LoadTransliteration(lyricsSearchResult);
|
||||
GenerateTransliterationLyricsData();
|
||||
|
||||
EnsureEndMs(lyricsSearchResult?.Duration);
|
||||
EnsureSyllables();
|
||||
|
||||
return _lyricsDataArr;
|
||||
}
|
||||
|
||||
@@ -126,7 +129,7 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
|
||||
{
|
||||
romaji = await transliterationService.TransliterateText(main.WrappedOriginalText, PhoneticHelper.RomanCode, token);
|
||||
_lyricsDataArr.FirstOrDefault()?.SetTransliteration(romaji);
|
||||
transliterationSearchProvider = TransliterationSearchProvider.CutletDocker;
|
||||
transliterationSearchProvider = TransliterationSearchProvider.Plugin;
|
||||
}
|
||||
catch (TaskCanceledException) { }
|
||||
catch (Exception)
|
||||
@@ -271,5 +274,84 @@ namespace BetterLyrics.WinUI3.Parsers.LyricsParser
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureEndMs(double? duration)
|
||||
{
|
||||
foreach (var lyricsData in _lyricsDataArr)
|
||||
{
|
||||
var lines = lyricsData.LyricsLines;
|
||||
// 计算结束时间
|
||||
for (int i = 0; i < lines.Count; i++)
|
||||
{
|
||||
// 计算行结束时间
|
||||
if (lines[i].EndMs == null)
|
||||
{
|
||||
if (i + 1 < lines.Count)
|
||||
{
|
||||
lines[i].EndMs = lines[i + 1].StartMs;
|
||||
}
|
||||
else
|
||||
{
|
||||
lines[i].EndMs = (int)(duration ?? 0) * 1000;
|
||||
}
|
||||
}
|
||||
// 计算音节结束时间
|
||||
for (int j = 0; j < lines[i].PrimarySyllables.Count; j++)
|
||||
{
|
||||
var syllable = lines[i].PrimarySyllables[j];
|
||||
if (syllable.EndMs == null)
|
||||
{
|
||||
if (j < lines[i].PrimarySyllables.Count - 1)
|
||||
{
|
||||
syllable.EndMs = lines[i].PrimarySyllables[j + 1].StartMs;
|
||||
}
|
||||
else
|
||||
{
|
||||
syllable.EndMs = lines[i].EndMs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoke this after <see cref="EnsureEndMs"/>
|
||||
/// </summary>
|
||||
private void EnsureSyllables()
|
||||
{
|
||||
foreach (var lyricsData in _lyricsDataArr)
|
||||
{
|
||||
if (lyricsData == null) continue;
|
||||
|
||||
var lines = lyricsData.LyricsLines;
|
||||
if (lines == null) continue;
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (line == null) continue;
|
||||
if (line.IsPrimaryHasRealSyllableInfo) continue;
|
||||
if (line.PrimarySyllables.Count > 0) continue;
|
||||
|
||||
var content = line.PrimaryText;
|
||||
var length = content.Length;
|
||||
if (length == 0) continue;
|
||||
|
||||
var avgSyllableDuration = line.DurationMs / length;
|
||||
if (avgSyllableDuration == 0) continue;
|
||||
|
||||
for (int j = 0; j < length; j++)
|
||||
{
|
||||
line.PrimarySyllables.Add(new BaseLyrics
|
||||
{
|
||||
Text = content[j].ToString(),
|
||||
StartIndex = j,
|
||||
StartMs = line.StartMs + avgSyllableDuration * j,
|
||||
EndMs = line.StartMs + avgSyllableDuration * (j + 1),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
<linker>
|
||||
<assembly fullname="Microsoft.Extensions.Logging.Abstractions" preserve="all" />
|
||||
<assembly fullname="System.Collections" preserve="all" />
|
||||
<assembly fullname="System.Collections.Concurrent" preserve="all" />
|
||||
<assembly fullname="System.ComponentModel" preserve="all" />
|
||||
<assembly fullname="System.ComponentModel.Annotations" preserve="all" />
|
||||
<assembly fullname="System.ComponentModel.Primitives" preserve="all" />
|
||||
<assembly fullname="System.Diagnostics.Process" preserve="all" />
|
||||
<assembly fullname="System.Drawing.Primitives" preserve="all" />
|
||||
<assembly fullname="System.IO.MemoryMappedFiles" preserve="all" />
|
||||
<assembly fullname="System.Linq" preserve="all" />
|
||||
<assembly fullname="System.Memory" preserve="all" />
|
||||
<assembly fullname="System.Net.Http" preserve="all" />
|
||||
<assembly fullname="System.Net.Mail" preserve="all" />
|
||||
<assembly fullname="System.Numerics.Tensors" preserve="all" />
|
||||
<assembly fullname="System.Numerics.Vectors" preserve="all" />
|
||||
<assembly fullname="System.Runtime" preserve="all" />
|
||||
<assembly fullname="System.Runtime.InteropServices" preserve="all" />
|
||||
<assembly fullname="System.Runtime.Intrinsics" preserve="all" />
|
||||
<assembly fullname="System.Security.Cryptography" preserve="all" />
|
||||
<assembly fullname="System.Text.Encodings.Web" preserve="all" />
|
||||
<assembly fullname="System.Text.Json" preserve="all" />
|
||||
<assembly fullname="System.Text.RegularExpressions" preserve="all" />
|
||||
<assembly fullname="System.Threading" preserve="all" />
|
||||
<assembly fullname="System.Threading.Tasks.Parallel" preserve="all" />
|
||||
<assembly fullname="BetterLyrics.WinUI3">
|
||||
<type fullname="BetterLyrics.WinUI3.PluginConfigs.BetterLyrics_Plugins_AI_Config" preserve="all" />
|
||||
</assembly>
|
||||
</linker>
|
||||
@@ -0,0 +1,415 @@
|
||||
// Auto-Generated by PluginAnalyzer
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace BetterLyrics.WinUI3.PluginConfigs;
|
||||
internal static class BetterLyrics_Plugins_AI_Config
|
||||
{
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Microsoft.Win32.SafeHandles.SafeMemoryMappedViewHandle))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Action<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Action<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.AppContext))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.AppDomain))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ArgumentException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ArgumentNullException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ArgumentOutOfRangeException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Array))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ArraySegment<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ArrayTypeMismatchException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.AsyncCallback))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Attribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.AttributeTargets))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.AttributeUsageAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Base64FormattingOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Boolean))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffer))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.ArrayPool<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.Binary.BinaryPrimitives))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.IBufferWriter<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.IMemoryOwner<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.IPinnable))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.MemoryHandle))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.MemoryManager<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.ReadOnlySequence<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.ReadOnlySequence<>.Enumerator))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.SearchValues))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.SearchValues<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffers.Text.Base64))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Byte))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Char))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.CLSCompliantAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.CodeDom.Compiler.GeneratedCodeAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.BitArray))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Concurrent.ConcurrentDictionary<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.Dictionary<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.Dictionary<,>.Enumerator))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.Dictionary<,>.KeyCollection))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.Dictionary<,>.ValueCollection))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.EqualityComparer<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.HashSet<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.HashSet<>.Enumerator))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IAsyncEnumerable<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IAsyncEnumerator<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.ICollection<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IComparer<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IDictionary<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IEnumerable<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IEnumerator<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IEqualityComparer<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IList<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IReadOnlyCollection<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IReadOnlyDictionary<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IReadOnlyList<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.KeyNotFoundException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.KeyValuePair<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.List<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.List<>.Enumerator))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.Queue<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.ICollection))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.IEnumerable))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.IEnumerator))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.IList))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.AllowedValuesAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.Base64StringAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.DataType))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.DataTypeAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.DeniedValuesAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.EmailAddressAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.LengthAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.MaxLengthAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.MinLengthAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.RangeAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.RegularExpressionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.StringLengthAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DataAnnotations.UrlAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DescriptionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.DisplayNameAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.EditorBrowsableAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.EditorBrowsableState))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.InvalidEnumArgumentException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Convert))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.DateTime))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.DateTimeKind))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.DateTimeOffset))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.DBNull))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Decimal))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Delegate))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.CodeAnalysis.AllowNullAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.CodeAnalysis.ExperimentalAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.CodeAnalysis.NotNullAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.CodeAnalysis.NotNullWhenAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DataReceivedEventArgs))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DataReceivedEventHandler))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.Debug))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggableAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggableAttribute.DebuggingModes))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggerBrowsableAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggerBrowsableState))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggerDisplayAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggerHiddenAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggerStepThroughAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggerTypeProxyAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.Process))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.ProcessStartInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.DllNotFoundException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Double))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Drawing.Rectangle))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Enum))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Environment))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Exception))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.FlagsAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.FormatException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Func<,,,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Func<,,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Func<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Func<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.GC))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Globalization.CultureInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Guid))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Half))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.HashCode))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IAsyncDisposable))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IAsyncResult))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IConvertible))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IDisposable))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IEquatable<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IFormatProvider))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Index))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IndexOutOfRangeException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Int16))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Int32))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Int64))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IntPtr))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.InvalidCastException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.InvalidOperationException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.Directory))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.DirectoryInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.File))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.FileAccess))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.FileMode))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.FileStream))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.MemoryMappedFiles.MemoryMappedFile))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.MemoryMappedFiles.MemoryMappedViewAccessor))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.MemoryStream))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.Path))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.SeekOrigin))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.Stream))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.UnmanagedMemoryStream))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IProgress<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IServiceProvider))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Linq.Enumerable))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Linq.IOrderedEnumerable<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Math))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.MathF))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Memory<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.MemoryExtensions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.MemoryExtensions.TryWriteInterpolatedStringHandler))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.MulticastDelegate))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Net.Http.Headers.MediaTypeHeaderValue))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Net.Mime.MediaTypeNames))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Net.WebUtility))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.NotSupportedException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Nullable))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Nullable<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Numerics.BitOperations))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Numerics.Tensors.TensorPrimitives))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Numerics.Vector))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Numerics.Vector<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Object))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ObjectDisposedException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ObsoleteAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.OperatingSystem))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.OperationCanceledException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.OverflowException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ParamArrayAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.PlatformNotSupportedException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Predicate<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Random))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Range))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ReadOnlyMemory<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ReadOnlySpan<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.Assembly))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyCompanyAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyConfigurationAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyCopyrightAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyDefaultAliasAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyDescriptionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyFileVersionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyInformationalVersionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyMetadataAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyProductAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyTitleAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.Binder))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.BindingFlags))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.ConstructorInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.CustomAttributeExtensions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.DefaultMemberAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.ICustomAttributeProvider))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.MemberInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.MethodBase))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.MethodInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.ParameterInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.ParameterModifier))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.PropertyInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.AsyncIteratorMethodBuilder))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.AsyncStateMachineAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.AsyncTaskMethodBuilder))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.AsyncTaskMethodBuilder<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.CompilationRelaxationsAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConditionalWeakTable<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConditionalWeakTable<,>.CreateValueCallback))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable<>.Enumerator))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConfiguredTaskAwaitable))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConfiguredTaskAwaitable<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConfiguredTaskAwaitable<>.ConfiguredTaskAwaiter))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<>.ConfiguredValueTaskAwaiter))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.DefaultInterpolatedStringHandler))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.EnumeratorCancellationAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ExtensionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.FixedBufferAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.IAsyncStateMachine))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.InlineArrayAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.InternalsVisibleToAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.IsByRefLikeAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.IsExternalInit))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.IsReadOnlyAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.IsUnmanagedAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.IteratorStateMachineAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.NullableAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.NullableContextAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.RefSafetyRulesAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.RequiresLocationAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.RuntimeCompatibilityAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.RuntimeHelpers))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.SkipLocalsInitAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.TaskAwaiter))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.TaskAwaiter<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.TupleElementNamesAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.Unsafe))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.UnsafeValueTypeAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ValueTaskAwaiter))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ValueTaskAwaiter<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.ExceptionServices.ExceptionDispatchInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.CallingConvention))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.CollectionsMarshal))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.DllImportResolver))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.DllImportSearchPath))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.GCHandle))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.GCHandleType))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.InAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.Marshal))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.MemoryMarshal))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.NativeLibrary))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.OSPlatform))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.RuntimeInformation))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.SafeBuffer))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.SafeHandle))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.UnmanagedType))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Intrinsics.Arm.ArmBase))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Intrinsics.Arm.ArmBase.Arm64))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Intrinsics.X86.Avx))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Intrinsics.X86.Avx2))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Intrinsics.X86.Avx512BW))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Intrinsics.X86.Avx512F))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Intrinsics.X86.Avx512Vbmi))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Intrinsics.X86.Bmi1))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Intrinsics.X86.Bmi1.X64))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Intrinsics.X86.X86Base))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Versioning.SupportedOSPlatformAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Versioning.TargetFrameworkAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Versioning.TargetPlatformAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.RuntimeTypeHandle))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.SByte))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Security.Cryptography.HashAlgorithmName))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Security.Cryptography.IncrementalHash))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Security.Permissions.SecurityAction))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Security.Permissions.SecurityPermissionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Security.UnverifiableCodeAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Single))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Span<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.String))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.StringComparer))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.StringComparison))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.StringSplitOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Decoder))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Encoding))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Encodings.Web.JavaScriptEncoder))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.JsonDocument))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.JsonDocumentOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.JsonElement))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.JsonEncodedText))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.JsonException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.JsonReaderOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.JsonSerializer))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.JsonSerializerDefaults))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.JsonSerializerOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.JsonTokenType))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.JsonValueKind))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Nodes.JsonArray))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Nodes.JsonNode))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Nodes.JsonNodeOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Nodes.JsonObject))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Nodes.JsonValue))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Schema.JsonSchemaExporter))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Schema.JsonSchemaExporterContext))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Schema.JsonSchemaExporterOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonConstructorAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonConverter))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonConverter<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonConverterAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonConverterFactory))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonDerivedTypeAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonIgnoreAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonIgnoreCondition))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonIncludeAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonNumberHandling))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonPolymorphicAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonPropertyNameAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonSerializableAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonSerializerContext))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonSourceGenerationOptionsAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonDerivedType))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonMetadataServices))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonParameterInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonParameterInfoValues))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonPropertyInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonTypeInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonTypeInfo<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonTypeInfoKind))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Serialization.Metadata.JsonTypeInfoResolver))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Utf8JsonReader))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Json.Utf8JsonWriter))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.Capture))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.GeneratedRegexAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.Group))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.GroupCollection))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.Match))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.Regex))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.RegexOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.RegexRunner))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.RegexRunnerFactory))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.StringBuilder))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.StringBuilder.AppendInterpolatedStringHandler))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.CancellationToken))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.CancellationTokenSource))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Interlocked))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Monitor))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.SpinLock))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.Parallel))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.ParallelLoopResult))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.ParallelOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.Sources.IValueTaskSource))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.Sources.IValueTaskSource<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.Sources.ValueTaskSourceStatus))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.Task))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.Task<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.TaskAsyncEnumerableExtensions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.ValueTask))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.ValueTask<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.ThreadLocal<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ThreadStaticAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.TimeSpan))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Type))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.UInt16))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.UInt32))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.UInt64))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.UIntPtr))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Uri))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.UriFormatException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ValueTuple<,,,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ValueTuple<,,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ValueTuple<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ValueType))]
|
||||
//[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Void))]
|
||||
[ModuleInitializer]
|
||||
internal static void Initialize()
|
||||
{
|
||||
// This method runs automatically on startup.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
<linker>
|
||||
<assembly fullname="System.Collections" preserve="all" />
|
||||
<assembly fullname="System.IO.MemoryMappedFiles" preserve="all" />
|
||||
<assembly fullname="System.Linq" preserve="all" />
|
||||
<assembly fullname="System.Memory" preserve="all" />
|
||||
<assembly fullname="System.ObjectModel" preserve="all" />
|
||||
<assembly fullname="System.Runtime" preserve="all" />
|
||||
<assembly fullname="System.Runtime.InteropServices" preserve="all" />
|
||||
<assembly fullname="System.Text.RegularExpressions" preserve="all" />
|
||||
<assembly fullname="System.Threading" preserve="all" />
|
||||
<assembly fullname="BetterLyrics.WinUI3">
|
||||
<type fullname="BetterLyrics.WinUI3.PluginConfigs.BetterLyrics_Plugins_Romaji_Config" preserve="all" />
|
||||
</assembly>
|
||||
</linker>
|
||||
@@ -0,0 +1,145 @@
|
||||
// Auto-Generated by PluginAnalyzer
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace BetterLyrics.WinUI3.PluginConfigs;
|
||||
internal static class BetterLyrics_Plugins_Romaji_Config
|
||||
{
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.AppContext))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.AppDomain))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ArgumentException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ArgumentNullException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ArgumentOutOfRangeException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Array))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.AsyncCallback))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Boolean))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Buffer))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Byte))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Char))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.Dictionary<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.EqualityComparer<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.ICollection<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IEnumerable<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IEnumerator<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IList<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IReadOnlyCollection<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.IReadOnlyList<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.LinkedList<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.LinkedListNode<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.Generic.List<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.ICollection))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.IEnumerable))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.IEnumerator))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.IList))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.ObjectModel.Collection<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Collections.ObjectModel.ObservableCollection<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.INotifyPropertyChanged))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.PropertyChangedEventArgs))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ComponentModel.PropertyChangedEventHandler))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.DateTime))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Delegate))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggableAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggableAttribute.DebuggingModes))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggerBrowsableAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggerBrowsableState))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Diagnostics.DebuggerHiddenAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Enum))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Environment))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Exception))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Func<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.GC))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IAsyncResult))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IComparable<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IDisposable))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IndexOutOfRangeException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Int16))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Int32))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Int64))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.InvalidOperationException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.BinaryReader))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.File))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.FileAccess))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.FileMode))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.FileShare))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.FileStream))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.HandleInheritability))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.MemoryMappedFiles.MemoryMappedFile))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.MemoryMappedFiles.MemoryMappedFileAccess))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.MemoryMappedFiles.MemoryMappedViewAccessor))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.MemoryMappedFiles.MemoryMappedViewStream))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.Path))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.Stream))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.StreamReader))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.TextReader))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.IO.UnmanagedMemoryAccessor))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Linq.Enumerable))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Linq.IGrouping<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Math))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.MemoryExtensions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.MulticastDelegate))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.NotImplementedException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.NotSupportedException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Nullable<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Object))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ObjectDisposedException))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ObsoleteAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ParamArrayAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ReadOnlySpan<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyCompanyAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyConfigurationAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyCopyrightAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyDescriptionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyFileVersionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyInformationalVersionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyMetadataAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyProductAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyTitleAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.AssemblyTrademarkAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Reflection.DefaultMemberAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.CallerMemberNameAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.CompilationRelaxationsAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.ExtensionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.IsReadOnlyAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.IteratorStateMachineAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.NullableAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.NullableContextAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.RefSafetyRulesAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.RuntimeCompatibilityAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.CompilerServices.TupleElementNamesAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.InteropServices.InAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Serialization.SerializationInfo))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Serialization.StreamingContext))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Versioning.SupportedOSPlatformAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Versioning.TargetFrameworkAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Runtime.Versioning.TargetPlatformAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Security.Permissions.SecurityAction))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Security.Permissions.SecurityPermissionAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Security.UnverifiableCodeAttribute))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Single))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.String))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.StringSplitOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.Encoding))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.Capture))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.Group))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.GroupCollection))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.Match))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.MatchCollection))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.Regex))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.RegularExpressions.RegexOptions))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Text.StringBuilder))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Interlocked))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.Task))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Threading.Tasks.Task<>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.TimeSpan))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.Type))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.UInt16))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.UInt32))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ValueTuple<,>))]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(System.ValueType))]
|
||||
[ModuleInitializer]
|
||||
internal static void Initialize()
|
||||
{
|
||||
// This method runs automatically on startup.
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ namespace BetterLyrics.WinUI3.Renderer
|
||||
|
||||
public CoverBackgroundRenderer()
|
||||
{
|
||||
_crossfadeTransition = new ValueTransition<double>(1.0, 0.7, defaultEasingType: EasingType.Linear);
|
||||
_crossfadeTransition = new ValueTransition<double>(1.0, EasingHelper.GetInterpolatorByEasingType<double>(EasingType.Linear), 0.7);
|
||||
}
|
||||
|
||||
public void SetCoverBitmap(CanvasBitmap? newBitmap)
|
||||
|
||||
@@ -697,10 +697,6 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService
|
||||
_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();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.Core.Interfaces.Features;
|
||||
using BetterLyrics.WinUI3.Constants;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
@@ -10,6 +11,7 @@ using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Providers;
|
||||
using BetterLyrics.WinUI3.Services.FileSystemService;
|
||||
using BetterLyrics.WinUI3.Services.LyricsCacheService;
|
||||
using BetterLyrics.WinUI3.Services.PluginService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using BetterLyrics.WinUI3.Services.SongSearchMapService;
|
||||
using Lyricify.Lyrics.Helpers;
|
||||
@@ -36,6 +38,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
private readonly IFileSystemService _fileSystemService;
|
||||
private readonly ILyricsCacheService _lyricsCacheService;
|
||||
private readonly ISongSearchMapService _songSearchMapService;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public LyricsSearchService(
|
||||
@@ -43,6 +46,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
IFileSystemService fileSystemService,
|
||||
ILyricsCacheService lyricsCacheService,
|
||||
ISongSearchMapService songSearchMapService,
|
||||
IPluginService pluginService,
|
||||
ILogger<LyricsSearchService> logger
|
||||
)
|
||||
{
|
||||
@@ -50,6 +54,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
_fileSystemService = fileSystemService;
|
||||
_lyricsCacheService = lyricsCacheService;
|
||||
_songSearchMapService = songSearchMapService;
|
||||
_pluginService = pluginService;
|
||||
_logger = logger;
|
||||
|
||||
_lrcLibHttpClient = new();
|
||||
@@ -207,11 +212,26 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
{
|
||||
_logger.LogInformation("SearchAllAsync {SongInfo}", songInfo);
|
||||
var results = new List<LyricsCacheItem>();
|
||||
|
||||
foreach (var provider in Enum.GetValues<LyricsSearchProvider>())
|
||||
{
|
||||
if (provider == LyricsSearchProvider.Plugin) continue;
|
||||
|
||||
var searchResult = await SearchSingleAsync(songInfo, provider, checkCache, token);
|
||||
results.Add(searchResult);
|
||||
}
|
||||
|
||||
foreach (var plugin in _pluginService.Plugins)
|
||||
{
|
||||
if (token.IsCancellationRequested) break;
|
||||
|
||||
if (plugin is ILyricsSource lyricsSearchPlugin)
|
||||
{
|
||||
var pluginResult = await SearchPluginAsync(songInfo, lyricsSearchPlugin, token);
|
||||
results.Add(pluginResult);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -673,5 +693,40 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private async Task<LyricsCacheItem> SearchPluginAsync(SongInfo songInfo, ILyricsSource plugin, CancellationToken token)
|
||||
{
|
||||
var cacheItem = new LyricsCacheItem
|
||||
{
|
||||
Provider = LyricsSearchProvider.Plugin,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var result = await plugin.GetLyricsAsync(songInfo.Title, songInfo.Artist, songInfo.Album, songInfo.Duration);
|
||||
|
||||
if (result != null && !string.IsNullOrEmpty(result.Raw))
|
||||
{
|
||||
cacheItem.Title = result.Title;
|
||||
cacheItem.Artist = result.Artist;
|
||||
cacheItem.Album = result.Album;
|
||||
cacheItem.Duration = result.Duration;
|
||||
|
||||
cacheItem.Raw = result.Raw;
|
||||
cacheItem.Translation = result.Translation;
|
||||
cacheItem.Transliteration = result.Transliteration;
|
||||
|
||||
cacheItem.Reference = result.Reference ?? "about:blank";
|
||||
cacheItem.MatchPercentage = MetadataComparer.CalculateScore(songInfo, cacheItem);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Plugin {PluginName} failed to search", plugin.Name);
|
||||
}
|
||||
|
||||
return cacheItem;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using BetterLyrics.Core.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.PluginService
|
||||
{
|
||||
public interface IPluginService
|
||||
{
|
||||
IReadOnlyList<IPlugin> Plugins { get; }
|
||||
|
||||
T? GetPlugin<T>() where T : class, IPlugin;
|
||||
void LoadPlugins();
|
||||
void InstallPlugin(string zipPath);
|
||||
void UninstallPlugin(string pluginId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using BetterLyrics.Core.Interfaces;
|
||||
using BetterLyrics.Core.Interfaces.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.PluginService
|
||||
{
|
||||
public class PluginContext : IPluginContext
|
||||
{
|
||||
private readonly IPluginService _pluginService;
|
||||
|
||||
public string PluginDirectory { get; }
|
||||
public IAIService? AIService => _pluginService.GetPlugin<IAIService>();
|
||||
|
||||
public PluginContext(IPluginService pluginService, string pluginDir)
|
||||
{
|
||||
_pluginService = pluginService;
|
||||
PluginDirectory = pluginDir;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.PluginService
|
||||
{
|
||||
public class PluginLoadContext : AssemblyLoadContext
|
||||
{
|
||||
private AssemblyDependencyResolver _resolver;
|
||||
|
||||
public PluginLoadContext(string pluginPath) : base(isCollectible: true)
|
||||
{
|
||||
_resolver = new AssemblyDependencyResolver(pluginPath);
|
||||
}
|
||||
|
||||
protected override Assembly? Load(AssemblyName assemblyName)
|
||||
{
|
||||
var assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
|
||||
if (assemblyPath != null)
|
||||
{
|
||||
return LoadFromAssemblyPath(assemblyPath);
|
||||
}
|
||||
|
||||
// return null to use the default AssemblyLoadContext
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
|
||||
{
|
||||
var libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
|
||||
if (libraryPath != null)
|
||||
{
|
||||
return LoadUnmanagedDllFromPath(libraryPath);
|
||||
}
|
||||
|
||||
// return IntPtr.Zero to use the default AssemblyLoadContext
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
using BetterLyrics.Core.Interfaces;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.PluginService
|
||||
{
|
||||
public class PluginService : IPluginService
|
||||
{
|
||||
private List<IPlugin> _plugins = new();
|
||||
public IReadOnlyList<IPlugin> Plugins => _plugins;
|
||||
private Dictionary<string, PluginLoadContext> _pluginContexts = new();
|
||||
private HashSet<string> _loadedDllPaths = new();
|
||||
|
||||
private readonly ILogger<PluginService> _logger;
|
||||
|
||||
public PluginService(ILogger<PluginService> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public T? GetPlugin<T>() where T : class, IPlugin
|
||||
{
|
||||
return _plugins.OfType<T>().FirstOrDefault();
|
||||
}
|
||||
|
||||
public void LoadPlugins()
|
||||
{
|
||||
string pluginsRoot = Path.Combine(ApplicationData.Current.LocalFolder.Path, "plugins");
|
||||
if (!Directory.Exists(pluginsRoot)) Directory.CreateDirectory(pluginsRoot);
|
||||
|
||||
var pluginFolders = Directory.GetDirectories(pluginsRoot);
|
||||
|
||||
foreach (var folder in pluginFolders)
|
||||
{
|
||||
var dllFiles = Directory.GetFiles(folder, "*.dll");
|
||||
|
||||
foreach (var dllPath in dllFiles)
|
||||
{
|
||||
if (_loadedDllPaths.Contains(dllPath)) continue;
|
||||
|
||||
TryLoadPlugin(dllPath);
|
||||
}
|
||||
}
|
||||
|
||||
InitializePlugins();
|
||||
}
|
||||
|
||||
private void InitializePlugins()
|
||||
{
|
||||
foreach (var plugin in _plugins)
|
||||
{
|
||||
try
|
||||
{
|
||||
string dllPath = plugin.GetType().Assembly.Location;
|
||||
string? pluginDir = Path.GetDirectoryName(dllPath);
|
||||
if (pluginDir == null) continue;
|
||||
|
||||
var context = new PluginContext(this, pluginDir);
|
||||
plugin.OnLoad(context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to initialize plugin {Name}", plugin.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TryLoadPlugin(string dllPath)
|
||||
{
|
||||
// 1. Create Context
|
||||
var loadContext = new PluginLoadContext(dllPath);
|
||||
|
||||
try
|
||||
{
|
||||
var assembly = loadContext.LoadFromAssemblyPath(dllPath);
|
||||
int loadedCount = 0; // Track successfully loaded plugins
|
||||
|
||||
// 2. [Safety Check] Safely retrieve types
|
||||
IEnumerable<Type> types;
|
||||
try
|
||||
{
|
||||
types = assembly.GetExportedTypes();
|
||||
}
|
||||
catch (ReflectionTypeLoadException ex)
|
||||
{
|
||||
// If some types fail to load, only keep the usable ones!
|
||||
types = ex.Types.Where(t => t != null)!;
|
||||
foreach (var loaderEx in ex.LoaderExceptions)
|
||||
{
|
||||
_logger.LogWarning("Partial type loading failure in DLL {path}: {msg}", dllPath, loaderEx?.Message);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
// 3. Check if it is a valid plugin class
|
||||
if (typeof(IPlugin).IsAssignableFrom(type) && !type.IsAbstract)
|
||||
{
|
||||
IPlugin? plugin = null;
|
||||
try
|
||||
{
|
||||
// 4. [Instantiation Guard] Prevent plugin constructor errors from crashing the main app
|
||||
plugin = (IPlugin?)Activator.CreateInstance(type);
|
||||
if (plugin == null) continue;
|
||||
|
||||
// 5. Check for duplicate IDs
|
||||
if (_plugins.Any(p => p.Id == plugin.Id))
|
||||
{
|
||||
_logger.LogWarning("Skipping duplicate plugin: {id} ({path})", plugin.Id, dllPath);
|
||||
// Explicitly break reference to aid Unload
|
||||
plugin = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 7. Add to collection
|
||||
_plugins.Add(plugin);
|
||||
_pluginContexts.Add(plugin.Id, loadContext);
|
||||
loadedCount++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to initialize/instantiate plugin {type}", type.FullName);
|
||||
|
||||
// If plugin initialization fails, explicitly dispose if possible
|
||||
if (plugin is IDisposable disposable)
|
||||
{
|
||||
try { disposable.Dispose(); } catch { }
|
||||
}
|
||||
plugin = null; // Break reference
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 8. Finalize: If no usable plugins were found in this DLL, unload Context
|
||||
if (loadedCount > 0)
|
||||
{
|
||||
_loadedDllPaths.Add(dllPath);
|
||||
_logger.LogInformation("Successfully loaded {count} plugin(s) from {path}", loadedCount, dllPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("No valid plugins found in {path}. Unloading context.", dllPath);
|
||||
// No plugin instances remain alive at this point, safe to unload
|
||||
loadContext.Unload();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to load assembly: {path}", dllPath);
|
||||
// Only unload here if the loading process completely crashed
|
||||
try { loadContext.Unload(); } catch { }
|
||||
}
|
||||
}
|
||||
|
||||
public void UninstallPlugin(string pluginId)
|
||||
{
|
||||
var plugin = _plugins.FirstOrDefault(p => p.Id == pluginId);
|
||||
if (plugin == null) return;
|
||||
|
||||
var dllPath = plugin.GetType().Assembly.Location;
|
||||
var folderPath = Path.GetDirectoryName(dllPath);
|
||||
|
||||
_plugins.Remove(plugin);
|
||||
_loadedDllPaths.Remove(dllPath);
|
||||
|
||||
if (_pluginContexts.TryGetValue(pluginId, out var context))
|
||||
{
|
||||
context.Unload();
|
||||
_pluginContexts.Remove(pluginId);
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
|
||||
if (Directory.Exists(folderPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(folderPath, true);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to delete plugin folder {}", folderPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void InstallPlugin(string zipPath)
|
||||
{
|
||||
string pluginsRoot = Path.Combine(ApplicationData.Current.LocalFolder.Path, "plugins");
|
||||
string folderName = Path.GetFileNameWithoutExtension(zipPath);
|
||||
string installDir = Path.Combine(pluginsRoot, folderName);
|
||||
|
||||
if (Directory.Exists(installDir))
|
||||
{
|
||||
// TODO: 最好是先 Find plugin by path -> UninstallPlugin(id)
|
||||
// 否则文件被锁住无法 Delete
|
||||
try
|
||||
{
|
||||
Directory.Delete(installDir, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to delete existing plugin folder {}", installDir);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(installDir);
|
||||
ZipFile.ExtractToDirectory(zipPath, installDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
using BetterLyrics.WinUI3.Models.Http;
|
||||
using BetterLyrics.Core.Interfaces.Features;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models.Http;
|
||||
using BetterLyrics.WinUI3.Serialization;
|
||||
using BetterLyrics.WinUI3.Services.PluginService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@@ -12,37 +16,31 @@ namespace BetterLyrics.WinUI3.Services.TransliterationService
|
||||
public class TransliterationService : ITransliterationService
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public TransliterationService(ISettingsService settingsService)
|
||||
public TransliterationService(ISettingsService settingsService, IPluginService pluginService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_pluginService = pluginService;
|
||||
_httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
public async Task<string> TransliterateText(string text, string targetLangCode, CancellationToken token)
|
||||
{
|
||||
string? result = null;
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
throw new Exception(text + " is empty or null.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(_settingsService.AppSettings.TranslationSettings.CutletDockerServer))
|
||||
var plugin = _pluginService.Plugins.OfType<ILyricsTransliterator>().FirstOrDefault();
|
||||
if (plugin != null)
|
||||
{
|
||||
throw new Exception("cutlet-docker server URL is not set in settings.");
|
||||
result = await plugin.GetTransliterationAsync(text, PhoneticHelper.RomanCode);
|
||||
}
|
||||
|
||||
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;
|
||||
return result ?? "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>لا يمكن عرض المقطوعات لأن المسار غير موجود</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>سياسة الخصوصية</value>
|
||||
</data>
|
||||
@@ -798,34 +810,37 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>منطقة قابلة للسحب</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>EaseInOutBack</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>EaseInOutBounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>EaseInOutCirc</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>EaseInOutCubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>EaseInOutElastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>EaseInOutExpo</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuad</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuart</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuint</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>EaseInOutSine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.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>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>اختصار التشغيل والإيقاف المؤقت</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>اختصار الأغنية السابقة</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>Titel können nicht angezeigt werden, da der Pfad nicht existiert</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>Datenschutzrichtlinie</value>
|
||||
</data>
|
||||
@@ -798,35 +810,38 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>Ziehbereich</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<value>Back Ease In-Out</value>
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<value>Bounce Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>Back</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<value>Circular Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>Bounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<value>Cubic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>Circular</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<value>Elastic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>Cubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<value>Exponential Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>Elastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>Exponential</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<value>Quartic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<value>Quintic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>Quartic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<value>Sine Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>Quintic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>Sine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
<value>Linear</value>
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.Content" xml:space="preserve">
|
||||
<value>Die App startet nach erfolgreichem Import automatisch neu</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Description" xml:space="preserve">
|
||||
<value>Priorisiere Transliterationen innerhalb des Songtextes; falls keine Übereinstimmung gefunden wird, fordere maschinelle Transliteration vom cutlet-docker-Server an</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>Japanische Lautschrift</value>
|
||||
</data>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>Tastenkürzel für Wiedergabe/Pause</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>Tastenkürzel für vorherigen Titel</value>
|
||||
</data>
|
||||
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>Unable to view tracks because the path does not exist</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value>Install plugin</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value>No plugins installed</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value>Plugin Manager</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value>Uninstall plugin</value>
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>Privacy Policy</value>
|
||||
</data>
|
||||
@@ -798,35 +810,47 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>Draggable Area</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<value>Back Ease In-Out</value>
|
||||
<data name="SettingsPageEasingMode.Header" xml:space="preserve">
|
||||
<value>Easing Mode</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<value>Bounce Ease In-Out</value>
|
||||
<data name="SettingsPageEasingModeIn.Content" xml:space="preserve">
|
||||
<value>In</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<value>Circular Ease In-Out</value>
|
||||
<data name="SettingsPageEasingModeInOut.Content" xml:space="preserve">
|
||||
<value>In-Out</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<value>Cubic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value>Out</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<value>Elastic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>Back</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<value>Exponential Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>Bounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>Circular</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<value>Quartic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>Cubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<value>Quintic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>Elastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<value>Sine Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>Exponential</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>Quartic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>Quintic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>Sine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
<value>Linear</value>
|
||||
@@ -924,9 +948,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.Content" xml:space="preserve">
|
||||
<value>The app will restart automatically after successful import</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Description" xml:space="preserve">
|
||||
<value>Prioritize reading transliteration within lyrics; if no match, request machine transliteration from cutlet-docker server</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>Japanese Phonetic</value>
|
||||
</data>
|
||||
@@ -1254,6 +1275,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>Play/Pause Shortcut</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value>Plugins</value>
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>Previous Track Shortcut</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>No se pueden ver las pistas porque la ruta no existe</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>Política de privacidad</value>
|
||||
</data>
|
||||
@@ -798,35 +810,41 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>Área arrastrable</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<value>Back Ease In-Out</value>
|
||||
<data name="SettingsPageEasingMode.Header" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<value>Bounce Ease In-Out</value>
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<value>Circular Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>Back</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<value>Cubic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>Bounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<value>Elastic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>Circular</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<value>Exponential Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>Cubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>Elastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<value>Quartic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>Exponential</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<value>Quintic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<value>Sine Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>Quartic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>Quintic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>Sine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
<value>Lineal</value>
|
||||
@@ -924,9 +942,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.Content" xml:space="preserve">
|
||||
<value>La aplicación se reiniciará automáticamente después de una importación exitosa</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Description" xml:space="preserve">
|
||||
<value>Priorizar la lectura de transliteración dentro de la letra; si no hay coincidencia, solicitar transliteración automática al servidor cutlet-docker</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>Fonética japonesa</value>
|
||||
</data>
|
||||
@@ -1254,6 +1269,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>Atajo de Reproducir/Pausar</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>Atajo de pista anterior</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>Impossible d'afficher les pistes car le chemin n'existe pas</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>Politique de confidentialité</value>
|
||||
</data>
|
||||
@@ -798,35 +810,38 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>Zone déplaçable</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<value>Back Ease In-Out</value>
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<value>Bounce Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>Back</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<value>Circular Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>Bounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<value>Cubic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>Circular</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<value>Elastic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>Cubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<value>Exponential Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>Elastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>Exponential</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<value>Quartic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<value>Quintic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>Quartic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<value>Sine Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>Quintic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>Sine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
<value>Linéaire</value>
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.Content" xml:space="preserve">
|
||||
<value>L'application redémarrera automatiquement après une importation réussie</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Description" xml:space="preserve">
|
||||
<value>Prioriser la lecture de la translittération dans les paroles ; si aucune correspondance, demander une translittération automatique au serveur cutlet-docker</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>Phonétique japonaise</value>
|
||||
</data>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>Raccourci Lecture/Pause</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>Raccourci piste précédente</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>ट्रैक देखने में असमर्थ क्योंकि पथ मौजूद नहीं है</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>गोपनीयता नीति</value>
|
||||
</data>
|
||||
@@ -798,34 +810,37 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>खींचने योग्य क्षेत्र</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>EaseInOutBack</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>EaseInOutBounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>EaseInOutCirc</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>EaseInOutCubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>EaseInOutElastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>EaseInOutExpo</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuad</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuart</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuint</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>EaseInOutSine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.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>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>प्ले और पॉज़ शॉर्टकट</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>पिछला ट्रैक शॉर्टकट</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>Tidak dapat melihat trek karena jalur tidak ada</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>Kebijakan Privasi</value>
|
||||
</data>
|
||||
@@ -798,34 +810,37 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>Area yang Dapat Diseret</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>EaseInOutBack</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>EaseInOutBounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>EaseInOutCirc</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>EaseInOutCubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>EaseInOutElastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>EaseInOutExpo</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuad</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuart</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuint</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>EaseInOutSine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.Content" xml:space="preserve">
|
||||
<value>Setelah impor berhasil, program akan dimuat ulang secara otomatis</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Description" xml:space="preserve">
|
||||
<value>Akan memprioritaskan membaca transliterasi di dalam lirik, jika tidak ada kecocokan maka akan meminta transliterasi mesin dari server cutlet-docker</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>Fonetik Bahasa Jepang</value>
|
||||
</data>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>Pintasan Putar dan Jeda</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>Pintasan Lagu Sebelumnya</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>パスが存在しないため、曲を表示できません</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>個人情報保護方針</value>
|
||||
</data>
|
||||
@@ -798,34 +810,37 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>ドラッグ可能エリア</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>バックイーズ イン アウト</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>バウンスイーズ イン アウト</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>サーキュラーイーズ イン アウト</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>キュービックイーズ イン アウト</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>エラスティックイーズ イン アウト</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>エキスポネンシャルイーズ イン アウト</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>クアドラティックイーズ イン アウト</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>クオートイーズ イン アウト</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>クイントイーズ イン アウト</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>サインイーズ イン アウト</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.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>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>再生/一時停止のショートカットキー</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>次のトラックのショートカットキー</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>경로가 존재하지 않아 트랙을 볼 수 없습니다</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>개인정보 처리방침</value>
|
||||
</data>
|
||||
@@ -798,35 +810,38 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>드래그 가능 영역</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<value>Back Ease In-Out</value>
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<value>Bounce Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>Back</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<value>Circular Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>Bounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<value>Cubic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>Circular</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<value>Elastic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>Cubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<value>Exponential Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>Elastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>Exponential</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<value>Quartic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<value>Quintic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>Quartic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<value>Sine Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>Quintic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>Sine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
<value>Linear (선형)</value>
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.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>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>재생 및 일시정지 단축키</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>이전 곡 단축키</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>Tidak dapat melihat trek kerana laluan tidak wujud</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>Dasar Privasi</value>
|
||||
</data>
|
||||
@@ -798,34 +810,37 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>Kawasan Boleh Diseret</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>EaseInOutBack</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>EaseInOutBounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>EaseInOutCirc</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>EaseInOutCubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>EaseInOutElastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>EaseInOutExpo</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuad</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuart</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuint</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>EaseInOutSine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.Content" xml:space="preserve">
|
||||
<value>Selepas import berjaya, program akan dimulakan semula secara automatik</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Description" xml:space="preserve">
|
||||
<value>Akan mengutamakan pembacaan transliterasi dalam lirik, jika tiada padanan maka akan meminta transliterasi mesin daripada pelayan cutlet-docker</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>Fonetik Bahasa Jepun</value>
|
||||
</data>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>Pintasan Main dan Jeda</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>Pintasan Lagu Sebelumnya</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>Não foi possível ver as faixas porque o caminho não existe</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>Política de Privacidade</value>
|
||||
</data>
|
||||
@@ -798,34 +810,37 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>Área de Arrastar</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>EaseInOutBack</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>EaseInOutBounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>EaseInOutCirc</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>EaseInOutCubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>EaseInOutElastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>EaseInOutExpo</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuad</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuart</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuint</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>EaseInOutSine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.Content" xml:space="preserve">
|
||||
<value>Após a importação bem-sucedida, o programa será reiniciado automaticamente</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Description" xml:space="preserve">
|
||||
<value>Dará prioridade à leitura da transliteração dentro da letra; se não houver correspondência, solicitará transliteração automática ao servidor cutlet-docker</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>Fonética Japonesa</value>
|
||||
</data>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>Atalho para Reproduzir e Pausar</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>Atalho para Faixa Anterior</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>Невозможно просмотреть треки, так как путь не существует</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>Политика конфиденциальности</value>
|
||||
</data>
|
||||
@@ -798,35 +810,38 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>Перетаскиваемая область</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<value>Back Ease In-Out</value>
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<value>Bounce Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>Back</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<value>Circular Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>Bounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<value>Cubic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>Circular</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<value>Elastic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>Cubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<value>Exponential Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>Elastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>Exponential</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<value>Quartic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>Quadratic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<value>Quintic Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>Quartic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<value>Sine Ease In-Out</value>
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>Quintic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>Sine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
<value>Linear</value>
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.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>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>Горячая клавиша Воспроизведение/Пауза</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>Горячая клавиша предыдущего трека</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>ไม่สามารถดูแทร็กได้เนื่องจากเส้นทางไม่มีอยู่</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>นโยบายความเป็นส่วนตัว</value>
|
||||
</data>
|
||||
@@ -798,34 +810,37 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>พื้นที่ลาก</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>EaseInOutBack</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>EaseInOutBounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>EaseInOutCirc</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>EaseInOutCubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>EaseInOutElastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>EaseInOutExpo</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuad</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuart</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuint</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>EaseInOutSine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.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>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>ทางลัดเล่นและหยุดชั่วคราว</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>ทางลัดเพลงก่อนหน้า</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>Không thể xem các bài hát vì đường dẫn không tồn tại</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>Chính sách bảo mật</value>
|
||||
</data>
|
||||
@@ -798,34 +810,37 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>Vùng có thể kéo</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>EaseInOutBack</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>EaseInOutBounce</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>EaseInOutCirc</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>EaseInOutCubic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>EaseInOutElastic</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>EaseInOutExpo</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuad</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuart</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>EaseInOutQuint</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>EaseInOutSine</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.Content" xml:space="preserve">
|
||||
<value>Sau khi nhập thành công, chương trình sẽ tự động khởi động lại</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Description" xml:space="preserve">
|
||||
<value>Sẽ ưu tiên đọc phiên âm trong lời bài hát, nếu không khớp sẽ yêu cầu phiên âm máy từ máy chủ cutlet-docker</value>
|
||||
</data>
|
||||
<data name="SettingsPageJapanese.Header" xml:space="preserve">
|
||||
<value>Phiên âm tiếng Nhật</value>
|
||||
</data>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>Phím tắt phát và tạm dừng</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>Phím tắt bài hát trước</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>无法查看曲目,因为路径不存在</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value>安装插件</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value>未安装任何插件</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value>插件管理</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value>卸载插件</value>
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>隐私政策</value>
|
||||
</data>
|
||||
@@ -798,35 +810,47 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>可拖动区域</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<value>回弹缓入缓出</value>
|
||||
<data name="SettingsPageEasingMode.Header" xml:space="preserve">
|
||||
<value>缓动类型</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<value>弹跳缓入缓出</value>
|
||||
<data name="SettingsPageEasingModeIn.Content" xml:space="preserve">
|
||||
<value>缓入</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<value>圆形缓入缓出</value>
|
||||
<data name="SettingsPageEasingModeInOut.Content" xml:space="preserve">
|
||||
<value>缓出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<value>三次缓入缓出</value>
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value>缓入缓出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<value>弹性缓入缓出</value>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>回弹</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<value>指数缓入缓出</value>
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>弹跳</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<value>二次缓入缓出</value>
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>圆形</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<value>四次缓入缓出</value>
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>三次</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<value>五次缓入缓出</value>
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>弹性</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<value>正弦缓入缓出</value>
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>指数</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>二次</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>四次</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>五次</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>正弦</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
<value>线性</value>
|
||||
@@ -924,9 +948,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.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>
|
||||
@@ -1254,6 +1275,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>播放与暂停快捷键</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value>插件</value>
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>上一曲目快捷键</value>
|
||||
</data>
|
||||
|
||||
@@ -59,46 +59,46 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -555,6 +555,18 @@
|
||||
<data name="PlaylistViewFailed" xml:space="preserve">
|
||||
<value>無法檢視曲目,因為路徑不存在</value>
|
||||
</data>
|
||||
<data name="PluginManagerControlInstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlNoPluginsInstalled.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlTitle.Text" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PluginManagerControlUninstall.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="PrivacyPolicy.Content" xml:space="preserve">
|
||||
<value>隱私權政策</value>
|
||||
</data>
|
||||
@@ -798,34 +810,37 @@
|
||||
<data name="SettingsPageDragArea.Header" xml:space="preserve">
|
||||
<value>可拖曳區域</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBack.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingModeOut.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseBack.Content" xml:space="preserve">
|
||||
<value>回彈緩入緩出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutBounce.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseBounce.Content" xml:space="preserve">
|
||||
<value>彈跳緩入緩出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCirc.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCirc.Content" xml:space="preserve">
|
||||
<value>圓形緩入緩出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutCubic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseCubic.Content" xml:space="preserve">
|
||||
<value>三次緩入緩出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutElastic.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseElastic.Content" xml:space="preserve">
|
||||
<value>彈性緩入緩出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutExpo.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseExpo.Content" xml:space="preserve">
|
||||
<value>指數緩入緩出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuad.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuad.Content" xml:space="preserve">
|
||||
<value>二次緩入緩出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuart.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuart.Content" xml:space="preserve">
|
||||
<value>四次緩入緩出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutQuint.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseQuint.Content" xml:space="preserve">
|
||||
<value>五次緩入緩出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeEaseInOutSine.Content" xml:space="preserve">
|
||||
<data name="SettingsPageEasingTypeEaseSine.Content" xml:space="preserve">
|
||||
<value>正弦緩入緩出</value>
|
||||
</data>
|
||||
<data name="SettingsPageEasingTypeLinear.Content" xml:space="preserve">
|
||||
@@ -924,9 +939,6 @@
|
||||
<data name="SettingsPageImportSettingsInfo.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>
|
||||
@@ -1254,6 +1266,9 @@
|
||||
<data name="SettingsPagePlayOrPauseSongHotKey.Header" xml:space="preserve">
|
||||
<value>播放與暫停快速鍵</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlugins.Content" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="SettingsPagePreviousSongHotKey.Header" xml:space="preserve">
|
||||
<value>上一曲目快速鍵</value>
|
||||
</data>
|
||||
|
||||
@@ -39,9 +39,6 @@ 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;
|
||||
|
||||
@@ -125,35 +122,6 @@ 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()
|
||||
{
|
||||
|
||||
@@ -56,6 +56,12 @@
|
||||
Glyph=}"
|
||||
Tag="Stats" />
|
||||
|
||||
<NavigationViewItem
|
||||
x:Uid="SettingsPagePlugins"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
Tag="Plugins" />
|
||||
|
||||
<NavigationViewItem
|
||||
x:Uid="SettingsPageAbout"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
@@ -96,6 +102,11 @@
|
||||
<uc:StatsDashboardControl />
|
||||
</controls:Case>
|
||||
|
||||
<!-- Plugins -->
|
||||
<controls:Case Value="Plugins">
|
||||
<uc:PluginManagerControl />
|
||||
</controls:Case>
|
||||
|
||||
<!-- About -->
|
||||
<controls:Case Value="About">
|
||||
<uc:AboutControl />
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 18
|
||||
VisualStudioVersion = 18.1.11312.151 d18.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "BetterLyrics.WinUI3 (Package)", "BetterLyrics.WinUI3\BetterLyrics.WinUI3 (Package)\BetterLyrics.WinUI3 (Package).wapproj", "{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BetterLyrics.WinUI3", "BetterLyrics.WinUI3\BetterLyrics.WinUI3\BetterLyrics.WinUI3.csproj", "{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Impressionist", "Impressionist\Impressionist\Impressionist.csproj", "{A678BCA5-03DE-71E4-73C1-388B7550E4E3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorThief.WinUI3", "ColorThief.WinUI3\ColorThief.WinUI3.csproj", "{8F2FE667-2D91-428E-0630-05E6330F9625}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BetterLyrics.Core", "BetterLyrics.Core\BetterLyrics.Core.csproj", "{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Debug|x64.Build.0 = Debug|x64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Debug|x86.Build.0 = Debug|x86
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Release|x64.ActiveCfg = Release|x64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Release|x64.Build.0 = Release|x64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Release|x64.Deploy.0 = Release|x64
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Release|x86.ActiveCfg = Release|x86
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Release|x86.Build.0 = Release|x86
|
||||
{6576CD19-EF92-4099-B37D-E2D8EBDB6BF5}.Release|x86.Deploy.0 = Release|x86
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Debug|x64.Build.0 = Debug|x64
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Debug|x86.Build.0 = Debug|x86
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Release|x64.ActiveCfg = Release|x64
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Release|x64.Build.0 = Release|x64
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Release|x86.ActiveCfg = Release|x86
|
||||
{6D26909A-9EE5-4D26-9E81-686BDE36A9D3}.Release|x86.Build.0 = Release|x86
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A678BCA5-03DE-71E4-73C1-388B7550E4E3}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8F2FE667-2D91-428E-0630-05E6330F9625}.Release|x86.Build.0 = Release|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Release|x64.Build.0 = Release|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{0F47FE6F-D0AA-49E5-8F33-78DFDEB1F810}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {0FD73F15-ED69-4DC2-9FD3-A4F03AF172A4}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
24
BetterLyrics.slnx
Normal file
24
BetterLyrics.slnx
Normal file
@@ -0,0 +1,24 @@
|
||||
<Solution>
|
||||
<Configurations>
|
||||
<Platform Name="ARM64" />
|
||||
<Platform Name="x64" />
|
||||
<Platform Name="x86" />
|
||||
</Configurations>
|
||||
<Folder Name="/Plugins/">
|
||||
<Project Path="Plugins/BetterLyrics.Plugins.AI.Local/BetterLyrics.Plugins.AI.Local.csproj" />
|
||||
<Project Path="Plugins/BetterLyrics.Plugins.Transliteration.Romaji/BetterLyrics.Plugins.Transliteration.Romaji.csproj" />
|
||||
<Project Path="Plugins/BetterLyrics.Plugins.Translation.LocalAI/BetterLyrics.Plugins.Translation.LocalAI.csproj" Id="17f9f675-6745-44cb-b8b4-604a2ae90dd1" />
|
||||
</Folder>
|
||||
<Project Path="BetterLyrics.Core/BetterLyrics.Core.csproj" />
|
||||
<Project Path="BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/BetterLyrics.WinUI3 (Package).wapproj" Type="c7167f0d-bc9f-4e6e-afe1-012c56b48db5">
|
||||
<Deploy />
|
||||
</Project>
|
||||
<Project Path="BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
<Platform Solution="*|x86" Project="x86" />
|
||||
</Project>
|
||||
<Project Path="ColorThief.WinUI3/ColorThief.WinUI3.csproj" />
|
||||
<Project Path="Impressionist/Impressionist/Impressionist.csproj" />
|
||||
<Project Path="PluginAnalyzer/PluginAnalyzer.csproj" Id="8ee58bf7-807d-486c-8d7d-c00bb9ec2b81" />
|
||||
</Solution>
|
||||
@@ -4,11 +4,6 @@
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<RootNamespace>ColorThief.WinUI3</RootNamespace>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.7175" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.8.251106002" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
14
PluginAnalyzer/PluginAnalyzer.csproj
Normal file
14
PluginAnalyzer/PluginAnalyzer.csproj
Normal file
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Mono.Cecil" Version="0.11.6" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
254
PluginAnalyzer/Program.cs
Normal file
254
PluginAnalyzer/Program.cs
Normal file
@@ -0,0 +1,254 @@
|
||||
using Mono.Cecil;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Diagnostics;
|
||||
|
||||
class Program
|
||||
{
|
||||
// Global sets
|
||||
static HashSet<string> _mergedAssemblies = new HashSet<string>();
|
||||
static HashSet<string> _mergedSystemTypes = new HashSet<string>();
|
||||
static string _currentScanDirectory = "";
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// =========================================================
|
||||
// 🚀 MODE 1: CLI Automation Mode (被 VS 编译调用时)
|
||||
// =========================================================
|
||||
if (args.Length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
string scanPath = args[0].Replace("\"", "").Trim();
|
||||
string targetNs = args.Length > 1 ? args[1] : "BetterLyrics.WinUI3";
|
||||
string prefix = args.Length > 2 ? args[2] : "Plugin";
|
||||
|
||||
// 读取第4个参数作为输出目录,如果没传,就默认用扫描目录
|
||||
string outputDir = args.Length > 3 ? args[3].Replace("\"", "").Trim() : scanPath;
|
||||
|
||||
Console.WriteLine($"[Analyzer] Scanning: {scanPath}");
|
||||
Console.WriteLine($"[Analyzer] Output to: {outputDir}");
|
||||
|
||||
RunBatch(scanPath, targetNs, prefix, outputDir, silent: true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[Analyzer] Error: {ex.Message}");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// 🚀 MODE 2: Interactive Mode (手动双击运行)
|
||||
// =========================================================
|
||||
Console.WriteLine("==================================================");
|
||||
Console.WriteLine(" Plugin Dependency Analyzer (Auto-CLI Ready) ");
|
||||
Console.WriteLine("==================================================");
|
||||
|
||||
while (true)
|
||||
{
|
||||
_mergedAssemblies.Clear();
|
||||
_mergedSystemTypes.Clear();
|
||||
|
||||
Console.WriteLine("\n1. Enter Plugin FOLDER path (or 'exit'):");
|
||||
Console.Write("> ");
|
||||
string input = Console.ReadLine();
|
||||
if (string.IsNullOrWhiteSpace(input)) continue;
|
||||
if (input.Trim().ToLower() == "exit") break;
|
||||
|
||||
string path = input.Replace("\"", "").Trim();
|
||||
if (!Directory.Exists(path)) { Console.WriteLine("[ERROR] Folder not found."); continue; }
|
||||
|
||||
Console.WriteLine("2. Enter Namespace (Default: BetterLyrics.WinUI3):");
|
||||
Console.Write("> ");
|
||||
string ns = Console.ReadLine().Trim();
|
||||
if (string.IsNullOrWhiteSpace(ns)) ns = "BetterLyrics.WinUI3";
|
||||
|
||||
string prefix = new DirectoryInfo(path).Name;
|
||||
Console.WriteLine($"3. Enter prefix (Default: {prefix}):");
|
||||
Console.Write("> ");
|
||||
string p = Console.ReadLine().Trim();
|
||||
if (!string.IsNullOrWhiteSpace(p)) prefix = p;
|
||||
|
||||
// 👇👇👇【修复点在这里】👇👇👇
|
||||
// 交互模式下,我们默认把文件生成在 exe 旁边的 AnalyzerOutput 文件夹里
|
||||
string interactiveOutputDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AnalyzerOutput");
|
||||
|
||||
// 传入 interactiveOutputDir 以匹配新的方法签名
|
||||
RunBatch(path, ns, prefix, interactiveOutputDir, silent: false);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// 下面的 RunBatch 和 GenerateFiles 签名已更新支持 outputDir
|
||||
// ---------------------------------------------------------
|
||||
|
||||
static void RunBatch(string scanPath, string ns, string prefix, string outputDir, bool silent)
|
||||
{
|
||||
_currentScanDirectory = scanPath;
|
||||
_mergedAssemblies.Clear();
|
||||
_mergedSystemTypes.Clear();
|
||||
|
||||
ProcessDirectory(scanPath);
|
||||
|
||||
// 传递 outputDir
|
||||
GenerateFiles(prefix, ns, outputDir, silent);
|
||||
}
|
||||
|
||||
static void GenerateFiles(string prefix, string rootNamespace, string outputDir, bool silent)
|
||||
{
|
||||
Directory.CreateDirectory(outputDir);
|
||||
|
||||
string xmlFileName = $"{prefix}_TrimmerRoots.xml";
|
||||
string csFileName = $"{prefix}_TrimmingConfig.cs";
|
||||
|
||||
// 👇 关键修改:区分 Assembly 名和 Namespace 名
|
||||
string assemblyName = rootNamespace; // DLL 名字 (例如 BetterLyrics.WinUI3)
|
||||
string codeNamespace = $"{rootNamespace}.PluginConfigs"; // C# 命名空间 (例如 BetterLyrics.WinUI3.PluginConfigs)
|
||||
|
||||
// 类名和全名
|
||||
string configClassName = $"{prefix.Replace(".", "_").Replace(" ", "_")}_Config";
|
||||
string fullConfigClassName = $"{codeNamespace}.{configClassName}";
|
||||
|
||||
// 路径变量
|
||||
string xmlPath = Path.Combine(outputDir, xmlFileName);
|
||||
string csPath = Path.Combine(outputDir, csFileName);
|
||||
|
||||
// ==========================================
|
||||
// 1. Generate XML
|
||||
// ==========================================
|
||||
var xmlBuilder = new StringBuilder();
|
||||
xmlBuilder.AppendLine("");
|
||||
xmlBuilder.AppendLine("<linker>");
|
||||
|
||||
// A. 保护插件依赖
|
||||
if (_mergedAssemblies.Count > 0)
|
||||
{
|
||||
foreach (var asm in _mergedAssemblies.OrderBy(n => n))
|
||||
xmlBuilder.AppendLine($" <assembly fullname=\"{asm}\" preserve=\"all\" />");
|
||||
}
|
||||
|
||||
// B. 保护生成的 Config 类
|
||||
// ⚠️ 注意:assembly fullname 必须是 rootNamespace (DLL名),而不是 codeNamespace
|
||||
xmlBuilder.AppendLine($" <assembly fullname=\"{assemblyName}\">");
|
||||
xmlBuilder.AppendLine($" <type fullname=\"{fullConfigClassName}\" preserve=\"all\" />");
|
||||
xmlBuilder.AppendLine($" </assembly>");
|
||||
|
||||
xmlBuilder.AppendLine("</linker>");
|
||||
|
||||
// ==========================================
|
||||
// 2. Generate C#
|
||||
// ==========================================
|
||||
var csBuilder = new StringBuilder();
|
||||
csBuilder.AppendLine("// Auto-Generated by PluginAnalyzer");
|
||||
csBuilder.AppendLine("using System.Diagnostics.CodeAnalysis;");
|
||||
csBuilder.AppendLine("using System.Runtime.CompilerServices;");
|
||||
csBuilder.AppendLine("");
|
||||
|
||||
// 👇 这里使用带后缀的命名空间
|
||||
csBuilder.AppendLine($"namespace {codeNamespace};");
|
||||
|
||||
csBuilder.AppendLine($"internal static class {configClassName}");
|
||||
csBuilder.AppendLine("{");
|
||||
|
||||
foreach (var type in _mergedSystemTypes.OrderBy(n => n))
|
||||
{
|
||||
csBuilder.AppendLine($" [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof({type}))]");
|
||||
}
|
||||
|
||||
csBuilder.AppendLine(" [ModuleInitializer]");
|
||||
csBuilder.AppendLine(" internal static void Initialize()");
|
||||
csBuilder.AppendLine(" {");
|
||||
csBuilder.AppendLine(" // This method runs automatically on startup.");
|
||||
csBuilder.AppendLine(" }");
|
||||
csBuilder.AppendLine("}");
|
||||
|
||||
// ==========================================
|
||||
// 3. Write & Notify
|
||||
// ==========================================
|
||||
File.WriteAllText(xmlPath, xmlBuilder.ToString());
|
||||
File.WriteAllText(csPath, csBuilder.ToString());
|
||||
|
||||
if (!silent)
|
||||
{
|
||||
Console.WriteLine($"[Analyzer] Generated: {xmlFileName}");
|
||||
Process.Start("explorer.exe", outputDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[Analyzer] Created: {xmlPath}");
|
||||
Console.WriteLine($"[Analyzer] Created: {csPath}");
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Helpers (逻辑保持不变)
|
||||
// ---------------------------------------------------------
|
||||
|
||||
static void ProcessDirectory(string folderPath)
|
||||
{
|
||||
var files = Directory.GetFiles(folderPath, "*.dll");
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (!IsHostOrSystemBinary(Path.GetFileName(file))) AnalyzeDll(file);
|
||||
}
|
||||
}
|
||||
|
||||
static void AnalyzeDll(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
var resolver = new DefaultAssemblyResolver();
|
||||
resolver.AddSearchDirectory(Path.GetDirectoryName(path));
|
||||
using var assembly = AssemblyDefinition.ReadAssembly(path, new ReaderParameters { AssemblyResolver = resolver });
|
||||
|
||||
foreach (var typeRef in assembly.MainModule.GetTypeReferences())
|
||||
{
|
||||
if (typeRef.Scope is AssemblyNameReference asmRef && !IsIgnoredDependency(asmRef.Name) && !IsLocalDll(asmRef.Name))
|
||||
_mergedAssemblies.Add(asmRef.Name);
|
||||
|
||||
if (typeRef.FullName.StartsWith("System.") || typeRef.FullName.StartsWith("Microsoft.Win32"))
|
||||
_mergedSystemTypes.Add(FormatTypeName(typeRef));
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
static bool IsLocalDll(string asmName) => File.Exists(Path.Combine(_currentScanDirectory, asmName + ".dll"));
|
||||
|
||||
static bool IsHostOrSystemBinary(string fileName)
|
||||
{
|
||||
fileName = fileName.ToLower();
|
||||
return fileName.StartsWith("betterlyrics.") && !fileName.Contains("plugin") ||
|
||||
fileName.StartsWith("microsoft.windows") || fileName.StartsWith("winrt.") || fileName.StartsWith("system.");
|
||||
}
|
||||
|
||||
static bool IsIgnoredDependency(string asmName) => asmName.Contains("BetterLyrics") || asmName.Contains("WindowsAppSDK") || asmName.Contains("Microsoft.Windows") || asmName == "netstandard" || asmName == "mscorlib";
|
||||
|
||||
static string FormatTypeName(TypeReference type)
|
||||
{
|
||||
string name = type.FullName;
|
||||
|
||||
// 1. 处理嵌套类型 (Cecil 用 '/',C# 用 '.')
|
||||
name = name.Replace("/", ".");
|
||||
|
||||
// 2. 处理泛型 (核心修复:根据参数数量动态生成逗号)
|
||||
// List`1 -> List<>
|
||||
// Dictionary`2 -> Dictionary<,>
|
||||
// Tuple`3 -> Tuple<,,>
|
||||
if (name.Contains("`"))
|
||||
{
|
||||
name = Regex.Replace(name, @"`(\d+)", match =>
|
||||
{
|
||||
int argsCount = int.Parse(match.Groups[1].Value);
|
||||
// 逗号数量 = 参数数量 - 1
|
||||
// 比如 1个参数=0个逗号 (<>)
|
||||
// 比如 2个参数=1个逗号 (<,>)
|
||||
return "<" + new string(',', Math.Max(0, argsCount - 1)) + ">";
|
||||
});
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="AutoExcludeSharedAssemblies" AfterTargets="ResolveAssemblyReferences">
|
||||
<PropertyGroup>
|
||||
<HostOutputDir>..\..\BetterLyrics.WinUI3\BetterLyrics.WinUI3\bin\x64\$(Configuration)\$(TargetFramework)\</HostOutputDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<Message Text="[Debug] Searching for Host Assemblies in: $(HostOutputDir)" Importance="High" />
|
||||
|
||||
<ItemGroup>
|
||||
<FilesToCopy Include="@(ReferenceCopyLocalPaths)" />
|
||||
<SharedFiles Include="@(FilesToCopy)" Condition="Exists('$(HostOutputDir)%(Filename)%(Extension)')" />
|
||||
<ReferenceCopyLocalPaths Remove="@(SharedFiles)" />
|
||||
</ItemGroup>
|
||||
|
||||
<Message Text="[Smart Trim] Excluded shared assemblies:%0a@(SharedFiles->' -> %(Filename)%(Extension)', '%0a')" Importance="High" Condition="'@(SharedFiles)' != ''" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RunPluginAnalyzer" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AnalyzerPath>..\..\PluginAnalyzer\bin\Debug\net10.0\PluginAnalyzer.exe</AnalyzerPath>
|
||||
<ScanDir>$(TargetDir)</ScanDir>
|
||||
<Ns>BetterLyrics.WinUI3</Ns>
|
||||
<Prefix>$(ProjectName)</Prefix>
|
||||
|
||||
<OutputDir>..\..\BetterLyrics.WinUI3\BetterLyrics.WinUI3\PluginConfigs\</OutputDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<Message Text="[Analyzer] Delivering configs to Main App..." Importance="High" />
|
||||
<Exec Command=""$(AnalyzerPath)" "$(ScanDir)\" "$(Ns)" "$(Prefix)" "$(OutputDir)\"" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LLamaSharp" Version="0.25.0" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cpu" Version="0.25.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BetterLyrics.Core\BetterLyrics.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
112
Plugins/BetterLyrics.Plugins.AI.Local/Plugin.cs
Normal file
112
Plugins/BetterLyrics.Plugins.AI.Local/Plugin.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using BetterLyrics.Core.Interfaces;
|
||||
using BetterLyrics.Core.Interfaces.Services;
|
||||
using LLama;
|
||||
using LLama.Common;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.Plugins.AI.Local
|
||||
{
|
||||
public class Plugin : IPlugin, IAIService
|
||||
{
|
||||
private LLamaWeights? _model;
|
||||
private ModelParams? _parameters;
|
||||
private string? _modelPath;
|
||||
|
||||
public string Id => "jayfunc.ai";
|
||||
public string Name => "Local AI Service";
|
||||
public string Description => "";
|
||||
public string Author => "jayfunc";
|
||||
public string Version => "1.0.0.0";
|
||||
public DateTime LastUpdated => new DateTime(2026, 1, 12);
|
||||
|
||||
public async Task<string> ChatAsync(string systemPrompt, string userPrompt)
|
||||
{
|
||||
if (_model == null) return "错误:本地模型未加载。请检查插件目录下是否有 .gguf 文件。";
|
||||
|
||||
return await Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_parameters == null)
|
||||
{
|
||||
return "错误:模型参数未正确配置。";
|
||||
}
|
||||
|
||||
// 1. 创建上下文
|
||||
using var context = _model.CreateContext(_parameters);
|
||||
|
||||
// 2. 创建聊天执行器 (InteractiveExecutor 适合聊天)
|
||||
var executor = new InteractiveExecutor(context);
|
||||
|
||||
// 3. 创建会话
|
||||
var session = new ChatSession(executor);
|
||||
|
||||
// 4. 设置系统提示词 (System Prompt)
|
||||
// LLamaSharp 的 ChatSession 处理 System Prompt 稍微有点技巧,通常直接作为第一次输入的一部分或者使用特定的 Prompt 模板
|
||||
// 这里做一个简单的处理:
|
||||
|
||||
var fullPrompt = $"{systemPrompt}\n\n用户: {userPrompt}\n助手:";
|
||||
|
||||
// 5. 运行推理
|
||||
StringBuilder responseBuilder = new StringBuilder();
|
||||
|
||||
// Transform: 将输出流转换为文本
|
||||
// InferenceParams: 设置采样参数 (Temperature 等)
|
||||
var inferenceParams = new InferenceParams()
|
||||
{
|
||||
//Temperature = 0.6f,
|
||||
AntiPrompts = new List<string> { "用户:" } // 防止模型自问自答
|
||||
};
|
||||
|
||||
await foreach (var text in session.ChatAsync(new ChatHistory.Message(AuthorRole.User, userPrompt), inferenceParams: inferenceParams))
|
||||
{
|
||||
responseBuilder.Append(text);
|
||||
}
|
||||
|
||||
return responseBuilder.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return $"推理出错: {ex.Message}";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void OnLoad(IPluginContext context)
|
||||
{
|
||||
_modelPath = Directory.GetFiles(context.PluginDirectory, "*.gguf").FirstOrDefault();
|
||||
|
||||
if (string.IsNullOrEmpty(_modelPath))
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("【LocalAI】未找到 .gguf 模型文件,请下载模型放入插件目录!");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 2. 配置模型参数
|
||||
_parameters = new ModelParams(_modelPath)
|
||||
{
|
||||
ContextSize = 2048, // 上下文长度,根据内存调整
|
||||
GpuLayerCount = 0, // 0 = 纯CPU,设为 20+ 可以通过显卡加速(需安装 Cuda 后端)
|
||||
Threads = 4 // CPU 线程数
|
||||
};
|
||||
|
||||
// 3. 加载模型 (这一步比较耗时,实际开发建议放在后台线程或第一次调用时懒加载)
|
||||
_model = LLamaWeights.LoadFromFile(_parameters);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"【LocalAI】模型加载成功: {_modelPath}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"【LocalAI】模型加载失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnUnload()
|
||||
{
|
||||
_model?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BetterLyrics.Core\BetterLyrics.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
35
Plugins/BetterLyrics.Plugins.Translation.LocalAI/Plugin.cs
Normal file
35
Plugins/BetterLyrics.Plugins.Translation.LocalAI/Plugin.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using BetterLyrics.Core.Interfaces;
|
||||
using BetterLyrics.Core.Interfaces.Features;
|
||||
|
||||
namespace BetterLyrics.Plugins.Translation.LocalAI
|
||||
{
|
||||
public class Plugin : IPlugin, ILyricsTranslator
|
||||
{
|
||||
public string Id => throw new NotImplementedException();
|
||||
|
||||
public string Name => throw new NotImplementedException();
|
||||
|
||||
public string Description => throw new NotImplementedException();
|
||||
|
||||
public string Author => throw new NotImplementedException();
|
||||
|
||||
public string Version => throw new NotImplementedException();
|
||||
|
||||
public DateTime LastUpdated => throw new NotImplementedException();
|
||||
|
||||
public Task<string?> GetTranslationAsync(string text, string targetLangCode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnLoad(IPluginContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnUnload()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
<MeCabUseDefaultDictionary>False</MeCabUseDefaultDictionary>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="customizeDict.txt">
|
||||
<PackagePath>contentFiles\any\any\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\AUTHORS">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\BSD">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\ChangeLog">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\char.bin">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\COPYING">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\dicrc">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\GPL">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\INSTALL">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\LGPL">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\matrix.bin">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\sys.dic">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\unidic-mecab.pdf">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
<Content Include="unidic\unk.dic">
|
||||
<PackagePath>contentFiles\any\any\unidic\</PackagePath>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
<Pack>true</Pack>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MeCab.DotNet" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BetterLyrics.Core\BetterLyrics.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="AutoExcludeSharedAssemblies" AfterTargets="ResolveAssemblyReferences">
|
||||
<PropertyGroup>
|
||||
<HostOutputDir>..\..\BetterLyrics.WinUI3\BetterLyrics.WinUI3\bin\x64\$(Configuration)\$(TargetFramework)\</HostOutputDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<Message Text="[Debug] Searching for Host Assemblies in: $(HostOutputDir)" Importance="High" />
|
||||
|
||||
<ItemGroup>
|
||||
<FilesToCopy Include="@(ReferenceCopyLocalPaths)" />
|
||||
<SharedFiles Include="@(FilesToCopy)" Condition="Exists('$(HostOutputDir)%(Filename)%(Extension)')" />
|
||||
<ReferenceCopyLocalPaths Remove="@(SharedFiles)" />
|
||||
</ItemGroup>
|
||||
|
||||
<Message Text="[Smart Trim] Excluded shared assemblies:%0a@(SharedFiles->' -> %(Filename)%(Extension)', '%0a')" Importance="High" Condition="'@(SharedFiles)' != ''" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RunPluginAnalyzer" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AnalyzerPath>..\..\PluginAnalyzer\bin\Debug\net10.0\PluginAnalyzer.exe</AnalyzerPath>
|
||||
<ScanDir>$(TargetDir)</ScanDir>
|
||||
<Ns>BetterLyrics.WinUI3</Ns>
|
||||
<Prefix>$(ProjectName)</Prefix>
|
||||
|
||||
<OutputDir>..\..\BetterLyrics.WinUI3\BetterLyrics.WinUI3\PluginConfigs\</OutputDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<Message Text="[Analyzer] Delivering configs to Main App..." Importance="High" />
|
||||
<Exec Command=""$(AnalyzerPath)" "$(ScanDir)\" "$(Ns)" "$(Prefix)" "$(OutputDir)\"" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace BetterLyrics.Plugins.Romaji.Extensions
|
||||
{
|
||||
public static class StringExtension
|
||||
{
|
||||
public static string[] LineToUnits(this string str)
|
||||
{
|
||||
return str.Split(new[] { ' ', ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.Plugins.Romaji.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// 此类用于片假、平假互转
|
||||
/// </summary>
|
||||
public static class KanaHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 转为片假名
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToKatakana(string str)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
foreach (var c in str)
|
||||
{
|
||||
var bytes = Encoding.Unicode.GetBytes(c.ToString());
|
||||
if (bytes.Length == 2 && bytes[1] == 0x30 && bytes[0] >= 0x40 && bytes[0] <= 0x9F)
|
||||
stringBuilder.Append(Encoding.Unicode.GetString(new[] { (byte)(bytes[0] + 0x60), bytes[1] }));
|
||||
else
|
||||
stringBuilder.Append(c);
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转为平假名
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToHiragana(string str)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
foreach (var c in str)
|
||||
{
|
||||
var bytes = Encoding.Unicode.GetBytes(c.ToString());
|
||||
if (bytes.Length == 2 && bytes[1] == 0x30 && bytes[0] >= 0xA0 && bytes[0] <= 0xFA)
|
||||
stringBuilder.Append(Encoding.Unicode.GetString(new[] { (byte)(bytes[0] - 0x60), bytes[1] }));
|
||||
else
|
||||
stringBuilder.Append(c);
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 假名转罗马音
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string KatakanaToRomaji(string str)
|
||||
{
|
||||
var result = new StringBuilder();
|
||||
|
||||
for (var i = 0; i < str.Length;)
|
||||
{
|
||||
if (i < str.Length - 1)
|
||||
{
|
||||
var extendedWord = str.Substring(i, 2);
|
||||
if (ExtendedKanaDictionary.ContainsKey(extendedWord))
|
||||
{
|
||||
result.Append(ExtendedKanaDictionary[extendedWord]);
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var word = str[i].ToString();
|
||||
if (KanaDictionary.ContainsKey(word))
|
||||
{
|
||||
//正常转换
|
||||
result.Append(KanaDictionary[word]);
|
||||
}
|
||||
else if (word == "ー")
|
||||
{
|
||||
//长音,取前一个音
|
||||
result.Append(result.Length > 0 ? result[result.Length - 1].ToString() : word);
|
||||
}
|
||||
else
|
||||
{
|
||||
//不能识别,保持原样
|
||||
result.Append(word);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
//处理促音
|
||||
for (var i = 0; i < result.Length; i++)
|
||||
{
|
||||
if (result[i] == 'っ' || result[i] == 'ッ')
|
||||
if (i < result.Length - 1)
|
||||
if (result[i + 1] == 'c')
|
||||
result[i] = 't';
|
||||
else
|
||||
result[i] = result[i + 1];
|
||||
else
|
||||
result.Remove(i, 1);
|
||||
}
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public static Dictionary<string, string> KanaDictionary = new Dictionary<string, string>
|
||||
{
|
||||
//平假
|
||||
{ "あ", "a" }, { "い", "i" }, { "う", "u" }, { "え", "e" }, { "お", "o" },
|
||||
{ "か", "ka" }, { "き", "ki" }, { "く", "ku" }, { "け", "ke" }, { "こ", "ko" },
|
||||
{ "さ", "sa" }, { "し", "shi" }, { "す", "su" }, { "せ", "se" }, { "そ", "so" },
|
||||
{ "た", "ta" }, { "ち", "chi" }, { "つ", "tsu" }, { "て", "te" }, { "と", "to" },
|
||||
{ "な", "na" }, { "に", "ni" }, { "ぬ", "nu" }, { "ね", "ne" }, { "の", "no" },
|
||||
{ "は", "ha" }, { "ひ", "hi" }, { "ふ", "fu" }, { "へ", "he" }, { "ほ", "ho" },
|
||||
{ "ま", "ma" }, { "み", "mi" }, { "む", "mu" }, { "め", "me" }, { "も", "mo" },
|
||||
{ "や", "ya" }, { "ゆ", "yu" }, { "よ", "yo" },
|
||||
{ "ら", "ra" }, { "り", "ri" }, { "る", "ru" }, { "れ", "re" }, { "ろ", "ro" },
|
||||
{ "わ", "wa" }, { "を", "wo" },
|
||||
{ "が", "ga" }, { "ぎ", "gi" }, { "ぐ", "gu" }, { "げ", "ge" }, { "ご", "go" },
|
||||
{ "ざ", "za" }, { "じ", "ji" }, { "ず", "zu" }, { "ぜ", "ze" }, { "ぞ", "zo" },
|
||||
{ "だ", "da" }, { "ぢ", "ji" }, { "づ", "zu" }, { "で", "de" }, { "ど", "do" },
|
||||
{ "ば", "ba" }, { "び", "bi" }, { "ぶ", "bu" }, { "べ", "be" }, { "ぼ", "bo" },
|
||||
{ "ぱ", "pa" }, { "ぴ", "pi" }, { "ぷ", "pu" }, { "ぺ", "pe" }, { "ぽ", "po" },
|
||||
{ "ん", "n" },
|
||||
|
||||
//片假
|
||||
{ "ア", "a" }, { "イ", "i" }, { "ウ", "u" }, { "エ", "e" }, { "オ", "o" },
|
||||
{ "カ", "ka" }, { "キ", "ki" }, { "ク", "ku" }, { "ケ", "ke" }, { "コ", "ko" },
|
||||
{ "サ", "sa" }, { "シ", "shi" }, { "ス", "su" }, { "セ", "se" }, { "ソ", "so" },
|
||||
{ "タ", "ta" }, { "チ", "chi" }, { "ツ", "tsu" }, { "テ", "te" }, { "ト", "to" },
|
||||
{ "ナ", "na" }, { "ニ", "ni" }, { "ヌ", "nu" }, { "ネ", "ne" }, { "ノ", "no" },
|
||||
{ "ハ", "ha" }, { "ヒ", "hi" }, { "フ", "fu" }, { "ヘ", "he" }, { "ホ", "ho" },
|
||||
{ "マ", "ma" }, { "ミ", "mi" }, { "ム", "mu" }, { "メ", "me" }, { "モ", "mo" },
|
||||
{ "ヤ", "ya" }, { "ユ", "yu" }, { "ヨ", "yo" },
|
||||
{ "ラ", "ra" }, { "リ", "ri" }, { "ル", "ru" }, { "レ", "re" }, { "ロ", "ro" },
|
||||
{ "ワ", "wa" }, { "ヲ", "wo" },
|
||||
{ "ガ", "ga" }, { "ギ", "gi" }, { "グ", "gu" }, { "ゲ", "ge" }, { "ゴ", "go" },
|
||||
{ "ザ", "za" }, { "ジ", "ji" }, { "ズ", "zu" }, { "ゼ", "ze" }, { "ゾ", "zo" },
|
||||
{ "ダ", "da" }, { "ヂ", "ji" }, { "ヅ", "zu" }, { "デ", "de" }, { "ド", "do" },
|
||||
{ "バ", "ba" }, { "ビ", "bi" }, { "ブ", "bu" }, { "ベ", "be" }, { "ボ", "bo" },
|
||||
{ "パ", "pa" }, { "ピ", "pi" }, { "プ", "pu" }, { "ペ", "pe" }, { "ポ", "po" },
|
||||
{ "ン", "n" },
|
||||
|
||||
//小版本
|
||||
{ "ぁ", "a" }, { "ぃ", "i" }, { "ぅ", "u" }, { "ぇ", "e" }, { "ぉ", "o" },
|
||||
{ "ゃ", "ya" }, { "ゅ", "yu" }, { "ょ", "yo" }, { "ゎ", "wa" },
|
||||
{ "ァ", "a" }, { "ィ", "i" }, { "ゥ", "u" }, { "ェ", "e" }, { "ォ", "o" },
|
||||
{ "ャ", "ya" }, { "ュ", "yu" }, { "ョ", "yo" }, { "ヮ", "wa" },
|
||||
};
|
||||
|
||||
public static Dictionary<string, string> ExtendedKanaDictionary = new Dictionary<string, string>
|
||||
{
|
||||
//平假-拗音
|
||||
{ "きゃ", "kya" }, { "きゅ", "kyu" }, { "きょ", "kyo" },
|
||||
{ "しゃ", "sha" }, { "しゅ", "shu" }, { "しょ", "sho" },
|
||||
{ "ちゃ", "cha" }, { "ちゅ", "chu" }, { "ちょ", "cho" },
|
||||
{ "にゃ", "nya" }, { "にゅ", "nyu" }, { "にょ", "nyo" },
|
||||
{ "ひゃ", "hya" }, { "ひゅ", "hyu" }, { "ひょ", "hyo" },
|
||||
{ "みゃ", "mya" }, { "みゅ", "myu" }, { "みょ", "myo" },
|
||||
{ "りゃ", "rya" }, { "りゅ", "ryu" }, { "りょ", "ryo" },
|
||||
{ "ぎゃ", "gya" }, { "ぎゅ", "gyu" }, { "ぎょ", "gyo" },
|
||||
{ "じゃ", "ja" }, { "じゅ", "ju" }, { "じょ", "jo" },
|
||||
{ "ぢゃ", "ja" }, { "ぢゅ", "ju" }, { "ぢょ", "jo" },
|
||||
{ "びゃ", "bya" }, { "びゅ", "byu" }, { "びょ", "byo" },
|
||||
{ "ぴゃ", "pya" }, { "ぴゅ", "pyu" }, { "ぴょ", "pyo" },
|
||||
|
||||
//片假-拗音
|
||||
{ "キャ", "kya" }, { "キュ", "kyu" }, { "キョ", "kyo" },
|
||||
{ "シャ", "sha" }, { "シュ", "shu" }, { "ショ", "sho" },
|
||||
{ "チャ", "cha" }, { "チュ", "chu" }, { "チョ", "cho" },
|
||||
{ "ニャ", "nya" }, { "ニュ", "nyu" }, { "ニョ", "nyo" },
|
||||
{ "ヒャ", "hya" }, { "ヒュ", "hyu" }, { "ヒョ", "hyo" },
|
||||
{ "ミャ", "mya" }, { "ミュ", "myu" }, { "ミョ", "myo" },
|
||||
{ "リャ", "rya" }, { "リュ", "ryu" }, { "リョ", "ryo" },
|
||||
{ "ギャ", "gya" }, { "ギュ", "gyu" }, { "ギョ", "gyo" },
|
||||
{ "ジャ", "ja" }, { "ジュ", "ju" }, { "ジョ", "jo" },
|
||||
{ "ヂャ", "ja" }, { "ヂュ", "ju" }, { "ヂョ", "jo" },
|
||||
{ "ビャ", "bya" }, { "ビュ", "byu" }, { "ビョ", "byo" },
|
||||
{ "ピャ", "pya" }, { "ピュ", "pyu" }, { "ピョ", "pyo" },
|
||||
|
||||
//其他语言
|
||||
{ "イェ", "ye" },
|
||||
{ "ウィ", "wi" }, { "ウェ", "we" }, { "ウォ", "wo" },
|
||||
{ "ヴァ", "va" }, { "ヴィ", "vi" }, { "ヴ", "vu" }, { "ヴェ", "ve" }, { "ヴォ", "vo" },
|
||||
{ "ヴュ", "vyu" },
|
||||
{ "クァ", "kwa" }, { "クィ", "kwi" }, { "クェ", "kwe" }, { "クォ", "kwo" },
|
||||
{ "グァ", "gwa" },
|
||||
{ "シェ", "she" },
|
||||
{ "ジェ", "je" },
|
||||
{ "チェ", "che" },
|
||||
{ "ツァ", "tsa" }, { "ツィ", "tsi" }, { "ツェ", "tse" }, { "ツォ", "tso" },
|
||||
{ "ティ", "ti" }, { "トゥ", "tu" },
|
||||
{ "テュ", "tyu" },
|
||||
{ "ディ", "di" }, { "ドゥ", "du" },
|
||||
{ "デュ", "dyu" },
|
||||
{ "ファ", "fa" }, { "フィ", "fi" }, { "フェ", "fe" }, { "フォ", "fo" },
|
||||
{ "フュ", "fyu" },
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace BetterLyrics.Plugins.Romaji.Helpers
|
||||
{
|
||||
public static class LrcParser
|
||||
{
|
||||
public static readonly Regex LrcLineRegex =
|
||||
new Regex("(\\[(\\d+:)?\\d+:\\d+(\\.\\d+)?\\])+\\s*(?<text>.*?(?=\\[(\\d+:)?\\d+:\\d+(\\.\\d+)?\\]|$|\\r|\\n))",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
public static readonly Regex LrcTimeRegex =
|
||||
new Regex("\\[((?<hour>\\d+):)?(?<minute>\\d+):(?<second>\\d+)(\\.(?<millisecond>\\d+))?\\]", RegexOptions.Compiled);
|
||||
|
||||
public static List<(TimeSpan Time, string Text)> Parse(string lrc)
|
||||
{
|
||||
var result = new List<(TimeSpan Time, string Text)>();
|
||||
|
||||
var lineMatches = LrcLineRegex.Matches(lrc);
|
||||
foreach (Match lineMatch in lineMatches)
|
||||
{
|
||||
var text = lineMatch.Groups["text"].Value;
|
||||
var timeMatches = LrcTimeRegex.Matches(lineMatch.Value);
|
||||
foreach (Match timeMatch in timeMatches)
|
||||
{
|
||||
var hour = timeMatch.Groups["hour"].Success ? int.Parse(timeMatch.Groups["hour"].Value) : 0;
|
||||
var minute = timeMatch.Groups["minute"].Success ? int.Parse(timeMatch.Groups["minute"].Value) : 0;
|
||||
var second = timeMatch.Groups["second"].Success ? int.Parse(timeMatch.Groups["second"].Value) : 0;
|
||||
var millisecond = timeMatch.Groups["millisecond"].Success
|
||||
? int.Parse(timeMatch.Groups["millisecond"].Value)
|
||||
: 0;
|
||||
var time = new TimeSpan(0, hour, minute, second, millisecond);
|
||||
result.Add((time, text));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
using MeCab;
|
||||
using MeCab.Extension.UniDic;
|
||||
using BetterLyrics.Plugins.Romaji.Extensions;
|
||||
using BetterLyrics.Plugins.Romaji.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using BetterLyrics.Plugins.Romaji.Options;
|
||||
|
||||
namespace BetterLyrics.Plugins.Romaji.Helpers
|
||||
{
|
||||
public static class RomajiHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 分词器
|
||||
/// </summary>
|
||||
private static MeCabTagger _tagger;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义词典<原文, 假名>
|
||||
/// </summary>
|
||||
private static Dictionary<string, string> _customizeDict;
|
||||
|
||||
public static void Init(string baseDirectory = null)
|
||||
{
|
||||
string rootPath = !string.IsNullOrEmpty(baseDirectory)
|
||||
? baseDirectory
|
||||
: AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
//词典路径
|
||||
var dicPath = Path.Combine(rootPath, "unidic");
|
||||
var parameter = new MeCabParam
|
||||
{
|
||||
DicDir = dicPath,
|
||||
LatticeLevel = MeCabLatticeLevel.Zero
|
||||
};
|
||||
_tagger = MeCabTagger.Create(parameter);
|
||||
|
||||
var str = File.ReadAllText(Path.Combine(rootPath, "customizeDict.txt"));
|
||||
var list = str.Split(Environment.NewLine.ToArray());
|
||||
_customizeDict = new Dictionary<string, string>();
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(item)) continue;
|
||||
var array = item.Split(' ');
|
||||
if (array.Length < 2) continue;
|
||||
if (!_customizeDict.ContainsKey(array[0]))
|
||||
_customizeDict.Add(array[0], array[1]);
|
||||
}
|
||||
}
|
||||
|
||||
#region 主逻辑
|
||||
|
||||
/// <summary>
|
||||
/// 生成转换结果列表
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<ConvertedLine> ToRomaji(string text, ToRomajiOptions options = null)
|
||||
{
|
||||
options = options ?? new ToRomajiOptions();
|
||||
|
||||
var timeSpans = new List<TimeSpan?>();
|
||||
var lineTextList = text.Split(Environment.NewLine.ToArray()).Where(p => !string.IsNullOrWhiteSpace(p)).ToList();
|
||||
|
||||
for (var i = 0; i < lineTextList.Count; i++)
|
||||
{
|
||||
if (LrcParser.LrcLineRegex.IsMatch(lineTextList[i]))
|
||||
{
|
||||
var lyric = LrcParser.Parse(lineTextList[i]).FirstOrDefault();
|
||||
timeSpans.Add(lyric.Time);
|
||||
lineTextList[i] = lyric.Text;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeSpans.Add(null);
|
||||
}
|
||||
}
|
||||
|
||||
ushort lineIndex = 0;
|
||||
for (var index = 0; index < lineTextList.Count; index++)
|
||||
{
|
||||
var line = lineTextList[index];
|
||||
|
||||
if (IsChinese(line, options.ChineseRate)) continue;
|
||||
|
||||
var convertedLine = new ConvertedLine
|
||||
{
|
||||
Index = lineIndex,
|
||||
Time = index < timeSpans.Count ? timeSpans[index] : null,
|
||||
Japanese = line.Replace("\0", "")
|
||||
};
|
||||
|
||||
foreach (var sentence in convertedLine.Japanese.LineToUnits())
|
||||
{
|
||||
if (IsEnglish(sentence))
|
||||
{
|
||||
convertedLine.Units.Add(new ConvertedUnit(lineIndex, sentence, sentence, sentence, false));
|
||||
}
|
||||
else
|
||||
foreach (var unit in SentenceToRomaji(lineIndex, sentence, options.IsParticleAsPronunciation))
|
||||
convertedLine.Units.Add(unit);
|
||||
}
|
||||
|
||||
if (index + 1 < lineTextList.Count && IsChinese(lineTextList[index + 1], options.ChineseRate))
|
||||
convertedLine.Chinese = lineTextList[index + 1];
|
||||
|
||||
lineIndex++;
|
||||
yield return convertedLine;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分句转为罗马音
|
||||
/// </summary>
|
||||
/// <param name="lineIndex"></param>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="isParticleAsPronunciation"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<ConvertedUnit> SentenceToRomaji(ushort lineIndex, string str, bool isParticleAsPronunciation)
|
||||
{
|
||||
foreach (var item in _tagger.ParseToNodes(str))
|
||||
{
|
||||
var unit = MeCabNodeToUnit(lineIndex, item, isParticleAsPronunciation);
|
||||
|
||||
if (unit != null)
|
||||
yield return unit;
|
||||
}
|
||||
}
|
||||
|
||||
public static ConvertedUnit MeCabNodeToUnit(ushort lineIndex, MeCabNode item, bool isParticleAsPronunciation)
|
||||
{
|
||||
ConvertedUnit unit = null;
|
||||
if (item.CharType > 0)
|
||||
{
|
||||
var features = CustomSplit(item.Feature);
|
||||
if (TryCustomConvert(item.Surface, out var customResult))
|
||||
{
|
||||
//用户自定义词典
|
||||
unit = new ConvertedUnit(lineIndex,
|
||||
item.Surface,
|
||||
customResult,
|
||||
KanaHelper.KatakanaToRomaji(customResult),
|
||||
true);
|
||||
}
|
||||
else if (features.Length > 0 && (!isParticleAsPronunciation || item.GetPos1() != "助詞") && IsJapanese(item.Surface))
|
||||
{
|
||||
//纯假名
|
||||
unit = new ConvertedUnit(lineIndex,
|
||||
item.Surface,
|
||||
KanaHelper.ToHiragana(item.Surface),
|
||||
KanaHelper.KatakanaToRomaji(item.Surface),
|
||||
false);
|
||||
}
|
||||
else if (features.Length <= 6 || new[] { "補助記号" }.Contains(item.GetPos1()))
|
||||
{
|
||||
//标点符号或无法识别的字
|
||||
unit = new ConvertedUnit(lineIndex,
|
||||
item.Surface,
|
||||
item.Surface,
|
||||
item.Surface,
|
||||
false);
|
||||
}
|
||||
else if (IsEnglish(item.Surface))
|
||||
{
|
||||
//英文
|
||||
unit = new ConvertedUnit(lineIndex,
|
||||
item.Surface,
|
||||
item.Surface,
|
||||
item.Surface,
|
||||
false);
|
||||
}
|
||||
else
|
||||
{
|
||||
//汉字或助词
|
||||
var kana = GetKana(item);
|
||||
|
||||
unit = new ConvertedUnit(lineIndex,
|
||||
item.Surface,
|
||||
KanaHelper.ToHiragana(kana),
|
||||
KanaHelper.KatakanaToRomaji(kana),
|
||||
!IsJapanese(item.Surface));
|
||||
var (replaceHiragana, replaceRomaji) = GetReplaceData(item);
|
||||
unit.ReplaceHiragana = replaceHiragana;
|
||||
unit.ReplaceRomaji = replaceRomaji;
|
||||
}
|
||||
}
|
||||
else if (item.Stat != MeCabNodeStat.Bos && item.Stat != MeCabNodeStat.Eos)
|
||||
{
|
||||
unit = new ConvertedUnit(lineIndex,
|
||||
item.Surface,
|
||||
item.Surface,
|
||||
item.Surface,
|
||||
false);
|
||||
}
|
||||
|
||||
return unit;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 帮助方法
|
||||
|
||||
/// <summary>
|
||||
/// 自定义分隔方法(Feature可能存在如 a,b,c,"d,e",f 格式的数据,此处不能把双引号中的内容也分隔开)
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
private static string[] CustomSplit(string str)
|
||||
{
|
||||
var list = new List<string>();
|
||||
var item = new List<char>();
|
||||
var haveMark = false;
|
||||
foreach (var c in str)
|
||||
if (c == ',' && !haveMark)
|
||||
{
|
||||
list.Add(new string(item.ToArray()));
|
||||
item.Clear();
|
||||
}
|
||||
else if (c == '"')
|
||||
{
|
||||
item.Add(c);
|
||||
haveMark = !haveMark;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Add(c);
|
||||
}
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有发音
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
/// <returns></returns>
|
||||
private static (ObservableCollection<ReplaceString> replaceHiragana, ObservableCollection<ReplaceString>
|
||||
replaceRomaji) GetReplaceData(MeCabNode node)
|
||||
{
|
||||
var length = node.Length;
|
||||
var replaceNodeList = new List<MeCabNode>();
|
||||
|
||||
GetAllReplaceNode(replaceNodeList, node);
|
||||
|
||||
void GetAllReplaceNode(List<MeCabNode> list, MeCabNode n)
|
||||
{
|
||||
if (n != null && !list.Contains(n) && n.Length == length)
|
||||
{
|
||||
list.Add(n);
|
||||
GetAllReplaceNode(list, n.BNext);
|
||||
GetAllReplaceNode(list, n.ENext);
|
||||
}
|
||||
}
|
||||
|
||||
var replaceHiragana = new ObservableCollection<ReplaceString>();
|
||||
var replaceRomaji = new ObservableCollection<ReplaceString>();
|
||||
|
||||
ushort i = 1;
|
||||
foreach (var meCabNode in replaceNodeList
|
||||
.GroupBy(GetKana)
|
||||
.Select(g => g.First()))
|
||||
{
|
||||
var kana = GetKana(meCabNode);
|
||||
if (kana != null)
|
||||
{
|
||||
replaceHiragana.Add(new ReplaceString(i, KanaHelper.ToHiragana(kana), true));
|
||||
replaceRomaji.Add(new ReplaceString(i, KanaHelper.KatakanaToRomaji(kana), true));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return (replaceHiragana, replaceRomaji);
|
||||
}
|
||||
|
||||
private static string GetKana(MeCabNode node)
|
||||
{
|
||||
return node.GetPos1() == "助詞" ? node.GetPron() : node.GetKana();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自定义转换规则
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
private static bool TryCustomConvert(string str, out string result)
|
||||
{
|
||||
if (_customizeDict.ContainsKey(str))
|
||||
{
|
||||
result = _customizeDict[str];
|
||||
return true;
|
||||
}
|
||||
|
||||
result = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断字符串(句子)是否简体中文
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="rate">容错率(0-1)</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsChinese(string str, float rate)
|
||||
{
|
||||
if (str.Length < 2)
|
||||
return false;
|
||||
|
||||
var wordArray = str.ToCharArray();
|
||||
var total = wordArray.Length;
|
||||
var chCount = 0f;
|
||||
var enCount = 0f;
|
||||
|
||||
foreach (var word in wordArray)
|
||||
{
|
||||
if (word != 'ー' && IsJapanese(word.ToString()))
|
||||
//含有日文直接返回否
|
||||
return false;
|
||||
|
||||
var gbBytes = Encoding.Unicode.GetBytes(word.ToString());
|
||||
|
||||
if (gbBytes.Length == 2) // double bytes char.
|
||||
{
|
||||
if (gbBytes[1] >= 0x4E && gbBytes[1] <= 0x9F) //中文
|
||||
chCount++;
|
||||
else
|
||||
total--;
|
||||
}
|
||||
else if (gbBytes.Length == 1)
|
||||
{
|
||||
var byteAscii = int.Parse(gbBytes[0].ToString());
|
||||
if ((byteAscii >= 65 && byteAscii <= 90) || (byteAscii >= 97 && byteAscii <= 122)) //英文字母
|
||||
enCount++;
|
||||
else
|
||||
total--;
|
||||
}
|
||||
}
|
||||
|
||||
if (chCount == 0) return false; //一个简体中文都没有
|
||||
|
||||
return (chCount + enCount) / total >= rate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断字符串是否全为单字节
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsEnglish(string str)
|
||||
{
|
||||
return new Regex("^[\x20-\x7E]+$", RegexOptions.Compiled).IsMatch(str);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断字符串是否全为假名
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
private static bool IsJapanese(string str)
|
||||
{
|
||||
return Regex.IsMatch(str, @"^[\u3040-\u30ff]+$", RegexOptions.Compiled);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace BetterLyrics.Plugins.Romaji.Models
|
||||
{
|
||||
public class ConvertedLine
|
||||
{
|
||||
public ushort Index { get; set; } = 0;
|
||||
|
||||
public TimeSpan? Time { get; set; }
|
||||
|
||||
public string Chinese { get; set; } = string.Empty;
|
||||
|
||||
public string Japanese { get; set; } = string.Empty;
|
||||
|
||||
public ObservableCollection<ConvertedUnit> Units { get; set; } = new ObservableCollection<ConvertedUnit>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace BetterLyrics.Plugins.Romaji.Models
|
||||
{
|
||||
public class ConvertedUnit : INotifyPropertyChanged
|
||||
{
|
||||
private string _hiragana;
|
||||
private bool _isKanji;
|
||||
private string _japanese;
|
||||
private ObservableCollection<ReplaceString> _replaceHiragana;
|
||||
private ObservableCollection<ReplaceString> _replaceRomaji;
|
||||
private string _romaji;
|
||||
private ushort _selectId;
|
||||
private ushort _lineIndex;
|
||||
|
||||
public ConvertedUnit(ushort lineIndex, string japanese, string hiragana, string romaji, bool isKanji)
|
||||
{
|
||||
LineIndex = lineIndex;
|
||||
Japanese = japanese;
|
||||
Romaji = romaji;
|
||||
Hiragana = hiragana;
|
||||
IsKanji = isKanji;
|
||||
SelectId = 1;
|
||||
ReplaceHiragana = new ObservableCollection<ReplaceString> { new ReplaceString(1, hiragana, true) };
|
||||
ReplaceRomaji = new ObservableCollection<ReplaceString> { new ReplaceString(1, romaji, true) };
|
||||
}
|
||||
|
||||
public ushort LineIndex
|
||||
{
|
||||
get => _lineIndex;
|
||||
set
|
||||
{
|
||||
if (value == _lineIndex) return;
|
||||
_lineIndex = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public string Japanese
|
||||
{
|
||||
get => _japanese;
|
||||
set
|
||||
{
|
||||
if (value == _japanese) return;
|
||||
_japanese = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public string Romaji
|
||||
{
|
||||
get => _romaji;
|
||||
set
|
||||
{
|
||||
if (value == _romaji) return;
|
||||
_romaji = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<ReplaceString> ReplaceRomaji
|
||||
{
|
||||
get => _replaceRomaji;
|
||||
set
|
||||
{
|
||||
if (Equals(value, _replaceRomaji)) return;
|
||||
_replaceRomaji = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public string Hiragana
|
||||
{
|
||||
get => _hiragana;
|
||||
set
|
||||
{
|
||||
if (value == _hiragana) return;
|
||||
_hiragana = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<ReplaceString> ReplaceHiragana
|
||||
{
|
||||
get => _replaceHiragana;
|
||||
set
|
||||
{
|
||||
if (Equals(value, _replaceHiragana)) return;
|
||||
_replaceHiragana = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsKanji
|
||||
{
|
||||
get => _isKanji;
|
||||
set
|
||||
{
|
||||
if (value == _isKanji) return;
|
||||
_isKanji = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public ushort SelectId
|
||||
{
|
||||
get => _selectId;
|
||||
set
|
||||
{
|
||||
if (value == _selectId) return;
|
||||
_selectId = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace BetterLyrics.Plugins.Romaji.Models
|
||||
{
|
||||
public class ReplaceString
|
||||
{
|
||||
public ReplaceString(ushort id, string value, bool isSystem)
|
||||
{
|
||||
Id = id;
|
||||
Value = value;
|
||||
IsSystem = isSystem;
|
||||
}
|
||||
|
||||
public ushort Id { get; set; }
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
public bool IsSystem { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace BetterLyrics.Plugins.Romaji.Options
|
||||
{
|
||||
public class ToRomajiOptions
|
||||
{
|
||||
public float ChineseRate { get; set; } = 1f;
|
||||
|
||||
public bool IsParticleAsPronunciation { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using BetterLyrics.Core.Interfaces;
|
||||
using BetterLyrics.Core.Interfaces.Features;
|
||||
using BetterLyrics.Plugins.Romaji.Helpers;
|
||||
|
||||
namespace BetterLyrics.Plugins.Transliteration.Romaji
|
||||
{
|
||||
public class Plugin : ILyricsTransliterator
|
||||
{
|
||||
public string Id => "jayfunc.romaji";
|
||||
public string Name => "Romaji";
|
||||
public string Description => "Convert Japanese lyrics to Romaji transliteration.";
|
||||
public string Author => "jayfunc";
|
||||
public string Version => "1.0.0";
|
||||
public DateTime LastUpdated => new DateTime(2026, 1, 12);
|
||||
|
||||
public void OnLoad(IPluginContext context)
|
||||
{
|
||||
RomajiHelper.Init(context.PluginDirectory);
|
||||
}
|
||||
|
||||
public Task<string?> GetTransliterationAsync(string text, string targetLangCode)
|
||||
{
|
||||
string? result = null;
|
||||
if (targetLangCode == "ja-latin")
|
||||
{
|
||||
var lines = text.Split("\n");
|
||||
result = string.Join("\n", lines.Select(p => string.Join(" ", RomajiHelper.ToRomaji(p).FirstOrDefault()?.Units.Select(q => q.Romaji) ?? [""])));
|
||||
}
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public void OnUnload()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
## Credits
|
||||
|
||||
`Extensions` `Helpers` `Models` `Options` folders are based on the [RomajiConverter.WinUI](https://github.com/xyh20180101/RomajiConverter.WinUI) project (by [xyh20180101](https://github.com/xyh20180101)).
|
||||
All credits for those files go to the original author.
|
||||
|
||||
## Before you build...
|
||||
|
||||
- Download `unidic-mecab-2.1.2_bin.zip` from https://clrd.ninjal.ac.jp/unidic_archive/cwj/2.1.2/
|
||||
- Unzip it and copy the contents of the `dic` folder to `BetterLyrics.Plugins.Romaji\unidic`
|
||||
@@ -0,0 +1 @@
|
||||
私 わたし
|
||||
16
README.CN.md
16
README.CN.md
@@ -20,7 +20,7 @@
|
||||
|
||||
<br>
|
||||
|
||||
<img src="Promotion/banner.png" alt="Banner" width="100%" style="border-radius: 10px;">
|
||||
<img src="docs/assets/promotion/banner.png" alt="Banner" width="100%" style="border-radius: 10px;">
|
||||
|
||||
</div>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
| :---: | :---: |
|
||||
| <a href="https://apps.microsoft.com/detail/9P1WCD1P597R?referrer=appbadge&mode=direct"><img src="https://get.microsoft.com/images/en-us%20dark.svg" width="160"/></a><br>无限期免费试用(功能与付费版一致) | [**📦 最新版本 (.zip)**](https://github.com/jayfunc/BetterLyrics/releases/latest)<br>[查看安装指南](https://www.cnblogs.com/jayfunc/p/19212078) |
|
||||
|
||||
[📖 用户指南](https://github.com/jayfunc/BetterLyrics/wiki/使用指南) | [🔒 隐私政策](PrivacyPolicy.CN.md) | [⚖️ 服务条款](TermsofService.CN.md)
|
||||
[📖 用户指南](docs/USER_GUIDE.CN.md) | [🔒 隐私政策](docs/PRIVACY_POLICY.CN.md) | [⚖️ 服务条款](docs/TERMS_OF_SERVICE.CN.md)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -80,19 +80,19 @@
|
||||
|
||||
| 标准视图 | 侧边栏模式 |
|
||||
| :---: | :---: |
|
||||
| <img src="Screenshots/std.png" width="100%"> | <img src="Screenshots/narrow.png" width="100%"> |
|
||||
| <img src="docs/assets/screenshots/std.png" width="100%"> | <img src="docs/assets/screenshots/narrow.png" width="100%"> |
|
||||
|
||||
| 歌词视觉特效 | 多模式共存 |
|
||||
| :---: | :---: |
|
||||
| <img src="Screenshots/effect.png" width="100%"> | <img src="Screenshots/all-in-one.png" width="100%"> |
|
||||
| <img src="docs/assets/screenshots/effect.png" width="100%"> | <img src="docs/assets/screenshots/all-in-one.png" width="100%"> |
|
||||
|
||||
| 全屏模式 | 全屏模式 |
|
||||
| :---: | :---: |
|
||||
| <img src="Screenshots/fs3.png" width="100%"> | <img src="Screenshots/fs2.png" width="100%"> |
|
||||
| <img src="docs/assets/screenshots/fs3.png" width="100%"> | <img src="docs/assets/screenshots/fs2.png" width="100%"> |
|
||||
|
||||
| 音乐库 | 播放统计 |
|
||||
| :---: | :---: |
|
||||
| <img src="Screenshots/music-gallery.png" width="100%"> | <img src="Screenshots/stats.png" width="100%"> |
|
||||
| <img src="docs/assets/screenshots/music-gallery.png" width="100%"> | <img src="docs/assets/screenshots/stats.png" width="100%"> |
|
||||
|
||||
</div>
|
||||
|
||||
@@ -104,6 +104,8 @@
|
||||
|
||||
**协助翻译:** 找不到你的语言?[点此开始翻译](https://github.com/jayfunc/BetterLyrics?tab=contributing-ov-file)。
|
||||
|
||||
**开发插件:** 想要扩展功能?[🧩 阅读插件开发指南](docs/PLUGIN_DEV.CN.md)。
|
||||
|
||||
**从源码构建:**
|
||||
> 构建前,请确保已替换 `Constants` 文件夹下的 `DiscordTemplate.cs` 和 `LastFM.cs`。
|
||||
|
||||
@@ -115,7 +117,7 @@
|
||||
|
||||
| 网页平台 | 支付宝 (扫码) | 微信 (扫码) |
|
||||
| :---: | :---: | :---: |
|
||||
| [PayPal](https://paypal.me/zhefangpay)<br><br>[Buy Me a Coffee](https://buymeacoffee.com/founchoo)<br><br>[爱发电 (Afdian)](https://afdian.com/a/jayfunc) | <img src="Donate/Alipay.jpg" width="150"> | <img src="Donate/WeChatReward.png" width="150"> |
|
||||
| [PayPal](https://paypal.me/zhefangpay)<br><br>[Buy Me a Coffee](https://buymeacoffee.com/founchoo)<br><br>[爱发电 (Afdian)](https://afdian.com/a/jayfunc) | <img src="docs/assets/donate/Alipay.jpg" width="150"> | <img src="docs/assets/donate/WeChatReward.png" width="150"> |
|
||||
|
||||
**[查看完整赞助者名单 (Hall of Fame)](SPONSORS.md)**
|
||||
|
||||
|
||||
16
README.md
16
README.md
@@ -20,7 +20,7 @@
|
||||
|
||||
<br>
|
||||
|
||||
<img src="Promotion/banner.png" alt="Banner" width="100%" style="border-radius: 10px;">
|
||||
<img src="docs/assets/promotion/banner.png" alt="Banner" width="100%" style="border-radius: 10px;">
|
||||
|
||||
</div>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
| :---: | :---: |
|
||||
| <a href="https://apps.microsoft.com/detail/9P1WCD1P597R?referrer=appbadge&mode=direct"><img src="https://get.microsoft.com/images/en-us%20dark.svg" width="160"/></a><br>Unlimited free trial (Same as paid) | [**📦 Latest Release (.zip)**](https://github.com/jayfunc/BetterLyrics/releases/latest)<br>See [Installation Guide](https://jayfunc.blog/blog/how-to-install-zip) |
|
||||
|
||||
[📖 User Guide](https://github.com/jayfunc/BetterLyrics/wiki/User-Guide) | [🔒 Privacy Policy](PrivacyPolicy.md) | [⚖️ Terms of Service](TermsofService.md)
|
||||
[📖 User Guide](docs/USER_GUIDE.md) | [🔒 Privacy Policy](docs/PRIVACY_POLICY.md) | [⚖️ Terms of Service](docs/TERMS_OF_SERVICE.md)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -80,19 +80,19 @@
|
||||
|
||||
| Standard View | Narrow Mode |
|
||||
| :---: | :---: |
|
||||
| <img src="Screenshots/std.png" width="100%"> | <img src="Screenshots/narrow.png" width="100%"> |
|
||||
| <img src="docs/assets/screenshots/std.png" width="100%"> | <img src="docs/assets/screenshots/narrow.png" width="100%"> |
|
||||
|
||||
| Lyrics Visual Effects | Coexisting Modes |
|
||||
| :---: | :---: |
|
||||
| <img src="Screenshots/effect.png" width="100%"> | <img src="Screenshots/all-in-one.png" width="100%"> |
|
||||
| <img src="docs/assets/screenshots/effect.png" width="100%"> | <img src="docs/assets/screenshots/all-in-one.png" width="100%"> |
|
||||
|
||||
| Fullscreen Mode | Fullscreen Mode |
|
||||
| :---: | :---: |
|
||||
| <img src="Screenshots/fs3.png" width="100%"> | <img src="Screenshots/fs2.png" width="100%"> |
|
||||
| <img src="docs/assets/screenshots/fs3.png" width="100%"> | <img src="docs/assets/screenshots/fs2.png" width="100%"> |
|
||||
|
||||
| Music Gallery | Playback Statistics |
|
||||
| :---: | :---: |
|
||||
| <img src="Screenshots/music-gallery.png" width="100%"> | <img src="Screenshots/stats.png" width="100%"> |
|
||||
| <img src="docs/assets/screenshots/music-gallery.png" width="100%"> | <img src="docs/assets/screenshots/stats.png" width="100%"> |
|
||||
|
||||
</div>
|
||||
|
||||
@@ -104,6 +104,8 @@
|
||||
|
||||
**Help us translate:** Cannot find your language? [Start translating here](https://github.com/jayfunc/BetterLyrics?tab=contributing-ov-file).
|
||||
|
||||
**Develop Plugins:** Want to extend functionality? [🧩 Read the Developer Guide](docs/PLUGIN_DEV.md).
|
||||
|
||||
**Build from source:**
|
||||
> Before building, ensure you have replaced `DiscordTemplate.cs` and `LastFM.cs` in the `Constants` folder.
|
||||
|
||||
@@ -115,7 +117,7 @@ If you like BetterLyrics, please consider supporting it. Your support helps keep
|
||||
|
||||
| Web Platforms | Alipay (QR) | WeChat (QR) |
|
||||
| :---: | :---: | :---: |
|
||||
| [PayPal](https://paypal.me/zhefangpay)<br><br>[Buy Me a Coffee](https://buymeacoffee.com/founchoo)<br><br>[爱发电 (Afdian)](https://afdian.com/a/jayfunc) | <img src="Donate/Alipay.jpg" width="150"> | <img src="Donate/WeChatReward.png" width="150"> |
|
||||
| [PayPal](https://paypal.me/zhefangpay)<br><br>[Buy Me a Coffee](https://buymeacoffee.com/founchoo)<br><br>[爱发电 (Afdian)](https://afdian.com/a/jayfunc) | <img src="docs/assets/donate/Alipay.jpg" width="150"> | <img src="docs/assets/donate/WeChatReward.png" width="150"> |
|
||||
|
||||
**[View the full Hall of Fame (Sponsors)](SPONSORS.md)**
|
||||
|
||||
|
||||
13
RomajiConverter.Core/Extensions/StringExtension.cs
Normal file
13
RomajiConverter.Core/Extensions/StringExtension.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace RomajiConverter.Core.Extensions
|
||||
{
|
||||
public static class StringExtension
|
||||
{
|
||||
public static string[] LineToUnits(this string str)
|
||||
{
|
||||
return str.Split(new[] { ' ', ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
}
|
||||
}
|
||||
203
RomajiConverter.Core/Helpers/KanaHelper.cs
Normal file
203
RomajiConverter.Core/Helpers/KanaHelper.cs
Normal file
@@ -0,0 +1,203 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace RomajiConverter.Core.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// 此类用于片假、平假互转
|
||||
/// </summary>
|
||||
public static class KanaHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 转为片假名
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToKatakana(string str)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
foreach (var c in str)
|
||||
{
|
||||
var bytes = Encoding.Unicode.GetBytes(c.ToString());
|
||||
if (bytes.Length == 2 && bytes[1] == 0x30 && bytes[0] >= 0x40 && bytes[0] <= 0x9F)
|
||||
stringBuilder.Append(Encoding.Unicode.GetString(new[] { (byte)(bytes[0] + 0x60), bytes[1] }));
|
||||
else
|
||||
stringBuilder.Append(c);
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转为平假名
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToHiragana(string str)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
foreach (var c in str)
|
||||
{
|
||||
var bytes = Encoding.Unicode.GetBytes(c.ToString());
|
||||
if (bytes.Length == 2 && bytes[1] == 0x30 && bytes[0] >= 0xA0 && bytes[0] <= 0xFA)
|
||||
stringBuilder.Append(Encoding.Unicode.GetString(new[] { (byte)(bytes[0] - 0x60), bytes[1] }));
|
||||
else
|
||||
stringBuilder.Append(c);
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 假名转罗马音
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string KatakanaToRomaji(string str)
|
||||
{
|
||||
var result = new StringBuilder();
|
||||
|
||||
for (var i = 0; i < str.Length;)
|
||||
{
|
||||
if (i < str.Length - 1)
|
||||
{
|
||||
var extendedWord = str.Substring(i, 2);
|
||||
if (ExtendedKanaDictionary.ContainsKey(extendedWord))
|
||||
{
|
||||
result.Append(ExtendedKanaDictionary[extendedWord]);
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var word = str[i].ToString();
|
||||
if (KanaDictionary.ContainsKey(word))
|
||||
{
|
||||
//正常转换
|
||||
result.Append(KanaDictionary[word]);
|
||||
}
|
||||
else if (word == "ー")
|
||||
{
|
||||
//长音,取前一个音
|
||||
result.Append(result.Length > 0 ? result[result.Length - 1].ToString() : word);
|
||||
}
|
||||
else
|
||||
{
|
||||
//不能识别,保持原样
|
||||
result.Append(word);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
//处理促音
|
||||
for (var i = 0; i < result.Length; i++)
|
||||
{
|
||||
if (result[i] == 'っ' || result[i] == 'ッ')
|
||||
if (i < result.Length - 1)
|
||||
if (result[i + 1] == 'c')
|
||||
result[i] = 't';
|
||||
else
|
||||
result[i] = result[i + 1];
|
||||
else
|
||||
result.Remove(i, 1);
|
||||
}
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public static Dictionary<string, string> KanaDictionary = new Dictionary<string, string>
|
||||
{
|
||||
//平假
|
||||
{ "あ", "a" }, { "い", "i" }, { "う", "u" }, { "え", "e" }, { "お", "o" },
|
||||
{ "か", "ka" }, { "き", "ki" }, { "く", "ku" }, { "け", "ke" }, { "こ", "ko" },
|
||||
{ "さ", "sa" }, { "し", "shi" }, { "す", "su" }, { "せ", "se" }, { "そ", "so" },
|
||||
{ "た", "ta" }, { "ち", "chi" }, { "つ", "tsu" }, { "て", "te" }, { "と", "to" },
|
||||
{ "な", "na" }, { "に", "ni" }, { "ぬ", "nu" }, { "ね", "ne" }, { "の", "no" },
|
||||
{ "は", "ha" }, { "ひ", "hi" }, { "ふ", "fu" }, { "へ", "he" }, { "ほ", "ho" },
|
||||
{ "ま", "ma" }, { "み", "mi" }, { "む", "mu" }, { "め", "me" }, { "も", "mo" },
|
||||
{ "や", "ya" }, { "ゆ", "yu" }, { "よ", "yo" },
|
||||
{ "ら", "ra" }, { "り", "ri" }, { "る", "ru" }, { "れ", "re" }, { "ろ", "ro" },
|
||||
{ "わ", "wa" }, { "を", "wo" },
|
||||
{ "が", "ga" }, { "ぎ", "gi" }, { "ぐ", "gu" }, { "げ", "ge" }, { "ご", "go" },
|
||||
{ "ざ", "za" }, { "じ", "ji" }, { "ず", "zu" }, { "ぜ", "ze" }, { "ぞ", "zo" },
|
||||
{ "だ", "da" }, { "ぢ", "ji" }, { "づ", "zu" }, { "で", "de" }, { "ど", "do" },
|
||||
{ "ば", "ba" }, { "び", "bi" }, { "ぶ", "bu" }, { "べ", "be" }, { "ぼ", "bo" },
|
||||
{ "ぱ", "pa" }, { "ぴ", "pi" }, { "ぷ", "pu" }, { "ぺ", "pe" }, { "ぽ", "po" },
|
||||
{ "ん", "n" },
|
||||
|
||||
//片假
|
||||
{ "ア", "a" }, { "イ", "i" }, { "ウ", "u" }, { "エ", "e" }, { "オ", "o" },
|
||||
{ "カ", "ka" }, { "キ", "ki" }, { "ク", "ku" }, { "ケ", "ke" }, { "コ", "ko" },
|
||||
{ "サ", "sa" }, { "シ", "shi" }, { "ス", "su" }, { "セ", "se" }, { "ソ", "so" },
|
||||
{ "タ", "ta" }, { "チ", "chi" }, { "ツ", "tsu" }, { "テ", "te" }, { "ト", "to" },
|
||||
{ "ナ", "na" }, { "ニ", "ni" }, { "ヌ", "nu" }, { "ネ", "ne" }, { "ノ", "no" },
|
||||
{ "ハ", "ha" }, { "ヒ", "hi" }, { "フ", "fu" }, { "ヘ", "he" }, { "ホ", "ho" },
|
||||
{ "マ", "ma" }, { "ミ", "mi" }, { "ム", "mu" }, { "メ", "me" }, { "モ", "mo" },
|
||||
{ "ヤ", "ya" }, { "ユ", "yu" }, { "ヨ", "yo" },
|
||||
{ "ラ", "ra" }, { "リ", "ri" }, { "ル", "ru" }, { "レ", "re" }, { "ロ", "ro" },
|
||||
{ "ワ", "wa" }, { "ヲ", "wo" },
|
||||
{ "ガ", "ga" }, { "ギ", "gi" }, { "グ", "gu" }, { "ゲ", "ge" }, { "ゴ", "go" },
|
||||
{ "ザ", "za" }, { "ジ", "ji" }, { "ズ", "zu" }, { "ゼ", "ze" }, { "ゾ", "zo" },
|
||||
{ "ダ", "da" }, { "ヂ", "ji" }, { "ヅ", "zu" }, { "デ", "de" }, { "ド", "do" },
|
||||
{ "バ", "ba" }, { "ビ", "bi" }, { "ブ", "bu" }, { "ベ", "be" }, { "ボ", "bo" },
|
||||
{ "パ", "pa" }, { "ピ", "pi" }, { "プ", "pu" }, { "ペ", "pe" }, { "ポ", "po" },
|
||||
{ "ン", "n" },
|
||||
|
||||
//小版本
|
||||
{ "ぁ", "a" }, { "ぃ", "i" }, { "ぅ", "u" }, { "ぇ", "e" }, { "ぉ", "o" },
|
||||
{ "ゃ", "ya" }, { "ゅ", "yu" }, { "ょ", "yo" }, { "ゎ", "wa" },
|
||||
{ "ァ", "a" }, { "ィ", "i" }, { "ゥ", "u" }, { "ェ", "e" }, { "ォ", "o" },
|
||||
{ "ャ", "ya" }, { "ュ", "yu" }, { "ョ", "yo" }, { "ヮ", "wa" },
|
||||
};
|
||||
|
||||
public static Dictionary<string, string> ExtendedKanaDictionary = new Dictionary<string, string>
|
||||
{
|
||||
//平假-拗音
|
||||
{ "きゃ", "kya" }, { "きゅ", "kyu" }, { "きょ", "kyo" },
|
||||
{ "しゃ", "sha" }, { "しゅ", "shu" }, { "しょ", "sho" },
|
||||
{ "ちゃ", "cha" }, { "ちゅ", "chu" }, { "ちょ", "cho" },
|
||||
{ "にゃ", "nya" }, { "にゅ", "nyu" }, { "にょ", "nyo" },
|
||||
{ "ひゃ", "hya" }, { "ひゅ", "hyu" }, { "ひょ", "hyo" },
|
||||
{ "みゃ", "mya" }, { "みゅ", "myu" }, { "みょ", "myo" },
|
||||
{ "りゃ", "rya" }, { "りゅ", "ryu" }, { "りょ", "ryo" },
|
||||
{ "ぎゃ", "gya" }, { "ぎゅ", "gyu" }, { "ぎょ", "gyo" },
|
||||
{ "じゃ", "ja" }, { "じゅ", "ju" }, { "じょ", "jo" },
|
||||
{ "ぢゃ", "ja" }, { "ぢゅ", "ju" }, { "ぢょ", "jo" },
|
||||
{ "びゃ", "bya" }, { "びゅ", "byu" }, { "びょ", "byo" },
|
||||
{ "ぴゃ", "pya" }, { "ぴゅ", "pyu" }, { "ぴょ", "pyo" },
|
||||
|
||||
//片假-拗音
|
||||
{ "キャ", "kya" }, { "キュ", "kyu" }, { "キョ", "kyo" },
|
||||
{ "シャ", "sha" }, { "シュ", "shu" }, { "ショ", "sho" },
|
||||
{ "チャ", "cha" }, { "チュ", "chu" }, { "チョ", "cho" },
|
||||
{ "ニャ", "nya" }, { "ニュ", "nyu" }, { "ニョ", "nyo" },
|
||||
{ "ヒャ", "hya" }, { "ヒュ", "hyu" }, { "ヒョ", "hyo" },
|
||||
{ "ミャ", "mya" }, { "ミュ", "myu" }, { "ミョ", "myo" },
|
||||
{ "リャ", "rya" }, { "リュ", "ryu" }, { "リョ", "ryo" },
|
||||
{ "ギャ", "gya" }, { "ギュ", "gyu" }, { "ギョ", "gyo" },
|
||||
{ "ジャ", "ja" }, { "ジュ", "ju" }, { "ジョ", "jo" },
|
||||
{ "ヂャ", "ja" }, { "ヂュ", "ju" }, { "ヂョ", "jo" },
|
||||
{ "ビャ", "bya" }, { "ビュ", "byu" }, { "ビョ", "byo" },
|
||||
{ "ピャ", "pya" }, { "ピュ", "pyu" }, { "ピョ", "pyo" },
|
||||
|
||||
//其他语言
|
||||
{ "イェ", "ye" },
|
||||
{ "ウィ", "wi" }, { "ウェ", "we" }, { "ウォ", "wo" },
|
||||
{ "ヴァ", "va" }, { "ヴィ", "vi" }, { "ヴ", "vu" }, { "ヴェ", "ve" }, { "ヴォ", "vo" },
|
||||
{ "ヴュ", "vyu" },
|
||||
{ "クァ", "kwa" }, { "クィ", "kwi" }, { "クェ", "kwe" }, { "クォ", "kwo" },
|
||||
{ "グァ", "gwa" },
|
||||
{ "シェ", "she" },
|
||||
{ "ジェ", "je" },
|
||||
{ "チェ", "che" },
|
||||
{ "ツァ", "tsa" }, { "ツィ", "tsi" }, { "ツェ", "tse" }, { "ツォ", "tso" },
|
||||
{ "ティ", "ti" }, { "トゥ", "tu" },
|
||||
{ "テュ", "tyu" },
|
||||
{ "ディ", "di" }, { "ドゥ", "du" },
|
||||
{ "デュ", "dyu" },
|
||||
{ "ファ", "fa" }, { "フィ", "fi" }, { "フェ", "fe" }, { "フォ", "fo" },
|
||||
{ "フュ", "fyu" },
|
||||
};
|
||||
}
|
||||
}
|
||||
41
RomajiConverter.Core/Helpers/LrcParser.cs
Normal file
41
RomajiConverter.Core/Helpers/LrcParser.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace RomajiConverter.Core.Helpers
|
||||
{
|
||||
public static class LrcParser
|
||||
{
|
||||
public static readonly Regex LrcLineRegex =
|
||||
new Regex("(\\[(\\d+:)?\\d+:\\d+(\\.\\d+)?\\])+\\s*(?<text>.*?(?=\\[(\\d+:)?\\d+:\\d+(\\.\\d+)?\\]|$|\\r|\\n))",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
public static readonly Regex LrcTimeRegex =
|
||||
new Regex("\\[((?<hour>\\d+):)?(?<minute>\\d+):(?<second>\\d+)(\\.(?<millisecond>\\d+))?\\]", RegexOptions.Compiled);
|
||||
|
||||
public static List<(TimeSpan Time, string Text)> Parse(string lrc)
|
||||
{
|
||||
var result = new List<(TimeSpan Time, string Text)>();
|
||||
|
||||
var lineMatches = LrcLineRegex.Matches(lrc);
|
||||
foreach (Match lineMatch in lineMatches)
|
||||
{
|
||||
var text = lineMatch.Groups["text"].Value;
|
||||
var timeMatches = LrcTimeRegex.Matches(lineMatch.Value);
|
||||
foreach (Match timeMatch in timeMatches)
|
||||
{
|
||||
var hour = timeMatch.Groups["hour"].Success ? int.Parse(timeMatch.Groups["hour"].Value) : 0;
|
||||
var minute = timeMatch.Groups["minute"].Success ? int.Parse(timeMatch.Groups["minute"].Value) : 0;
|
||||
var second = timeMatch.Groups["second"].Success ? int.Parse(timeMatch.Groups["second"].Value) : 0;
|
||||
var millisecond = timeMatch.Groups["millisecond"].Success
|
||||
? int.Parse(timeMatch.Groups["millisecond"].Value)
|
||||
: 0;
|
||||
var time = new TimeSpan(0, hour, minute, second, millisecond);
|
||||
result.Add((time, text));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user