mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-12 19:24:55 +08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b69493afd | ||
|
|
c524dc013c | ||
|
|
9ca5939e57 | ||
|
|
860abd4037 | ||
|
|
618415016f | ||
|
|
bfcba1425d | ||
|
|
0dc9ebf18e | ||
|
|
366d396b93 | ||
|
|
35ca28ac7b | ||
|
|
1505933107 | ||
|
|
958227d0f2 | ||
|
|
b1978fec09 |
5
.github/workflows/release-to-telegram.yml
vendored
5
.github/workflows/release-to-telegram.yml
vendored
@@ -12,6 +12,7 @@ jobs:
|
||||
env:
|
||||
TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||
CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||
THREAD_ID: ${{ secrets.TELEGRAM_THREAD_ID }}
|
||||
RELEASE_URL: ${{ github.event.release.html_url }}
|
||||
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
||||
RELEASE_NAME: ${{ github.event.release.name }}
|
||||
@@ -23,5 +24,5 @@ jobs:
|
||||
|
||||
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage" \
|
||||
-d chat_id="${CHAT_ID}" \
|
||||
-d text="${TEXT}" \
|
||||
-d parse_mode=Markdown
|
||||
-d message_thread_id="${THREAD_ID}" \
|
||||
-d text="${TEXT}"
|
||||
|
||||
@@ -1,149 +1,150 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '15.0'">
|
||||
<VisualStudioVersion>15.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x86">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x86">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<WapProjPath Condition="'$(WapProjPath)'==''">$(MSBuildExtensionsPath)\Microsoft\DesktopBridge\</WapProjPath>
|
||||
<PathToXAMLWinRTImplementations>BetterLyrics.WinUI3\</PathToXAMLWinRTImplementations>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.props" />
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>6576cd19-ef92-4099-b37d-e2d8ebdb6bf5</ProjectGuid>
|
||||
<TargetPlatformVersion>10.0.26100.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<AssetTargetFallback>net8.0-windows$(TargetPlatformVersion);$(AssetTargetFallback)</AssetTargetFallback>
|
||||
<DefaultLanguage>zh-CN</DefaultLanguage>
|
||||
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
|
||||
<EntryPointProjectUniqueName>..\BetterLyrics.WinUI3\BetterLyrics.WinUI3.csproj</EntryPointProjectUniqueName>
|
||||
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
||||
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
|
||||
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
|
||||
<GenerateTestArtifacts>True</GenerateTestArtifacts>
|
||||
<AppxBundlePlatforms>x86|x64</AppxBundlePlatforms>
|
||||
<GenerateTemporaryStoreCertificate>True</GenerateTemporaryStoreCertificate>
|
||||
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
|
||||
<PackageCertificateKeyFile>BetterLyrics.WinUI3 %28Package%29_TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="BetterLyrics.WinUI3 %28Package%29_TemporaryKey.pfx" />
|
||||
<Content Include="Images\LargeTile.scale-100.png" />
|
||||
<Content Include="Images\LargeTile.scale-125.png" />
|
||||
<Content Include="Images\LargeTile.scale-150.png" />
|
||||
<Content Include="Images\LargeTile.scale-200.png" />
|
||||
<Content Include="Images\LargeTile.scale-400.png" />
|
||||
<Content Include="Images\SmallTile.scale-100.png" />
|
||||
<Content Include="Images\SmallTile.scale-125.png" />
|
||||
<Content Include="Images\SmallTile.scale-150.png" />
|
||||
<Content Include="Images\SmallTile.scale-200.png" />
|
||||
<Content Include="Images\SmallTile.scale-400.png" />
|
||||
<Content Include="Images\SplashScreen.scale-100.png" />
|
||||
<Content Include="Images\SplashScreen.scale-125.png" />
|
||||
<Content Include="Images\SplashScreen.scale-150.png" />
|
||||
<Content Include="Images\SplashScreen.scale-200.png" />
|
||||
<Content Include="Images\LockScreenLogo.scale-200.png" />
|
||||
<Content Include="Images\SplashScreen.scale-400.png" />
|
||||
<Content Include="Images\Square150x150Logo.scale-100.png" />
|
||||
<Content Include="Images\Square150x150Logo.scale-125.png" />
|
||||
<Content Include="Images\Square150x150Logo.scale-150.png" />
|
||||
<Content Include="Images\Square150x150Logo.scale-200.png" />
|
||||
<Content Include="Images\Square150x150Logo.scale-400.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-lightunplated_targetsize-16.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-lightunplated_targetsize-24.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-lightunplated_targetsize-256.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-lightunplated_targetsize-32.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-lightunplated_targetsize-48.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-unplated_targetsize-16.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-unplated_targetsize-256.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-unplated_targetsize-32.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-unplated_targetsize-48.png" />
|
||||
<Content Include="Images\Square44x44Logo.scale-100.png" />
|
||||
<Content Include="Images\Square44x44Logo.scale-125.png" />
|
||||
<Content Include="Images\Square44x44Logo.scale-150.png" />
|
||||
<Content Include="Images\Square44x44Logo.scale-200.png" />
|
||||
<Content Include="Images\Square44x44Logo.scale-400.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-16.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-24.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-256.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-32.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-48.png" />
|
||||
<Content Include="Images\StoreLogo.scale-100.png" />
|
||||
<Content Include="Images\StoreLogo.scale-125.png" />
|
||||
<Content Include="Images\StoreLogo.scale-150.png" />
|
||||
<Content Include="Images\StoreLogo.scale-200.png" />
|
||||
<Content Include="Images\StoreLogo.scale-400.png" />
|
||||
<Content Include="Images\Wide310x150Logo.scale-100.png" />
|
||||
<Content Include="Images\Wide310x150Logo.scale-125.png" />
|
||||
<Content Include="Images\Wide310x150Logo.scale-150.png" />
|
||||
<Content Include="Images\Wide310x150Logo.scale-200.png" />
|
||||
<Content Include="Images\Wide310x150Logo.scale-400.png" />
|
||||
<None Include="Package.StoreAssociation.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BetterLyrics.WinUI3\BetterLyrics.WinUI3.csproj">
|
||||
<SkipGetTargetFrameworkProperties>True</SkipGetTargetFrameworkProperties>
|
||||
<PublishProfile>Properties\PublishProfiles\win-$(Platform).pubxml</PublishProfile>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4654" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250606001" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
|
||||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '15.0'">
|
||||
<VisualStudioVersion>15.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x86">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x86">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<WapProjPath Condition="'$(WapProjPath)'==''">$(MSBuildExtensionsPath)\Microsoft\DesktopBridge\</WapProjPath>
|
||||
<PathToXAMLWinRTImplementations>BetterLyrics.WinUI3\</PathToXAMLWinRTImplementations>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.props" />
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>6576cd19-ef92-4099-b37d-e2d8ebdb6bf5</ProjectGuid>
|
||||
<TargetPlatformVersion>10.0.26100.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<AssetTargetFallback>net8.0-windows$(TargetPlatformVersion);$(AssetTargetFallback)</AssetTargetFallback>
|
||||
<DefaultLanguage>zh-CN</DefaultLanguage>
|
||||
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
|
||||
<EntryPointProjectUniqueName>..\BetterLyrics.WinUI3\BetterLyrics.WinUI3.csproj</EntryPointProjectUniqueName>
|
||||
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
||||
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
|
||||
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
|
||||
<GenerateTestArtifacts>True</GenerateTestArtifacts>
|
||||
<AppxBundlePlatforms>x86|x64</AppxBundlePlatforms>
|
||||
<GenerateTemporaryStoreCertificate>True</GenerateTemporaryStoreCertificate>
|
||||
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
|
||||
<PackageCertificateKeyFile>BetterLyrics.WinUI3 %28Package%29_TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="BetterLyrics.WinUI3 %28Package%29_TemporaryKey.pfx" />
|
||||
<Content Include="Images\LargeTile.scale-100.png" />
|
||||
<Content Include="Images\LargeTile.scale-125.png" />
|
||||
<Content Include="Images\LargeTile.scale-150.png" />
|
||||
<Content Include="Images\LargeTile.scale-200.png" />
|
||||
<Content Include="Images\LargeTile.scale-400.png" />
|
||||
<Content Include="Images\SmallTile.scale-100.png" />
|
||||
<Content Include="Images\SmallTile.scale-125.png" />
|
||||
<Content Include="Images\SmallTile.scale-150.png" />
|
||||
<Content Include="Images\SmallTile.scale-200.png" />
|
||||
<Content Include="Images\SmallTile.scale-400.png" />
|
||||
<Content Include="Images\SplashScreen.scale-100.png" />
|
||||
<Content Include="Images\SplashScreen.scale-125.png" />
|
||||
<Content Include="Images\SplashScreen.scale-150.png" />
|
||||
<Content Include="Images\SplashScreen.scale-200.png" />
|
||||
<Content Include="Images\LockScreenLogo.scale-200.png" />
|
||||
<Content Include="Images\SplashScreen.scale-400.png" />
|
||||
<Content Include="Images\Square150x150Logo.scale-100.png" />
|
||||
<Content Include="Images\Square150x150Logo.scale-125.png" />
|
||||
<Content Include="Images\Square150x150Logo.scale-150.png" />
|
||||
<Content Include="Images\Square150x150Logo.scale-200.png" />
|
||||
<Content Include="Images\Square150x150Logo.scale-400.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-lightunplated_targetsize-16.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-lightunplated_targetsize-24.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-lightunplated_targetsize-256.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-lightunplated_targetsize-32.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-lightunplated_targetsize-48.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-unplated_targetsize-16.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-unplated_targetsize-256.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-unplated_targetsize-32.png" />
|
||||
<Content Include="Images\Square44x44Logo.altform-unplated_targetsize-48.png" />
|
||||
<Content Include="Images\Square44x44Logo.scale-100.png" />
|
||||
<Content Include="Images\Square44x44Logo.scale-125.png" />
|
||||
<Content Include="Images\Square44x44Logo.scale-150.png" />
|
||||
<Content Include="Images\Square44x44Logo.scale-200.png" />
|
||||
<Content Include="Images\Square44x44Logo.scale-400.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-16.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-24.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-256.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-32.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-48.png" />
|
||||
<Content Include="Images\StoreLogo.scale-100.png" />
|
||||
<Content Include="Images\StoreLogo.scale-125.png" />
|
||||
<Content Include="Images\StoreLogo.scale-150.png" />
|
||||
<Content Include="Images\StoreLogo.scale-200.png" />
|
||||
<Content Include="Images\StoreLogo.scale-400.png" />
|
||||
<Content Include="Images\Wide310x150Logo.scale-100.png" />
|
||||
<Content Include="Images\Wide310x150Logo.scale-125.png" />
|
||||
<Content Include="Images\Wide310x150Logo.scale-150.png" />
|
||||
<Content Include="Images\Wide310x150Logo.scale-200.png" />
|
||||
<Content Include="Images\Wide310x150Logo.scale-400.png" />
|
||||
<None Include="Package.StoreAssociation.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BetterLyrics.WinUI3\BetterLyrics.WinUI3.csproj">
|
||||
<EnableMsixTooling>true</EnableMsixTooling>
|
||||
<SkipGetTargetFrameworkProperties>True</SkipGetTargetFrameworkProperties>
|
||||
<PublishProfile>Properties\PublishProfiles\win-$(Platform).pubxml</PublishProfile>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4654" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250606001" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
|
||||
</Project>
|
||||
@@ -12,7 +12,7 @@
|
||||
<Identity
|
||||
Name="37412.BetterLyrics"
|
||||
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
|
||||
Version="1.0.39.0" />
|
||||
Version="1.0.40.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
|
||||
@@ -81,7 +81,10 @@
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
<Style x:Key="TitleBarToggleButtonStyle" TargetType="ToggleButton">
|
||||
<Style
|
||||
x:Key="TitleBarToggleButtonStyle"
|
||||
BasedOn="{StaticResource ToggleButtonRevealStyle}"
|
||||
TargetType="ToggleButton">
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
@@ -302,4 +305,5 @@
|
||||
<FontFamily x:Key="IconFontFamily">ms-appx:///Assets/Segoe Fluent Icons.ttf#Segoe Fluent Icons</FontFamily>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
|
||||
</Application>
|
||||
|
||||
@@ -107,6 +107,12 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
return t * t * (3f - 2f * t);
|
||||
}
|
||||
|
||||
public static float CubicBezier(float t, float p0, float p1, float p2, float p3)
|
||||
{
|
||||
float u = 1 - t;
|
||||
return u * u * u * p0 + 3 * u * u * t * p1 + 3 * u * t * t * p2 + t * t * t * p3;
|
||||
}
|
||||
|
||||
public static float Linear(float t) => t;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
if (!_isTransitioning) return;
|
||||
|
||||
_progress += (float)elapsedTime.TotalSeconds / _durationSeconds;
|
||||
_progress += (float)(elapsedTime.TotalSeconds / _durationSeconds);
|
||||
if (_progress >= 1f)
|
||||
{
|
||||
_progress = 1f;
|
||||
|
||||
@@ -86,6 +86,16 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExitApp()
|
||||
{
|
||||
LyricsWindow? lyricsWindow = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
if (lyricsWindow != null)
|
||||
{
|
||||
DockModeHelper.Disable(lyricsWindow);
|
||||
}
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private static void TrackWindow(object window)
|
||||
{
|
||||
if (!_activeWindows.Contains(window))
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.Graphics.Canvas.Geometry;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
using Windows.UI;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
@@ -16,9 +21,9 @@ namespace BetterLyrics.WinUI3.Models
|
||||
public ValueTransition<float> OpacityTransition { get; set; } = new(initialValue: 0f, durationSeconds: _animationDuration);
|
||||
public ValueTransition<float> ScaleTransition { get; set; } = new(initialValue: 0.95f, durationSeconds: _animationDuration);
|
||||
|
||||
public CanvasTextLayout? CanvasTextLayout { get; set; }
|
||||
public CanvasTextLayout? CanvasTextLayout { get; private set; }
|
||||
|
||||
public Vector2 CenterPosition { get; set; }
|
||||
public Vector2 CenterPosition { get; private set; }
|
||||
public Vector2 Position { get; set; }
|
||||
|
||||
public List<LyricsChar> LyricsChars { get; set; } = [];
|
||||
@@ -29,5 +34,68 @@ namespace BetterLyrics.WinUI3.Models
|
||||
|
||||
public string DisplayedText { get; set; } = "";
|
||||
public string OriginalText { get; set; } = "";
|
||||
|
||||
public CanvasGeometry? TextGeometry { get; private set; }
|
||||
|
||||
public CanvasCommandList? BackgroundFontEffect { get; private set; }
|
||||
public CanvasCommandList? ForegroundFontEffect { get; private set; }
|
||||
|
||||
public void UpdateCenterPosition(float maxWidth, TextAlignmentType type)
|
||||
{
|
||||
if (CanvasTextLayout == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
float centerY = Position.Y + (float)CanvasTextLayout.LayoutBounds.Height;
|
||||
CenterPosition = type switch
|
||||
{
|
||||
TextAlignmentType.Left => new Vector2(Position.X, centerY),
|
||||
TextAlignmentType.Center => new Vector2(Position.X + maxWidth / 2, centerY),
|
||||
TextAlignmentType.Right => new Vector2(Position.X + maxWidth, centerY),
|
||||
_ => throw new System.ArgumentOutOfRangeException(nameof(type), type, null),
|
||||
};
|
||||
}
|
||||
|
||||
public void UpdateTextLayout(ICanvasAnimatedControl control, CanvasTextFormat textFormat, float maxWidth, float maxHeight, TextAlignmentType type)
|
||||
{
|
||||
CanvasTextLayout?.Dispose();
|
||||
CanvasTextLayout = null;
|
||||
CanvasTextLayout = new CanvasTextLayout(control, DisplayedText, textFormat, maxWidth, maxHeight);
|
||||
CanvasTextLayout.HorizontalAlignment = type.ToCanvasHorizontalAlignment();
|
||||
}
|
||||
|
||||
public void UpdateTextGeometry()
|
||||
{
|
||||
TextGeometry?.Dispose();
|
||||
TextGeometry = null;
|
||||
if (CanvasTextLayout == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
TextGeometry = CanvasGeometry.CreateText(CanvasTextLayout);
|
||||
}
|
||||
|
||||
public void UpdateFontEffect(ICanvasAnimatedControl control, bool drawStroke, Color strokeColor, int strokeWidth, Color fontColor)
|
||||
{
|
||||
BackgroundFontEffect?.Dispose();
|
||||
BackgroundFontEffect = null;
|
||||
ForegroundFontEffect?.Dispose();
|
||||
ForegroundFontEffect = null;
|
||||
if (TextGeometry == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
BackgroundFontEffect = new CanvasCommandList(control);
|
||||
using var bgFontEffectDs = BackgroundFontEffect.CreateDrawingSession();
|
||||
ForegroundFontEffect = new CanvasCommandList(control);
|
||||
using var fgFontEffectDs = ForegroundFontEffect.CreateDrawingSession();
|
||||
if (drawStroke)
|
||||
{
|
||||
bgFontEffectDs.DrawGeometry(TextGeometry, Position, strokeColor, strokeWidth); // 描边
|
||||
fgFontEffectDs.DrawGeometry(TextGeometry, Position, strokeColor, strokeWidth); // 描边
|
||||
}
|
||||
bgFontEffectDs.FillGeometry(TextGeometry, Position, fontColor); // 填充
|
||||
fgFontEffectDs.FillGeometry(TextGeometry, Position, fontColor); // 填充
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ using EvtSource;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -292,15 +294,15 @@ namespace BetterLyrics.WinUI3.Services
|
||||
var decoder = await BitmapDecoder.CreateAsync(stream);
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var _albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Premultiplied);
|
||||
var albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Premultiplied);
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var _albumArtLightAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, false).FirstOrDefault();
|
||||
var _albumArtDarkAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, true).FirstOrDefault();
|
||||
var albumArtLightAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, false).FirstOrDefault();
|
||||
var albumArtDarkAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, true).FirstOrDefault();
|
||||
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
AlbumArtChangedChanged?.Invoke(this, new AlbumArtChangedEventArgs(_albumArtSwBitmap, _albumArtLightAccentColor, _albumArtDarkAccentColor));
|
||||
AlbumArtChangedChanged?.Invoke(this, new AlbumArtChangedEventArgs(albumArtSwBitmap, albumArtLightAccentColor, albumArtDarkAccentColor));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
SetDefault(CoverImageRadiusKey, 12); // 12 %
|
||||
SetDefault(CoverAcrylicEffectAmountKey, 0);
|
||||
// Lyrics
|
||||
SetDefault(LyricsAlignmentTypeKey, (int)TextAlignmentType.Center);
|
||||
SetDefault(LyricsAlignmentTypeKey, (int)TextAlignmentType.Left);
|
||||
SetDefault(SongInfoAlignmentTypeKey, (int)TextAlignmentType.Left);
|
||||
SetDefault(LyricsFontWeightKey, (int)LyricsFontWeight.Bold);
|
||||
SetDefault(LyricsBlurAmountKey, 5);
|
||||
@@ -210,8 +210,8 @@ namespace BetterLyrics.WinUI3.Services
|
||||
SetDefault(LyricsCustomFgFontColorKey, Colors.White.ToInt());
|
||||
SetDefault(LyricsCustomStrokeFontColorKey, Colors.White.ToInt());
|
||||
|
||||
SetDefault(LyricsStandardFontSizeKey, 28);
|
||||
SetDefault(LyricsDockFontSizeKey, 20);
|
||||
SetDefault(LyricsStandardFontSizeKey, 32);
|
||||
SetDefault(LyricsDockFontSizeKey, 16);
|
||||
SetDefault(LyricsDesktopFontSizeKey, 28);
|
||||
|
||||
SetDefault(LyricsLineSpacingFactorKey, 0.5f);
|
||||
@@ -233,7 +233,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
SetDefault(IgnoreFullscreenWindowKey, false);
|
||||
SetDefault(PreferredDisplayTypeKey, (int)LyricsDisplayType.SplitView);
|
||||
|
||||
SetDefault(LyricsScrollEasingTypeKey, (int)EasingType.EaseInOutQuad);
|
||||
SetDefault(LyricsScrollEasingTypeKey, (int)EasingType.EaseInOutSine);
|
||||
SetDefault(LyricsScrollDurationKey, 500); // 500ms
|
||||
SetDefault(TimelineSyncThresholdKey, 0); // 0ms
|
||||
|
||||
|
||||
@@ -916,4 +916,7 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SystemTrayResetWindowPosition.Text" xml:space="preserve">
|
||||
<value>Reset window position</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsAlignment.Description" xml:space="preserve">
|
||||
<value>This setting will not affect the dock mode and the dock mode will always remain centered.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -916,4 +916,7 @@
|
||||
<data name="SystemTrayResetWindowPosition.Text" xml:space="preserve">
|
||||
<value>ウィンドウの位置をリセットします</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsAlignment.Description" xml:space="preserve">
|
||||
<value>この設定はドックモードには影響しません。ドックモードは常に中心のままです。</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -916,4 +916,7 @@
|
||||
<data name="SystemTrayResetWindowPosition.Text" xml:space="preserve">
|
||||
<value>창 위치를 재설정합니다</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsAlignment.Description" xml:space="preserve">
|
||||
<value>이 설정은 도크 모드에 영향을 미치지 않으며 도크 모드는 항상 중앙에 유지됩니다.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -916,4 +916,7 @@
|
||||
<data name="SystemTrayResetWindowPosition.Text" xml:space="preserve">
|
||||
<value>重置窗口位置</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsAlignment.Description" xml:space="preserve">
|
||||
<value>此设置不会影响停靠模式,停靠模式将始终保持居中。</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -916,4 +916,7 @@
|
||||
<data name="SystemTrayResetWindowPosition.Text" xml:space="preserve">
|
||||
<value>重置窗口位置</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsAlignment.Description" xml:space="preserve">
|
||||
<value>此設定不會影響停靠模式,停靠模式將始終保持居中。</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -49,7 +49,12 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_lyricsBgTheme = _settingsService.LyricsBackgroundTheme;
|
||||
|
||||
_isFanLyricsEnabled = _settingsService.IsFanLyricsEnabled;
|
||||
|
||||
// 歌词描边
|
||||
_lyricsFontStrokeWidth = _settingsService.LyricsFontStrokeWidth;
|
||||
_lyricsStrokeFontColorType = _settingsService.LyricsStrokeFontColorType;
|
||||
_customStrokeFontColor = _settingsService.LyricsCustomStrokeFontColor;
|
||||
|
||||
_isTranslationEnabled = _settingsService.IsTranslationEnabled;
|
||||
_showTranslationOnly = _settingsService.ShowTranslationOnly;
|
||||
_isLibreTranslateEnabled = _settingsService.IsLibreTranslateEnabled;
|
||||
|
||||
@@ -35,15 +35,15 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
if (_isDockMode)
|
||||
{
|
||||
FillBackground(control, combinedDs, _immersiveBgTransition.Value, 0f, _immersiveBgOpacityTransition.Value);
|
||||
FillBackgroundColor(control, combinedDs, _immersiveBgColorTransition.Value, 0f, _immersiveBgOpacityTransition.Value);
|
||||
}
|
||||
else if (_isDesktopMode)
|
||||
{
|
||||
FillBackground(control, combinedDs, _immersiveBgTransition.Value, 0f, _immersiveBgOpacityTransition.Value);
|
||||
FillBackgroundColor(control, combinedDs, _immersiveBgColorTransition.Value, 0f, _immersiveBgOpacityTransition.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
FillBackground(control, combinedDs, _albumArtAccentColorTransition.Value, 0f, _albumArtBgOpacity / 100f);
|
||||
FillBackgroundColor(control, combinedDs, _albumArtAccentColorTransition.Value, 0f, _albumArtBgOpacity / 100f);
|
||||
DrawAlbumArtBackground(control, combinedDs);
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
if (_isDebugOverlayEnabled)
|
||||
{
|
||||
_drawFrameCount++;
|
||||
|
||||
var currentPlayingLine = _lyricsDataArr
|
||||
.ElementAtOrDefault(_langIndex)
|
||||
?.LyricsLines.ElementAtOrDefault(_playingLineIndex);
|
||||
@@ -71,32 +73,33 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
ds.DrawText(
|
||||
$"[DEBUG]\n" +
|
||||
$"Cur playing {_playingLineIndex}, char start idx {charStartIndex}, length {charLength}, prog {charProgress}\n" +
|
||||
$"Visible lines [{_startVisibleLineIndex}, {_endVisibleLineIndex}]\n" +
|
||||
$"Cur time {TotalTime + _positionOffset}\n" +
|
||||
$"Lang size {_lyricsDataArr.Count}\n" +
|
||||
$"Song duration {TimeSpan.FromMilliseconds(SongInfo?.DurationMs ?? 0)}",
|
||||
new Vector2(10, 10),
|
||||
ThemeTypeSent == Microsoft.UI.Xaml.ElementTheme.Light ? Colors.Black : Colors.White
|
||||
$"Canvas size: {_canvasWidth}x{_canvasHeight}\n" +
|
||||
$"FPS (Draw): {_displayedDrawFrameCount}\n" +
|
||||
$"Playing line: {_playingLineIndex}\n" +
|
||||
$"Syllable start idx: {charStartIndex}\n" +
|
||||
$"Syllable len: {charLength}\n" +
|
||||
$"Syllable prog: {charProgress}\n" +
|
||||
$"Visible lines: [{_startVisibleLineIndex}, {_endVisibleLineIndex}]\n" +
|
||||
$"Total line count: {GetMaxLyricsLineIndexBoundaries().Item2 + 1}\n" +
|
||||
$"Cur time: {TotalTime + _positionOffset}\n" +
|
||||
$"Lang size: {_lyricsDataArr.Count}\n" +
|
||||
$"Song duration: {TimeSpan.FromMilliseconds(SongInfo?.DurationMs ?? 0)}",
|
||||
new Vector2(10, 40),
|
||||
ThemeTypeSent == Microsoft.UI.Xaml.ElementTheme.Light ? Colors.Black : Colors.White,
|
||||
_debugTextFormat
|
||||
);
|
||||
}
|
||||
|
||||
//for (int i = _startVisibleLineIndex; i <= _endVisibleLineIndex; i++)
|
||||
//{
|
||||
// LyricsLine? line = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(i);
|
||||
// if (line != null)
|
||||
// {
|
||||
// ds.DrawText(
|
||||
// $"[{i}] {line.OriginalText} {line.HighlightOpacityTransition.Value}",
|
||||
// new Vector2(10, 30 + (i - _startVisibleLineIndex) * 20),
|
||||
// ThemeTypeSent == ElementTheme.Light ? Colors.Black : Colors.White
|
||||
// );
|
||||
// }
|
||||
//}
|
||||
if (_drawFrameStopwatch?.Elapsed.TotalSeconds >= 1.0)
|
||||
{
|
||||
_displayedDrawFrameCount = _drawFrameCount;
|
||||
_drawFrameStopwatch?.Restart();
|
||||
_drawFrameCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBackgroundImgae(ICanvasAnimatedControl control, CanvasDrawingSession ds, CanvasBitmap canvasBitmap, float opacity)
|
||||
private void DrawBackgroundImgae(OpacityEffect effect, CanvasDrawingSession ds, CanvasBitmap canvasBitmap)
|
||||
{
|
||||
float imageWidth = (float)canvasBitmap.Size.Width;
|
||||
float imageHeight = (float)canvasBitmap.Size.Height;
|
||||
@@ -107,128 +110,38 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
float x = _canvasWidth / 2 - imageWidth * scaleFactor / 2;
|
||||
float y = _canvasHeight / 2 - imageHeight * scaleFactor / 2;
|
||||
|
||||
// Original source: https://zhuanlan.zhihu.com/p/37178216
|
||||
float gain = _lyricsBgBrightnessTransition.Value;
|
||||
|
||||
float whiteX = 1 - 0.5f * gain;
|
||||
float whiteY = 0.5f + 0.5f * gain;
|
||||
float blackX = 0.5f - 0.5f * gain;
|
||||
float blackY = 0 + 0.5f * gain;
|
||||
|
||||
ds.DrawImage(new OpacityEffect
|
||||
{
|
||||
Source = new BrightnessEffect
|
||||
{
|
||||
Source = new ScaleEffect
|
||||
{
|
||||
Scale = new Vector2(scaleFactor),
|
||||
Source = canvasBitmap,
|
||||
},
|
||||
WhitePoint = new Vector2(whiteX, whiteY),
|
||||
BlackPoint = new Vector2(blackX, blackY),
|
||||
},
|
||||
Opacity = opacity,
|
||||
}, new Vector2(x, y));
|
||||
ds.DrawImage(effect, new Vector2(x, y));
|
||||
}
|
||||
|
||||
private void DrawForegroundImgae(ICanvasAnimatedControl control, CanvasDrawingSession ds, CanvasBitmap canvasBitmap, float opacity)
|
||||
private void DrawForegroundImgae(OpacityEffect effect, CanvasDrawingSession ds)
|
||||
{
|
||||
if (opacity == 0) return;
|
||||
|
||||
float imageWidth = (float)canvasBitmap.Size.Width;
|
||||
float imageHeight = (float)canvasBitmap.Size.Height;
|
||||
|
||||
float scaleFactor = _albumArtSize / Math.Min(imageWidth, imageHeight);
|
||||
if (scaleFactor < 0.01f) return;
|
||||
|
||||
float cornerRadius = _albumArtCornerRadius / 100f * _albumArtSize / 2;
|
||||
|
||||
using var cornerRadiusMask = new CanvasCommandList(control.Device);
|
||||
using var cornerRadiusMaskDs = cornerRadiusMask.CreateDrawingSession();
|
||||
cornerRadiusMaskDs.FillRoundedRectangle(
|
||||
new Rect(0, 0, imageWidth * scaleFactor, imageHeight * scaleFactor),
|
||||
cornerRadius, cornerRadius, Colors.White
|
||||
);
|
||||
|
||||
ds.DrawImage(new OpacityEffect
|
||||
{
|
||||
Source = new AlphaMaskEffect
|
||||
{
|
||||
Source = new ScaleEffect
|
||||
{
|
||||
Scale = new Vector2(scaleFactor),
|
||||
Source = canvasBitmap,
|
||||
},
|
||||
AlphaMask = cornerRadiusMask,
|
||||
},
|
||||
Opacity = opacity,
|
||||
}, new Vector2(_albumArtXTransition.Value, _albumArtYTransition.Value));
|
||||
ds.DrawImage(effect, new Vector2(_albumArtXTransition.Value, _albumArtYTransition.Value));
|
||||
}
|
||||
|
||||
private void DrawAlbumArtBackground(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
||||
{
|
||||
//ds.Transform = Matrix3x2.CreateRotation(_rotateAngle, control.Size.ToVector2() * 0.5f);
|
||||
|
||||
using var overlappedCovers = new CanvasCommandList(control.Device);
|
||||
using var overlappedCoversDs = overlappedCovers.CreateDrawingSession();
|
||||
overlappedCoversDs.Transform = Matrix3x2.CreateRotation(_rotateAngle, control.Size.ToVector2() * 0.5f);
|
||||
|
||||
if (_lastAlbumArtCanvasBitmap != null)
|
||||
if (_albumArtBgEffect == null)
|
||||
{
|
||||
DrawBackgroundImgae(control, overlappedCoversDs, _lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
||||
}
|
||||
if (_albumArtCanvasBitmap != null)
|
||||
{
|
||||
DrawBackgroundImgae(control, overlappedCoversDs, _albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
||||
return;
|
||||
}
|
||||
|
||||
overlappedCoversDs.Transform = Matrix3x2.Identity;
|
||||
|
||||
IGraphicsEffectSource blurredCover = new GaussianBlurEffect
|
||||
{
|
||||
BlurAmount = _albumArtBgBlurAmount,
|
||||
Source = overlappedCovers,
|
||||
BorderMode = EffectBorderMode.Soft,
|
||||
Optimization = EffectOptimization.Speed,
|
||||
};
|
||||
|
||||
// 应用亚克力噪点效果
|
||||
// TODO: 没有写_coverAcrylicNoiseCanvasBitmap加载的代码
|
||||
if (_coverAcrylicEffectAmount > 0 && _coverAcrylicNoiseCanvasBitmap != null)
|
||||
{
|
||||
blurredCover = new BlendEffect
|
||||
{
|
||||
Mode = BlendEffectMode.SoftLight,
|
||||
Background = blurredCover,
|
||||
Foreground = new OpacityEffect
|
||||
{
|
||||
Source = _coverAcrylicNoiseCanvasBitmap,
|
||||
Opacity = _coverAcrylicEffectAmount / 100f,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
var coverOverlayEffect = new OpacityEffect
|
||||
{
|
||||
Opacity = _albumArtBgOpacity / 100f,
|
||||
Source = blurredCover,
|
||||
};
|
||||
ds.DrawImage(coverOverlayEffect);
|
||||
|
||||
//ds.Transform = Matrix3x2.Identity;
|
||||
ds.Transform = Matrix3x2.CreateRotation(_rotateAngle, control.Size.ToVector2() * 0.5f);
|
||||
ds.DrawImage(_albumArtBgEffect);
|
||||
ds.Transform = Matrix3x2.Identity;
|
||||
}
|
||||
|
||||
private void DrawAlbumArt(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
||||
{
|
||||
using var albumArt = new CanvasCommandList(control.Device);
|
||||
using var albumArtDs = albumArt.CreateDrawingSession();
|
||||
if (_albumArtCanvasBitmap != null)
|
||||
|
||||
if (_lastFgImageEffect != null && !_lastFgImageEffect.IsDisposed() && _lastAlbumArtCanvasBitmap != null)
|
||||
{
|
||||
DrawForegroundImgae(control, albumArtDs, _albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
||||
DrawForegroundImgae(_lastFgImageEffect, albumArtDs);
|
||||
}
|
||||
if (_lastAlbumArtCanvasBitmap != null)
|
||||
if (_fgImageEffect != null && !_fgImageEffect.IsDisposed() && _albumArtCanvasBitmap != null)
|
||||
{
|
||||
DrawForegroundImgae(control, albumArtDs, _lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
||||
DrawForegroundImgae(_fgImageEffect, albumArtDs);
|
||||
}
|
||||
|
||||
using var opacity = new CanvasCommandList(control.Device);
|
||||
@@ -268,6 +181,11 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
LyricsLayoutOrientation.Vertical => _canvasWidth - _leftMargin - _albumArtSize - _rightMargin,
|
||||
_ => 0f
|
||||
};
|
||||
if (maxWidth <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using CanvasTextLayout titleLayout = new(
|
||||
control, title ?? string.Empty,
|
||||
_titleTextFormat, maxWidth, _canvasHeight
|
||||
@@ -305,60 +223,20 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
var textLayout = line.CanvasTextLayout;
|
||||
if (textLayout == null) continue;
|
||||
|
||||
var position = new Vector2(line.Position.X, line.Position.Y);
|
||||
|
||||
float layoutWidth = (float)textLayout.LayoutBounds.Width;
|
||||
float layoutHeight = (float)textLayout.LayoutBounds.Height;
|
||||
|
||||
if (layoutWidth <= 0 || layoutHeight <= 0) continue;
|
||||
|
||||
float centerX = position.X;
|
||||
float centerY = position.Y + layoutHeight / 2;
|
||||
|
||||
switch (_lyricsAlignmentType)
|
||||
{
|
||||
case TextAlignmentType.Left:
|
||||
textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Left;
|
||||
break;
|
||||
case TextAlignmentType.Center:
|
||||
textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Center;
|
||||
centerX += _maxLyricsWidth / 2;
|
||||
break;
|
||||
case TextAlignmentType.Right:
|
||||
textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Right;
|
||||
centerX += _maxLyricsWidth;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
float xOffset = _lyricsXTransition.Value;
|
||||
float yOffset = _canvasYScrollTransition.Value + _canvasHeight / 2 + _lyricsYTransition.Value;
|
||||
|
||||
// 组合变换:缩放 -> 旋转 -> 平移
|
||||
ds.Transform =
|
||||
Matrix3x2.CreateScale(line.ScaleTransition.Value, new Vector2(centerX, centerY))
|
||||
Matrix3x2.CreateScale(line.ScaleTransition.Value, line.CenterPosition)
|
||||
* Matrix3x2.CreateRotation(line.AngleTransition.Value, currentPlayingLine.Position)
|
||||
* Matrix3x2.CreateTranslation(xOffset, yOffset);
|
||||
* Matrix3x2.CreateTranslation(_lyricsXTransition.Value, yOffset);
|
||||
|
||||
// Create the background lyrics line with stroke and fill
|
||||
using var bgLyrics = new CanvasCommandList(control.Device);
|
||||
using var bgLyricsDs = bgLyrics.CreateDrawingSession();
|
||||
|
||||
// Create the foreground lyrics line with stroke and fill
|
||||
using var fgLyrics = new CanvasCommandList(control.Device);
|
||||
using var fgLyricsDs = fgLyrics.CreateDrawingSession();
|
||||
|
||||
// 创建文字几何体
|
||||
using var textGeometry = CanvasGeometry.CreateText(textLayout);
|
||||
if (_isDesktopMode)
|
||||
{
|
||||
bgLyricsDs.DrawGeometry(textGeometry, position, _strokeFontColor, _lyricsFontStrokeWidth); // 背景描边
|
||||
fgLyricsDs.DrawGeometry(textGeometry, position, _strokeFontColor, _lyricsFontStrokeWidth); // 前景描边
|
||||
}
|
||||
|
||||
bgLyricsDs.FillGeometry(textGeometry, position, _bgFontColor); // 背景填充
|
||||
fgLyricsDs.FillGeometry(textGeometry, position, _fgFontColor); // 前景填充
|
||||
if (line.BackgroundFontEffect == null || line.ForegroundFontEffect == null) continue;
|
||||
|
||||
using var combined = new CanvasCommandList(control.Device);
|
||||
using var combinedDs = combined.CreateDrawingSession();
|
||||
@@ -367,12 +245,16 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
// 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层(背景歌词层次)
|
||||
// Current line will not be blurred
|
||||
combinedDs.DrawImage(
|
||||
new GaussianBlurEffect
|
||||
new OpacityEffect
|
||||
{
|
||||
Source = new OpacityEffect { Source = bgLyrics, Opacity = line.OpacityTransition.Value * _lyricsOpacityTransition.Value },
|
||||
BlurAmount = line.BlurAmountTransition.Value,
|
||||
BorderMode = EffectBorderMode.Soft,
|
||||
Optimization = EffectOptimization.Speed,
|
||||
Source = new GaussianBlurEffect
|
||||
{
|
||||
Source = line.BackgroundFontEffect,
|
||||
BlurAmount = line.BlurAmountTransition.Value,
|
||||
BorderMode = EffectBorderMode.Soft,
|
||||
Optimization = EffectOptimization.Speed,
|
||||
},
|
||||
Opacity = line.OpacityTransition.Value * _lyricsOpacityTransition.Value,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -405,7 +287,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
var region = regions[j];
|
||||
var rect = new Rect(
|
||||
region.LayoutBounds.X,
|
||||
region.LayoutBounds.Y + position.Y,
|
||||
region.LayoutBounds.Y + line.Position.Y,
|
||||
region.LayoutBounds.Width,
|
||||
region.LayoutBounds.Height
|
||||
);
|
||||
@@ -422,20 +304,20 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
// Rects
|
||||
var highlightRect = new Rect(
|
||||
highlightRegion.LayoutBounds.X,
|
||||
highlightRegion.LayoutBounds.Y + position.Y,
|
||||
highlightRegion.LayoutBounds.Y + line.Position.Y,
|
||||
highlightWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
|
||||
var fadeInRect = new Rect(
|
||||
highlightRect.Right - fadingWidth,
|
||||
highlightRegion.LayoutBounds.Y + position.Y,
|
||||
highlightRegion.LayoutBounds.Y + line.Position.Y,
|
||||
fadingWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
var fadeOutRect = new Rect(
|
||||
highlightRect.Right,
|
||||
highlightRegion.LayoutBounds.Y + position.Y,
|
||||
highlightRegion.LayoutBounds.Y + line.Position.Y,
|
||||
fadingWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
@@ -463,7 +345,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
else
|
||||
{
|
||||
float height = 0f;
|
||||
//var regions = textLayout.GetCharacterRegions(0, string.Join("", line.LyricsChars.Select(x => x.Text)).Length);
|
||||
var regions = textLayout.GetCharacterRegions(0, line.OriginalText.Length);
|
||||
if (regions.Length > 0)
|
||||
{
|
||||
@@ -473,7 +354,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
maskDs.FillRectangle(
|
||||
new Rect(
|
||||
textLayout.LayoutBounds.X,
|
||||
position.Y,
|
||||
line.Position.Y,
|
||||
textLayout.LayoutBounds.Width,
|
||||
height
|
||||
),
|
||||
@@ -490,12 +371,12 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
Source = new AlphaMaskEffect
|
||||
{
|
||||
Source = fgLyrics,
|
||||
Source = line.ForegroundFontEffect,
|
||||
AlphaMask = _lyricsGlowEffectScope switch
|
||||
{
|
||||
LineRenderingType.CurrentChar => highlightMask,
|
||||
LineRenderingType.LineStartToCurrentChar => mask,
|
||||
LineRenderingType.CurrentLine => fgLyrics,
|
||||
LineRenderingType.CurrentLine => line.ForegroundFontEffect,
|
||||
_ => mask,
|
||||
},
|
||||
},
|
||||
@@ -505,12 +386,12 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
: new CanvasCommandList(control.Device),
|
||||
Foreground = new AlphaMaskEffect
|
||||
{
|
||||
Source = fgLyrics,
|
||||
Source = line.ForegroundFontEffect,
|
||||
AlphaMask = _lyricsHighlightScope switch
|
||||
{
|
||||
LineRenderingType.CurrentChar => highlightMask,
|
||||
LineRenderingType.LineStartToCurrentChar => mask,
|
||||
LineRenderingType.CurrentLine => fgLyrics,
|
||||
LineRenderingType.CurrentLine => line.ForegroundFontEffect,
|
||||
_ => mask,
|
||||
},
|
||||
},
|
||||
@@ -553,21 +434,14 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private void FillBackground(ICanvasAnimatedControl control, CanvasDrawingSession ds, Color color, float radius, float opacity)
|
||||
private void FillBackgroundColor(ICanvasAnimatedControl control, CanvasDrawingSession ds, Color color, float radius, float opacity)
|
||||
{
|
||||
CanvasCommandList list = new(control.Device);
|
||||
using var listDs = list.CreateDrawingSession();
|
||||
listDs.FillRoundedRectangle(
|
||||
ds.FillRoundedRectangle(
|
||||
new Rect(0, 0, _canvasWidth, _canvasHeight),
|
||||
radius,
|
||||
radius,
|
||||
color
|
||||
color.WithAlpha((byte)(opacity * 255))
|
||||
);
|
||||
ds.DrawImage(new OpacityEffect
|
||||
{
|
||||
Source = list,
|
||||
Opacity = opacity
|
||||
});
|
||||
}
|
||||
|
||||
private CanvasLinearGradientBrush GetHorizontalFillBrush(
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.Graphics.Canvas.Effects;
|
||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||
using Microsoft.UI;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
public partial class LyricsRendererViewModel
|
||||
{
|
||||
private OpacityEffect? _lastBgImageEffect;
|
||||
private OpacityEffect? _bgImageEffect;
|
||||
|
||||
private OpacityEffect? _lastFgImageEffect;
|
||||
private OpacityEffect? _fgImageEffect;
|
||||
|
||||
private CanvasCommandList? _albumArtBgEffect;
|
||||
|
||||
private OpacityEffect CreateBgImageEffect(CanvasBitmap canvasBitmap, float opacity)
|
||||
{
|
||||
float imageWidth = (float)canvasBitmap.Size.Width;
|
||||
float imageHeight = (float)canvasBitmap.Size.Height;
|
||||
|
||||
float targetSize = MathF.Sqrt(MathF.Pow(_canvasWidth, 2) + MathF.Pow(_canvasHeight, 2));
|
||||
float scaleFactor = targetSize / MathF.Min(imageWidth, imageHeight);
|
||||
|
||||
// Original source: https://zhuanlan.zhihu.com/p/37178216
|
||||
float gain = _lyricsBgBrightnessTransition.Value;
|
||||
|
||||
float whiteX = 1 - 0.5f * gain;
|
||||
float whiteY = 0.5f + 0.5f * gain;
|
||||
float blackX = 0.5f - 0.5f * gain;
|
||||
float blackY = 0 + 0.5f * gain;
|
||||
|
||||
return new OpacityEffect
|
||||
{
|
||||
Source = new BrightnessEffect
|
||||
{
|
||||
Source = new ScaleEffect
|
||||
{
|
||||
Scale = new Vector2(scaleFactor),
|
||||
Source = canvasBitmap,
|
||||
},
|
||||
WhitePoint = new Vector2(whiteX, whiteY),
|
||||
BlackPoint = new Vector2(blackX, blackY),
|
||||
},
|
||||
Opacity = opacity,
|
||||
};
|
||||
}
|
||||
|
||||
private OpacityEffect? CreateFgImageEffect(ICanvasAnimatedControl control, CanvasBitmap canvasBitmap, float opacity)
|
||||
{
|
||||
// TODO 最大化/还原时图片大小未跟随改变
|
||||
if (opacity == 0) return null;
|
||||
|
||||
float imageWidth = (float)canvasBitmap.Size.Width;
|
||||
float imageHeight = (float)canvasBitmap.Size.Height;
|
||||
|
||||
float scaleFactor = _albumArtSize / Math.Min(imageWidth, imageHeight);
|
||||
if (scaleFactor < 0.01f) return null;
|
||||
|
||||
float cornerRadius = _albumArtCornerRadius / 100f * _albumArtSize / 2;
|
||||
|
||||
var cornerRadiusMask = new CanvasCommandList(control);
|
||||
using var cornerRadiusMaskDs = cornerRadiusMask.CreateDrawingSession();
|
||||
cornerRadiusMaskDs.FillRoundedRectangle(
|
||||
new Rect(0, 0, imageWidth * scaleFactor, imageHeight * scaleFactor),
|
||||
cornerRadius, cornerRadius, Colors.White
|
||||
);
|
||||
|
||||
return new OpacityEffect
|
||||
{
|
||||
Source = new AlphaMaskEffect
|
||||
{
|
||||
Source = new ScaleEffect
|
||||
{
|
||||
Scale = new Vector2(scaleFactor),
|
||||
Source = canvasBitmap,
|
||||
},
|
||||
AlphaMask = cornerRadiusMask,
|
||||
},
|
||||
Opacity = opacity,
|
||||
};
|
||||
}
|
||||
|
||||
private void UpdateAlbumArtBgEffect(ICanvasAnimatedControl control)
|
||||
{
|
||||
_albumArtBgEffect?.Dispose();
|
||||
_albumArtBgEffect = null;
|
||||
|
||||
using var overlappedCovers = new CanvasCommandList(control);
|
||||
using var overlappedCoversDs = overlappedCovers.CreateDrawingSession();
|
||||
|
||||
if (_lastBgImageEffect != null && !_lastBgImageEffect.IsDisposed() && _lastAlbumArtCanvasBitmap != null)
|
||||
{
|
||||
DrawBackgroundImgae(_lastBgImageEffect, overlappedCoversDs, _lastAlbumArtCanvasBitmap);
|
||||
}
|
||||
if (_bgImageEffect != null && !_bgImageEffect.IsDisposed() && _albumArtCanvasBitmap != null)
|
||||
{
|
||||
DrawBackgroundImgae(_bgImageEffect, overlappedCoversDs, _albumArtCanvasBitmap);
|
||||
}
|
||||
|
||||
using var blurredCover = new GaussianBlurEffect
|
||||
{
|
||||
BlurAmount = _albumArtBgBlurAmount,
|
||||
Source = overlappedCovers,
|
||||
BorderMode = EffectBorderMode.Soft,
|
||||
Optimization = EffectOptimization.Speed,
|
||||
};
|
||||
|
||||
using var combined = new CanvasCommandList(control);
|
||||
using var combinedDs = combined.CreateDrawingSession();
|
||||
|
||||
if (_coverAcrylicEffectAmount > 0 && _coverAcrylicNoiseCanvasBitmap != null)
|
||||
{
|
||||
// 应用亚克力噪点效果
|
||||
combinedDs.DrawImage(new BlendEffect
|
||||
{
|
||||
Mode = BlendEffectMode.SoftLight,
|
||||
Background = blurredCover,
|
||||
Foreground = new OpacityEffect
|
||||
{
|
||||
Source = _coverAcrylicNoiseCanvasBitmap,
|
||||
Opacity = _coverAcrylicEffectAmount / 100f,
|
||||
},
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
combinedDs.DrawImage(blurredCover);
|
||||
}
|
||||
|
||||
_albumArtBgEffect = new CanvasCommandList(control);
|
||||
using var albumArtBgDs = _albumArtBgEffect.CreateDrawingSession();
|
||||
albumArtBgDs.DrawImage(new OpacityEffect
|
||||
{
|
||||
Opacity = _albumArtBgOpacity / 100f,
|
||||
Source = combined,
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateLastBgImageEffect()
|
||||
{
|
||||
_lastBgImageEffect?.Dispose();
|
||||
_lastBgImageEffect = null;
|
||||
if (_lastAlbumArtCanvasBitmap != null)
|
||||
{
|
||||
_lastBgImageEffect = CreateBgImageEffect(_lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateBgImageEffect()
|
||||
{
|
||||
_bgImageEffect?.Dispose();
|
||||
_bgImageEffect = null;
|
||||
if (_albumArtCanvasBitmap != null)
|
||||
{
|
||||
_bgImageEffect = CreateBgImageEffect(_albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLastFgImageEffect(ICanvasAnimatedControl control)
|
||||
{
|
||||
_lastFgImageEffect?.Dispose();
|
||||
_lastFgImageEffect = null;
|
||||
if (_lastAlbumArtCanvasBitmap != null)
|
||||
{
|
||||
_lastFgImageEffect = CreateFgImageEffect(control, _lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateFgImageEffect(ICanvasAnimatedControl control)
|
||||
{
|
||||
_fgImageEffect?.Dispose();
|
||||
_fgImageEffect = null;
|
||||
if (_albumArtCanvasBitmap != null)
|
||||
{
|
||||
_fgImageEffect = CreateFgImageEffect(control, _albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.IsDebugOverlayEnabled))
|
||||
{
|
||||
_isDebugOverlayEnabled = message.NewValue;
|
||||
_isDebugOverlayEnabledChanged = true;
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.IsLyricsGlowEffectEnabled))
|
||||
{
|
||||
@@ -139,7 +140,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
if (message.PropertyName == nameof(LyricsWindowViewModel.ActivatedWindowAccentColor))
|
||||
{
|
||||
_immersiveBgTransition.StartTransition(message.NewValue);
|
||||
_immersiveBgColorTransition.StartTransition(message.NewValue);
|
||||
_environmentalColor = message.NewValue;
|
||||
UpdateColorConfig();
|
||||
}
|
||||
@@ -183,6 +184,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.CoverImageRadius))
|
||||
{
|
||||
_albumArtCornerRadius = message.NewValue;
|
||||
_isAlbumArtCornerRadiusChanged = true;
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.CoverOverlayOpacity))
|
||||
{
|
||||
@@ -231,6 +233,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFontStrokeWidth))
|
||||
{
|
||||
_lyricsFontStrokeWidth = message.NewValue;
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsScrollDuration))
|
||||
{
|
||||
@@ -277,6 +280,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.LyricsAlignmentType))
|
||||
{
|
||||
_lyricsAlignmentType = message.NewValue;
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.SongInfoAlignmentType))
|
||||
{
|
||||
|
||||
@@ -14,11 +14,11 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
private readonly ValueTransition<float> _canvasYScrollTransition = new(
|
||||
initialValue: 0f,
|
||||
durationSeconds: 0.5f,
|
||||
easingType: EasingType.EaseInOutCubic
|
||||
durationSeconds: 0.3f,
|
||||
easingType: EasingType.EaseInOutSine
|
||||
);
|
||||
|
||||
private readonly ValueTransition<Color> _immersiveBgTransition = new(
|
||||
private readonly ValueTransition<Color> _immersiveBgColorTransition = new(
|
||||
initialValue: Colors.Transparent,
|
||||
durationSeconds: 0.3f,
|
||||
interpolator: (from, to, progress) => Helper.ColorHelper.GetInterpolatedColor(progress, from, to)
|
||||
@@ -32,27 +32,31 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private readonly ValueTransition<float> _immersiveBgOpacityTransition = new(
|
||||
initialValue: 1f,
|
||||
durationSeconds: 0.2f
|
||||
durationSeconds: 0.3f
|
||||
);
|
||||
|
||||
private readonly ValueTransition<float> _titleXTransition = new(
|
||||
initialValue: 0f,
|
||||
durationSeconds: 0.3f
|
||||
durationSeconds: 0.3f,
|
||||
easingType: EasingType.EaseInOutBack
|
||||
);
|
||||
|
||||
private readonly ValueTransition<float> _titleYTransition = new(
|
||||
initialValue: 0f,
|
||||
durationSeconds: 0.3f
|
||||
durationSeconds: 0.3f,
|
||||
easingType: EasingType.EaseInOutBack
|
||||
);
|
||||
|
||||
private readonly ValueTransition<float> _lyricsXTransition = new(
|
||||
initialValue: 0f,
|
||||
durationSeconds: 0.3f
|
||||
durationSeconds: 0.3f,
|
||||
easingType: EasingType.EaseInOutBack
|
||||
);
|
||||
|
||||
private readonly ValueTransition<float> _lyricsYTransition = new(
|
||||
initialValue: 0f,
|
||||
durationSeconds: 0.3f
|
||||
durationSeconds: 0.3f,
|
||||
easingType: EasingType.EaseInOutBack
|
||||
);
|
||||
|
||||
private readonly ValueTransition<float> _lyricsOpacityTransition = new(
|
||||
@@ -72,12 +76,14 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private readonly ValueTransition<float> _albumArtXTransition = new(
|
||||
initialValue: 0f,
|
||||
durationSeconds: 0.3f
|
||||
durationSeconds: 0.3f,
|
||||
easingType: EasingType.EaseInOutBack
|
||||
);
|
||||
|
||||
private readonly ValueTransition<float> _albumArtYTransition = new(
|
||||
initialValue: 0f,
|
||||
durationSeconds: 0.3f
|
||||
durationSeconds: 0.3f,
|
||||
easingType: EasingType.EaseInOutBack
|
||||
);
|
||||
|
||||
private readonly ValueTransition<float> _songInfoOpacityTransition = new(
|
||||
|
||||
@@ -28,6 +28,13 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
private bool _isPlayingLineChanged = false;
|
||||
private bool _isVisibleLinesBoundaryChanged = false;
|
||||
|
||||
private bool _isDebugOverlayEnabledChanged = false;
|
||||
|
||||
private bool _albumArtChanged = false;
|
||||
private bool _isCoverAcrylicEffectAmountChanged = false;
|
||||
|
||||
private bool _isAlbumArtCornerRadiusChanged = true;
|
||||
|
||||
public void Update(ICanvasAnimatedControl control, CanvasAnimatedUpdateEventArgs args)
|
||||
{
|
||||
_elapsedTime = args.Timing.ElapsedTime;
|
||||
@@ -49,19 +56,18 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_displayType = _displayTypeReceived;
|
||||
_playingLineIndex = playingLineIndex;
|
||||
|
||||
if (_albumArtChanged)
|
||||
if (_isDebugOverlayEnabledChanged)
|
||||
{
|
||||
if (_lastAlbumArtSwBitmap != null)
|
||||
if (_isDebugOverlayEnabled)
|
||||
{
|
||||
_lastAlbumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _lastAlbumArtSwBitmap);
|
||||
_drawFrameStopwatch = Stopwatch.StartNew();
|
||||
}
|
||||
_albumArtBgTransition.Reset(0f);
|
||||
_albumArtBgTransition.StartTransition(1f);
|
||||
if (_albumArtSwBitmap != null)
|
||||
else
|
||||
{
|
||||
_albumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _albumArtSwBitmap);
|
||||
_drawFrameStopwatch?.Stop();
|
||||
_drawFrameStopwatch = null;
|
||||
}
|
||||
_albumArtChanged = false;
|
||||
_isDebugOverlayEnabledChanged = false;
|
||||
}
|
||||
|
||||
if (_isDynamicCoverOverlayEnabled)
|
||||
@@ -87,14 +93,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_isCoverAcrylicEffectAmountChanged = true;
|
||||
}
|
||||
|
||||
if (_isCoverAcrylicEffectAmountChanged)
|
||||
if (_isDisplayTypeChanged || _isCanvasWidthChanged || _isCanvasHeightChanged)
|
||||
{
|
||||
UpdateCoverAcrylicOverlay(control);
|
||||
}
|
||||
|
||||
if (_isDisplayTypeChanged || _isCanvasWidthChanged)
|
||||
{
|
||||
bool jumpTo = !_isDisplayTypeChanged && _isCanvasWidthChanged;
|
||||
bool jumpTo = !_isDisplayTypeChanged && (_isCanvasWidthChanged || _isCanvasHeightChanged);
|
||||
switch (_lyricsLayoutOrientation)
|
||||
{
|
||||
case LyricsLayoutOrientation.Horizontal:
|
||||
@@ -161,6 +162,65 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
if (_isAlbumArtCornerRadiusChanged)
|
||||
{
|
||||
UpdateLastFgImageEffect(control);
|
||||
UpdateFgImageEffect(control);
|
||||
_isAlbumArtCornerRadiusChanged = false;
|
||||
}
|
||||
|
||||
// 背景图切换计算
|
||||
// 将当前背景图放到 _lastAlbumArtSwBitmap 中 并设置不透明度为 1
|
||||
// 将新的背景图放到 _albumArtSwBitmap 中 并设置不透明度为 0
|
||||
// 这样可以实现背景图的连贯渐变效果
|
||||
if (_albumArtChanged || _isCanvasHeightChanged || _isCanvasWidthChanged ||
|
||||
_lyricsBgBrightnessTransition.IsTransitioning ||
|
||||
_albumArtBgTransition.IsTransitioning)
|
||||
{
|
||||
// 必须先在此处重置动画
|
||||
if (_albumArtChanged)
|
||||
{
|
||||
_albumArtBgTransition.Reset(0f);
|
||||
_albumArtBgTransition.StartTransition(1f);
|
||||
}
|
||||
// 更新 last
|
||||
if (_albumArtChanged)
|
||||
{
|
||||
if (_lastAlbumArtSwBitmap != null)
|
||||
{
|
||||
_lastAlbumArtCanvasBitmap?.Dispose();
|
||||
_lastAlbumArtCanvasBitmap = null;
|
||||
_lastAlbumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _lastAlbumArtSwBitmap);
|
||||
}
|
||||
}
|
||||
UpdateLastFgImageEffect(control);
|
||||
UpdateLastBgImageEffect();
|
||||
// 更新 current
|
||||
if (_albumArtChanged)
|
||||
{
|
||||
if (_albumArtSwBitmap != null)
|
||||
{
|
||||
_albumArtCanvasBitmap?.Dispose();
|
||||
_albumArtCanvasBitmap = null;
|
||||
_albumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _albumArtSwBitmap);
|
||||
}
|
||||
}
|
||||
UpdateFgImageEffect(control);
|
||||
UpdateBgImageEffect();
|
||||
// 更新叠加的背景效果
|
||||
UpdateAlbumArtBgEffect(control);
|
||||
}
|
||||
|
||||
if (_isCoverAcrylicEffectAmountChanged)
|
||||
{
|
||||
UpdateCoverAcrylicOverlay(control);
|
||||
UpdateAlbumArtBgEffect(control);
|
||||
|
||||
_isCoverAcrylicEffectAmountChanged = false;
|
||||
}
|
||||
|
||||
_albumArtChanged = false;
|
||||
|
||||
if (_isCanvasWidthChanged || _lyricsXTransition.IsTransitioning)
|
||||
{
|
||||
_maxLyricsWidth = _canvasWidth - _lyricsXTransition.Value - _rightMargin;
|
||||
@@ -191,7 +251,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_lyricsOpacityTransition.Update(_elapsedTime);
|
||||
_albumArtOpacityTransition.Update(_elapsedTime);
|
||||
_immersiveBgOpacityTransition.Update(_elapsedTime);
|
||||
_immersiveBgTransition.Update(_elapsedTime);
|
||||
_immersiveBgColorTransition.Update(_elapsedTime);
|
||||
_albumArtAccentColorTransition.Update(_elapsedTime);
|
||||
_albumArtBgTransition.Update(_elapsedTime);
|
||||
_lyricsBgBrightnessTransition.Update(_elapsedTime);
|
||||
@@ -228,22 +288,16 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.CanvasTextLayout != null)
|
||||
{
|
||||
line.CanvasTextLayout.Dispose();
|
||||
line.CanvasTextLayout = null;
|
||||
}
|
||||
|
||||
// Calculate layout bounds
|
||||
line.CanvasTextLayout = new CanvasTextLayout(
|
||||
control,
|
||||
line.DisplayedText,
|
||||
_lyricsTextFormat,
|
||||
_maxLyricsWidth,
|
||||
_canvasHeight
|
||||
);
|
||||
|
||||
line.UpdateTextLayout(control, _lyricsTextFormat, _maxLyricsWidth, _canvasHeight, _isDockMode ? TextAlignmentType.Center : _lyricsAlignmentType);
|
||||
line.UpdateTextGeometry();
|
||||
line.Position = new Vector2(0, y);
|
||||
line.UpdateCenterPosition(_maxLyricsWidth, _isDockMode ? TextAlignmentType.Center : _lyricsAlignmentType);
|
||||
line.UpdateFontEffect(control, _isDesktopMode, _strokeFontColor, _lyricsFontStrokeWidth, _bgFontColor);
|
||||
|
||||
if (line.CanvasTextLayout == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
y +=
|
||||
(float)line.CanvasTextLayout.LayoutBounds.Height
|
||||
@@ -443,6 +497,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
|
||||
private void UpdateLinesProps()
|
||||
@@ -519,6 +575,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
if (_coverAcrylicEffectAmount > 0)
|
||||
{
|
||||
var ret = NoiseOverlayHelper.GenerateNoiseBitmapBGRA((int)_canvasWidth, (int)_canvasHeight);
|
||||
_coverAcrylicNoiseCanvasBitmap?.Dispose();
|
||||
_coverAcrylicNoiseCanvasBitmap = null;
|
||||
_coverAcrylicNoiseCanvasBitmap = CanvasBitmap.CreateFromBytes(
|
||||
control,
|
||||
ret,
|
||||
@@ -527,7 +585,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized
|
||||
);
|
||||
}
|
||||
_isCoverAcrylicEffectAmountChanged = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using ABI.Microsoft.UI.Xaml;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Events;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Lyricify.Lyrics.Helpers.General;
|
||||
using Lyricify.Lyrics.Providers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||
using Microsoft.Graphics.Display;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Text;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -42,16 +35,17 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private int _songDurationMs = (int)TimeSpan.FromMinutes(99).TotalMilliseconds;
|
||||
|
||||
private Stopwatch? _drawFrameStopwatch;
|
||||
private int _drawFrameCount = 0;
|
||||
private int _displayedDrawFrameCount = 0;
|
||||
|
||||
private SoftwareBitmap? _lastAlbumArtSwBitmap = null;
|
||||
private SoftwareBitmap? _albumArtSwBitmap = null;
|
||||
|
||||
private CanvasBitmap? _lastAlbumArtCanvasBitmap = null;
|
||||
private CanvasBitmap? _albumArtCanvasBitmap = null;
|
||||
|
||||
private bool _albumArtChanged = false;
|
||||
|
||||
private CanvasBitmap? _coverAcrylicNoiseCanvasBitmap = null;
|
||||
private bool _isCoverAcrylicEffectAmountChanged = false;
|
||||
|
||||
private float _albumArtSize = 0f;
|
||||
private int _albumArtCornerRadius = 0;
|
||||
@@ -189,6 +183,11 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
TrimmingSign = CanvasTrimmingSign.Ellipsis,
|
||||
TrimmingGranularity = CanvasTextTrimmingGranularity.Character,
|
||||
};
|
||||
private CanvasTextFormat _debugTextFormat = new()
|
||||
{
|
||||
FontSize = 12,
|
||||
FontWeight = FontWeights.ExtraBlack,
|
||||
};
|
||||
|
||||
private LatestOnlyTaskRunner _refreshLyricsRunner = new();
|
||||
private LatestOnlyTaskRunner _showTranslationsRunner = new();
|
||||
@@ -392,14 +391,12 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
if (e.AlbumArtSwBitmap != _albumArtSwBitmap)
|
||||
{
|
||||
//_lastAlbumArtSwBitmap?.Dispose();
|
||||
_lastAlbumArtSwBitmap = null;
|
||||
_lastAlbumArtSwBitmap = _albumArtSwBitmap;
|
||||
//_lastAlbumArtCanvasBitmap?.Dispose();
|
||||
_lastAlbumArtCanvasBitmap = null;
|
||||
|
||||
//_albumArtSwBitmap?.Dispose();
|
||||
_albumArtSwBitmap = null;
|
||||
_albumArtSwBitmap = e.AlbumArtSwBitmap;
|
||||
//_albumArtCanvasBitmap?.Dispose();
|
||||
_albumArtCanvasBitmap = null;
|
||||
|
||||
_albumArtChanged = true;
|
||||
|
||||
@@ -543,12 +540,12 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
switch (provider)
|
||||
{
|
||||
case Enums.LyricsSearchProvider.QQ:
|
||||
translationRaw = FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, PathHelper.QQTranslationCacheDirectory);
|
||||
translationRaw = Helper.FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, Helper.PathHelper.QQTranslationCacheDirectory);
|
||||
break;
|
||||
case Enums.LyricsSearchProvider.Kugou:
|
||||
break;
|
||||
case Enums.LyricsSearchProvider.Netease:
|
||||
translationRaw = FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, PathHelper.NeteaseTranslationCacheDirectory);
|
||||
translationRaw = Helper.FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, Helper.PathHelper.NeteaseTranslationCacheDirectory);
|
||||
break;
|
||||
case Enums.LyricsSearchProvider.LrcLib:
|
||||
break;
|
||||
|
||||
@@ -105,18 +105,18 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
if (LocalMediaFolders.Any(x => Path.GetFullPath(x.Path).TrimEnd(Path.DirectorySeparatorChar).Equals(normalizedPath.TrimEnd(Path.DirectorySeparatorChar), StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPagePathExistedInfo"));
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPagePathExistedInfo"), InfoBarSeverity.Warning);
|
||||
}
|
||||
else if (LocalMediaFolders.Any(item => normalizedPath.StartsWith(Path.GetFullPath(item.Path).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
// 添加的文件夹是现有文件夹的子文件夹
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPagePathBeIncludedInfo"));
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPagePathBeIncludedInfo"), InfoBarSeverity.Warning);
|
||||
}
|
||||
else if (LocalMediaFolders.Any(item => Path.GetFullPath(item.Path).TrimEnd(Path.DirectorySeparatorChar).StartsWith(normalizedPath, StringComparison.OrdinalIgnoreCase))
|
||||
)
|
||||
{
|
||||
// 添加的文件夹是现有文件夹的父文件夹
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPagePathIncludingOthersInfo"));
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPagePathIncludingOthersInfo"), InfoBarSeverity.Warning);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -136,19 +136,19 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[RelayCommand]
|
||||
private static async Task OpenCacheFolderAsync()
|
||||
{
|
||||
await Windows.System.Launcher.LaunchFolderPathAsync(PathHelper.CacheFolder);
|
||||
await Windows.System.Launcher.LaunchFolderPathAsync(Helper.PathHelper.CacheFolder);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void RestartApp()
|
||||
{
|
||||
WindowHelper.RestartApp();
|
||||
Helper.WindowHelper.RestartApp();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task SelectAndAddFolderAsync(UIElement sender)
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<SettingsWindow>();
|
||||
var window = Helper.WindowHelper.GetWindowByWindowType<SettingsWindow>();
|
||||
if (window == null) return;
|
||||
|
||||
var picker = new Windows.Storage.Pickers.FolderPicker();
|
||||
@@ -177,18 +177,20 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
string result = await _libreTranslateService.TranslateTextAsync("Hello, world!", targetLangCode, null);
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageServerTestSuccessInfo"), Microsoft.UI.Xaml.Controls.InfoBarSeverity.Success);
|
||||
IsLibreTranslateServerTesting = false;
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageServerTestSuccessInfo"), InfoBarSeverity.Success);
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageServerTestFailedInfo"), Microsoft.UI.Xaml.Controls.InfoBarSeverity.Error);
|
||||
IsLibreTranslateServerTesting = false;
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageServerTestFailedInfo"), InfoBarSeverity.Error);
|
||||
});
|
||||
}
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
IsLibreTranslateServerTesting = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -201,9 +203,14 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
bool testResult = await NetHelper.CheckConnectivity($"{LXMusicServer}/status");
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(
|
||||
App.ResourceLoader!.GetString($"SettingsPageServerTest{(testResult ? "Success" : "Failed")}Info"),
|
||||
testResult ? InfoBarSeverity.Success : InfoBarSeverity.Error);
|
||||
if (testResult)
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageServerTestSuccessInfo"), InfoBarSeverity.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageServerTestFailedInfo"), InfoBarSeverity.Error);
|
||||
}
|
||||
IsLXMusicServerTesting = false;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,12 +37,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[RelayCommand]
|
||||
private static void ExitApp()
|
||||
{
|
||||
LyricsWindow? lyricsWindow = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
if (lyricsWindow != null)
|
||||
{
|
||||
DockModeHelper.Disable(lyricsWindow);
|
||||
}
|
||||
Environment.Exit(0);
|
||||
WindowHelper.ExitApp();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
|
||||
@@ -113,6 +113,7 @@
|
||||
x:Name="SettingsFlyoutItem"
|
||||
x:Uid="SystemTraySettings"
|
||||
Click="SettingsMenuFlyoutItem_Click" />
|
||||
<MenuFlyoutItem x:Uid="SystemTrayExit" Click="ExitAppMenuFlyoutItem_Click" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
|
||||
@@ -41,8 +41,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
|
||||
private void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args)
|
||||
{
|
||||
DockModeHelper.Disable(this);
|
||||
Environment.Exit(0);
|
||||
WindowHelper.ExitApp();
|
||||
}
|
||||
|
||||
public void UpdateTitleBarArea()
|
||||
@@ -267,11 +266,6 @@ namespace BetterLyrics.WinUI3.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void TipContainerCenter_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
App.Current.LyricsWindowNotificationPanel = TipContainerCenter;
|
||||
}
|
||||
|
||||
private void RootGrid_PointerEntered(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
ViewModel.IsMouseWithinWindow = true;
|
||||
@@ -308,5 +302,15 @@ namespace BetterLyrics.WinUI3.Views
|
||||
{
|
||||
WindowHelper.OpenWindow<MusicGalleryWindow>();
|
||||
}
|
||||
|
||||
private void ExitAppMenuFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowHelper.ExitApp();
|
||||
}
|
||||
|
||||
private void TipContainerCenter_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
App.Current.LyricsWindowNotificationPanel = TipContainerCenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1078,16 +1078,5 @@
|
||||
</ScrollViewer>
|
||||
</NavigationView>
|
||||
|
||||
<scontrols:NotificationPanel
|
||||
x:Name="TipContainerCenter"
|
||||
Margin="0,0,0,52"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
Canvas.ZIndex="1"
|
||||
FlowDirection="RightToLeft"
|
||||
Loaded="TipContainerCenter_Loaded"
|
||||
Orientation="Vertical"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
@@ -89,11 +89,6 @@ namespace BetterLyrics.WinUI3.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void TipContainerCenter_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel = TipContainerCenter;
|
||||
}
|
||||
|
||||
private async void AutoStartupToggleSwitch_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AutoStartupToggleSwitch.IsOn = await ViewModel.DetectIsAutoStartupEnabledAsync();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Views"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:scontrols="using:ShadowViewer.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Window.SystemBackdrop>
|
||||
@@ -14,6 +15,17 @@
|
||||
|
||||
<Grid x:Name="RootGrid">
|
||||
<Frame x:Name="RootFrame" />
|
||||
|
||||
<scontrols:NotificationPanel
|
||||
x:Name="TipContainerCenter"
|
||||
Margin="0,0,0,52"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
Canvas.ZIndex="1"
|
||||
FlowDirection="RightToLeft"
|
||||
Loaded="TipContainerCenter_Loaded"
|
||||
Orientation="Vertical"
|
||||
Visibility="Collapsed" />
|
||||
</Grid>
|
||||
|
||||
</Window>
|
||||
|
||||
@@ -20,5 +20,10 @@ namespace BetterLyrics.WinUI3.Views
|
||||
|
||||
RootFrame.Navigate(typeof(SettingsPage));
|
||||
}
|
||||
|
||||
private void TipContainerCenter_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel = TipContainerCenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
14
FAQ/FAQ.md
Normal file
14
FAQ/FAQ.md
Normal file
@@ -0,0 +1,14 @@
|
||||
## FAQ has been moved
|
||||
[Click here to visit](https://github.com/jayfunc/BetterLyrics?tab=readme-ov-file#faq)
|
||||
|
||||
## FAQ 现已迁移
|
||||
[点此访问](https://github.com/jayfunc/BetterLyrics/blob/dev/README.zh-CN.md#faq)
|
||||
|
||||
## FAQ 已移至新位置
|
||||
[點此前往](https://github.com/jayfunc/BetterLyrics/blob/dev/README.zh-TW.md#faq)
|
||||
|
||||
## FAQ は移動しました
|
||||
[こちらをクリック](https://github.com/jayfunc/BetterLyrics/blob/dev/README.ja.md#faq)
|
||||
|
||||
## FAQ가 이동되었습니다
|
||||
[여기를 클릭하세요](https://github.com/jayfunc/BetterLyrics/blob/dev/README.ko.md#faq)
|
||||
44
Promotion/en.txt
Normal file
44
Promotion/en.txt
Normal file
@@ -0,0 +1,44 @@
|
||||
* The free trial version is identical to the paid version — no feature limitations.
|
||||
|
||||
🎵 BetterLyrics — Lyrics that move you, visuals that delight. A stunning lyrics display tool for Windows.
|
||||
|
||||
Looking for a smooth, dynamic, and immersive way to view lyrics on Windows?
|
||||
BetterLyrics delivers a whole new visual experience — making every song truly sing on screen.
|
||||
|
||||
✨ Key Features
|
||||
|
||||
- Beautiful UI with smooth animations
|
||||
Built with WinUI 3, featuring multiple themes and dynamic backgrounds. Enjoy seamless lyric scrolling, fade effects, and rich visuals.
|
||||
|
||||
- Offline translation with support for 30 languages
|
||||
Automatically reads translation lines embedded in local lyrics files. Multi-language support helps you understand every lyric, no internet needed.
|
||||
|
||||
- Supports multiple lyric sources and formats
|
||||
Reads local lyrics in LRC, ESLRC, TTML, and other formats. Also fetches lyrics online from major sources like QQ Music, NetEase Cloud Music, Kugou, and LrcLib.
|
||||
|
||||
- Real-time sync with various music players
|
||||
Compatible with NetEase Cloud, Kugou, Apple Music, Spotify, PotPlayer, MusicBee, AIMP, and even the default Windows player. Lyrics sync automatically—no setup required.
|
||||
|
||||
- Multiple display modes to suit your workflow
|
||||
Switch easily between immersive full-screen mode, floating desktop lyrics, and smart window docking to fit any listening scenario.
|
||||
|
||||
- Auto-hide when playback is paused
|
||||
The interface stays out of your way — lyrics automatically hide when music stops, keeping your screen clean and distraction-free.
|
||||
|
||||
🔧 Extra Features You’ll Love
|
||||
|
||||
- Fine-tune lyric timing with offset adjustment — perfect for mismatched audio versions
|
||||
|
||||
- Toggle translation, customize layout, pin or lock windows — your lyrics, your way
|
||||
|
||||
- Active community, frequent updates, and responsive support for user feedback
|
||||
|
||||
✅ Perfect For:
|
||||
|
||||
- Users who want floating desktop lyrics to elevate their listening experience
|
||||
|
||||
- Listeners who use multiple players or need support for various lyric formats
|
||||
|
||||
- Fans of beautiful, customizable visuals in their music tools
|
||||
|
||||
🎧 Whether you're immersed in music through headphones or want lyrics to stay visible on your screen, BetterLyrics gives you a personalized, immersive way to experience every song.
|
||||
44
Promotion/ja.txt
Normal file
44
Promotion/ja.txt
Normal file
@@ -0,0 +1,44 @@
|
||||
* 無料体験版と有料版は機能に違いはありません。
|
||||
|
||||
🎵 BetterLyrics — 歌詞が心を動かし、目を楽しませる。高品質なWindows用歌詞表示ツール
|
||||
|
||||
Windowsで滑らかでダイナミック、没入感のある歌詞表示を体験しませんか?
|
||||
BetterLyricsは全く新しいビジュアル体験を提供し、すべての曲が画面上でまるで「歌っている」ように感じられます。
|
||||
|
||||
✨ 主な機能
|
||||
|
||||
- 美しいインターフェースと滑らかなアニメーション
|
||||
WinUI 3をベースに開発され、複数のテーマや動的な背景をサポート。歌詞のスクロールやフェード効果など、視覚的に洗練された演出を楽しめます。
|
||||
|
||||
- オフライン翻訳対応、30言語サポート
|
||||
ローカルの歌詞ファイルに含まれる翻訳を自動で読み込み表示。インターネット接続なしで多言語の歌詞理解をサポートします。
|
||||
|
||||
- 多様な歌詞フォーマットとソースに対応
|
||||
LRC、ESLRC、TTMLなどのローカル歌詞ファイルを読み込み、さらにQQミュージック、NetEaseクラウドミュージック、Kugou、LrcLibなどの主要オンラインソースから歌詞を取得可能です。
|
||||
|
||||
- 多くの音楽プレイヤーとリアルタイム同期
|
||||
NetEaseクラウドミュージック、Kugou、Apple Music、Spotify、PotPlayer、MusicBee、AIMP、そしてWindows標準プレイヤーまで幅広く対応。歌詞は自動的に同期され、手動設定は不要です。
|
||||
|
||||
- 多彩な表示モードを自由に切り替え
|
||||
没入型の全画面モード、デスクトップに浮かぶ歌詞、スマートウィンドウドッキングなど、用途に合わせて切り替え可能。
|
||||
|
||||
- 再生停止時には自動で非表示
|
||||
音楽が一時停止すると歌詞画面が自動的に隠れ、画面を邪魔せずスッキリ使えます。
|
||||
|
||||
🔧 便利な追加機能
|
||||
|
||||
- 微調整可能な歌詞タイムラインオフセットで、音源のズレをぴったり補正
|
||||
|
||||
- 翻訳表示のオンオフ、レイアウトのカスタマイズ、ウィンドウの固定・ロックなどの高度な設定
|
||||
|
||||
- 活発なユーザーコミュニティによる継続的なアップデートと迅速なフィードバック対応
|
||||
|
||||
✅ こんな方におすすめ
|
||||
|
||||
- デスクトップに歌詞を浮かべて、より豊かな音楽体験を求める方
|
||||
|
||||
- 複数のプレイヤーや多様な歌詞フォーマットを使いたい方
|
||||
|
||||
- 美しくカスタマイズ可能なUIを好む方
|
||||
|
||||
🎧 ヘッドホンで没入して聴くときも、デスクトップに歌詞を表示して楽しむときも、BetterLyricsがあなたの音楽体験をより特別なものにします。
|
||||
45
Promotion/ko.txt
Normal file
45
Promotion/ko.txt
Normal file
@@ -0,0 +1,45 @@
|
||||
* 무료 체험판과 유료 버전은 기능 차이가 전혀 없습니다.
|
||||
|
||||
🎵 BetterLyrics — 가사는 눈으로, 감동은 마음으로. 고품질 Windows용 가사 디스플레이 도구
|
||||
|
||||
Windows에서 부드럽고 역동적이며 몰입감 있는 가사 표시를 경험해보세요.
|
||||
BetterLyrics는 완전히 새로운 시각적 음악 경험을 선사합니다. 이제 모든 곡이 화면 위에서 살아 숨쉽니다.
|
||||
|
||||
✨ 주요 기능
|
||||
|
||||
- 세련된 인터페이스와 부드러운 애니메이션
|
||||
WinUI 3 기반으로 개발되었으며 다양한 테마와 동적 배경을 지원합니다. 가사 스크롤, 페이드 효과 등 시각적 효과가 매끄럽고 아름답습니다.
|
||||
|
||||
- 30개 언어를 지원하는 오프라인 번역 기능
|
||||
로컬 가사 파일 내에 포함된 번역 내용을 자동으로 읽어와 표시합니다. 인터넷 연결 없이도 다양한 언어의 가사를 이해할 수 있습니다.
|
||||
|
||||
- 다양한 가사 형식 및 소스 지원
|
||||
LRC, ESLRC, TTML 등 로컬 파일 형식을 지원하며, QQ 음악, 넷이즈 클라우드, 쿠거우, LrcLib 등 주요 온라인 소스에서 가사를 자동으로 가져올 수 있습니다.
|
||||
|
||||
- 다양한 음악 플레이어와 실시간 동기화
|
||||
넷이즈, 쿠거우, Apple Music, Spotify, PotPlayer, MusicBee, AIMP, 그리고 Windows 기본 플레이어까지 폭넓게 호환됩니다. 가사는 자동으로 동기화되어 별도 설정 없이도 편리하게 사용 가능합니다.
|
||||
|
||||
- 다양한 디스플레이 모드 제공
|
||||
몰입형 전체 화면, 바탕화면 가사 띄우기, 스마트 윈도우 도킹 등 다양한 사용 환경에 맞춰 자유롭게 전환할 수 있습니다.
|
||||
|
||||
- 자동 숨김 기능으로 깔끔한 화면 유지
|
||||
음악이 일시정지되면 가사 창이 자동으로 숨겨져 화면을 방해하지 않고 깔끔함을 유지합니다.
|
||||
|
||||
🔧 세심한 부가기능
|
||||
|
||||
- 가사 싱크를 미세하게 조정할 수 있는 타임라인 오프셋 기능 제공
|
||||
|
||||
- 번역 표시 여부, 레이아웃 설정, 창 고정 및 잠금 등 고급 옵션 지원
|
||||
|
||||
- 활발한 사용자 커뮤니티 운영 중이며, 지속적인 업데이트와 피드백 반영
|
||||
|
||||
✅ 이런 분께 추천합니다
|
||||
|
||||
- 바탕화면에 가사를 띄워 감성적인 음악 감상을 원하는 분
|
||||
|
||||
- 다양한 플레이어나 가사 형식을 사용하는 분
|
||||
|
||||
- 세련되고 사용자 맞춤형 UI를 선호하는 분
|
||||
|
||||
🎧 헤드폰을 쓰고 몰입해서 듣든, 바탕화면에 가사를 띄워 놓고 감상하든 BetterLyrics는 여러분만의 음악 감상 경험을 완성해드립니다.
|
||||
|
||||
44
Promotion/zh-CN.txt
Normal file
44
Promotion/zh-CN.txt
Normal file
@@ -0,0 +1,44 @@
|
||||
* 免费试用版与付费版无任何区别
|
||||
|
||||
🎵 BetterLyrics —— 曲中人心、词悦双眼,高颜值 Windows 歌词展示工具
|
||||
|
||||
想在 Windows 上体验流畅、动态、沉浸的歌词显示效果?
|
||||
BetterLyrics 打造全新视觉体验,让每一首歌都真正“唱”给你看!
|
||||
|
||||
✨ 核心功能亮点
|
||||
|
||||
- 界面美观,动画丝滑
|
||||
基于 WinUI 3 框架开发,支持多种主题风格与动态背景,歌词滚动、淡入淡出等特效令人眼前一亮。
|
||||
|
||||
- 可配置接入离线翻译,支持 30 种语言
|
||||
自动读取本地歌词中的翻译内容,支持多语言自动识别与显示,助你听懂每一句歌词。
|
||||
|
||||
- 支持多种歌词来源与格式
|
||||
可读取本地的 LRC、ESLRC、TTML 等格式歌词文件,同时支持从在线源获取歌词,包括 QQ 音乐、网易云、酷狗音乐与 LrcLib 等主流平台。
|
||||
|
||||
- 多播放器实时同步
|
||||
支持网易云音乐、酷狗音乐、Apple Music、Spotify、PotPlayer、MusicBee、AIMP 等,系统自带播放器也能用,歌词自动同步无需手动干预。
|
||||
|
||||
- 多种显示模式随心切换
|
||||
沉浸式全屏、桌面悬浮歌词、窗口智能停靠,满足你不同场景的需求。
|
||||
|
||||
- 自动隐藏,安静陪伴
|
||||
播放器暂停时自动隐藏歌词界面,不打扰、不占屏,清爽使用体验。
|
||||
|
||||
🔧 更多贴心功能
|
||||
|
||||
- 歌词时间轴支持偏移微调,解决不同版本音频对不上的问题
|
||||
|
||||
- 支持歌词翻译开关、界面布局自由设置、窗口置顶/锁定等高级功能
|
||||
|
||||
- 拥有活跃的用户社区,持续更新优化,问题反馈及时响应
|
||||
|
||||
✅ 推荐使用场景
|
||||
|
||||
- 想要桌面歌词悬浮,提升听歌氛围
|
||||
|
||||
- 需要跨平台、多格式的歌词显示支持
|
||||
|
||||
- 喜欢细节丰富、界面可自定义的听歌工具
|
||||
|
||||
🎧 无论你是用耳机沉浸式聆听,还是想让歌词在桌面随时可见,BetterLyrics 都能为你打造专属的听歌体验!
|
||||
44
Promotion/zh-TW.txt
Normal file
44
Promotion/zh-TW.txt
Normal file
@@ -0,0 +1,44 @@
|
||||
* 免費試用版與付費版功能完全一致
|
||||
|
||||
🎵 BetterLyrics —— 曲動人心、詞悅雙眼,高顏值 Windows 歌詞顯示工具
|
||||
|
||||
想在 Windows 上體驗流暢、動態、沉浸感十足的歌詞顯示效果?
|
||||
BetterLyrics 為你打造全新視覺享受,讓每一首歌都真正「唱」給你看!
|
||||
|
||||
✨ 核心功能亮點
|
||||
|
||||
- 介面美觀,動畫流暢
|
||||
採用 WinUI 3 框架打造,支援多種主題風格與動態背景,歌詞滾動、淡入淡出等特效精緻細膩。
|
||||
|
||||
- 可設定離線翻譯,支援 30 種語言
|
||||
自動讀取本地歌詞中的翻譯內容,支援多語系辨識與顯示,幫你聽懂每一句歌詞。
|
||||
|
||||
- 支援多種歌詞來源與格式
|
||||
可讀取本地的 LRC、ESLRC、TTML 等格式歌詞檔,同時支援從線上來源獲取歌詞,包括 QQ 音樂、網易雲、酷狗音樂與 LrcLib 等主流平台。
|
||||
|
||||
- 多播放器即時同步
|
||||
相容網易雲音樂、酷狗音樂、Apple Music、Spotify、PotPlayer、MusicBee、AIMP 等播放器,甚至支援系統內建播放器,歌詞自動同步無須手動調整。
|
||||
|
||||
- 多種顯示模式自由切換
|
||||
沉浸式全螢幕、桌面浮動歌詞、智慧貼齊窗口等模式,靈活搭配不同使用場景。
|
||||
|
||||
- 自動隱藏,安靜陪伴
|
||||
音樂暫停時自動隱藏歌詞介面,不打擾、不佔螢幕,帶來更清爽的使用體驗。
|
||||
|
||||
🔧 更多貼心功能
|
||||
|
||||
- 歌詞時間軸支援細微調整,完美對齊不同版本的音訊
|
||||
|
||||
- 支援翻譯開關、介面版面自定義、窗口鎖定與置頂等進階選項
|
||||
|
||||
- 活躍用戶社群持續參與、版本持續優化、問題回饋即時處理
|
||||
|
||||
✅ 適用場景推薦
|
||||
|
||||
- 想要桌面浮動歌詞,增強聽歌氛圍
|
||||
|
||||
- 需要跨平台、多格式的歌詞支援
|
||||
|
||||
- 喜愛細節豐富、介面可自訂的聽歌工具
|
||||
|
||||
🎧 無論你是戴上耳機沉浸聆聽,還是想讓歌詞隨時浮現在桌面,BetterLyrics 都能為你打造專屬的聽歌體驗!
|
||||
2
README.CN.md
Normal file
2
README.CN.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## 简体中文文档现已迁移
|
||||
[点此访问](https://github.com/jayfunc/BetterLyrics/blob/dev/README.zh-CN.md)
|
||||
Reference in New Issue
Block a user