mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-12 10:54:55 +08:00
fix
This commit is contained in:
@@ -5,52 +5,62 @@
|
||||
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
|
||||
xmlns:uap18="http://schemas.microsoft.com/appx/manifest/uap/windows10/18"
|
||||
IgnorableNamespaces="uap rescap uap18">
|
||||
|
||||
<Identity
|
||||
Name="37412.BetterLyrics"
|
||||
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
|
||||
Version="1.0.8.0" />
|
||||
<Identity
|
||||
Name="37412.BetterLyrics"
|
||||
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
|
||||
Version="1.0.9.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
<Properties>
|
||||
<DisplayName>BetterLyrics</DisplayName>
|
||||
<PublisherDisplayName>founchoo</PublisherDisplayName>
|
||||
<Logo>Images\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Properties>
|
||||
<DisplayName>BetterLyrics</DisplayName>
|
||||
<PublisherDisplayName>founchoo</PublisherDisplayName>
|
||||
<Logo>Images\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.19041.0" MaxVersionTested="10.0.26100.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.26100.0" />
|
||||
</Dependencies>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.19041.0" MaxVersionTested="10.0.26100.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.26100.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="en-US"/>
|
||||
<Resource Language="zh-CN"/>
|
||||
<Resource Language="zh-TW"/>
|
||||
<Resource Language="ja-JP"/>
|
||||
<Resource Language="ko-KR"/>
|
||||
</Resources>
|
||||
<Resources>
|
||||
<Resource Language="en-US"/>
|
||||
<Resource Language="zh-CN"/>
|
||||
<Resource Language="zh-TW"/>
|
||||
<Resource Language="ja-JP"/>
|
||||
<Resource Language="ko-KR"/>
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="App"
|
||||
Executable="$targetnametoken$.exe"
|
||||
EntryPoint="$targetentrypoint$">
|
||||
<uap:VisualElements
|
||||
DisplayName="BetterLyrics"
|
||||
Description="BetterLyrics.WinUI3 (Package)"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Images\Square150x150Logo.png"
|
||||
Square44x44Logo="Images\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png"/>
|
||||
<uap:SplashScreen Image="Images\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Applications>
|
||||
<Application Id="App"
|
||||
Executable="$targetnametoken$.exe"
|
||||
EntryPoint="$targetentrypoint$">
|
||||
<uap:VisualElements
|
||||
DisplayName="BetterLyrics"
|
||||
Description="BetterLyrics.WinUI3 (Package)"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Images\Square150x150Logo.png"
|
||||
Square44x44Logo="Images\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png"/>
|
||||
<uap:SplashScreen Image="Images\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
<uap5:Extension
|
||||
Category="windows.startupTask">
|
||||
<uap5:StartupTask
|
||||
TaskId="AutoStartup"
|
||||
Enabled="false"
|
||||
DisplayName="BetterLyrics" />
|
||||
</uap5:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
</Capabilities>
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
</Capabilities>
|
||||
</Package>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
<x:Double x:Key="SettingsCardSpacing">4</x:Double>
|
||||
|
||||
<!-- Style (inc. the correct spacing) of a section header -->
|
||||
<!-- Style -->
|
||||
<Style
|
||||
x:Key="SettingsSectionHeaderTextBlockStyle"
|
||||
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
@@ -16,6 +12,11 @@ using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.Windows.ApplicationModel.Resources;
|
||||
using Serilog;
|
||||
using ShadowViewer.Controls;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3
|
||||
{
|
||||
@@ -23,13 +24,15 @@ namespace BetterLyrics.WinUI3
|
||||
{
|
||||
|
||||
private readonly ILogger<App> _logger;
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
public static new App Current => (App)Application.Current;
|
||||
public static DispatcherQueue? DispatcherQueue { get; private set; }
|
||||
public static DispatcherQueueTimer? DispatcherQueueTimer { get; private set; }
|
||||
public static ResourceLoader? ResourceLoader { get; private set; }
|
||||
|
||||
public NotificationPanel? LyricsWindowNotificationPanel { get; set; }
|
||||
public NotificationPanel? SettingsWindowNotificationPanel { get; set; }
|
||||
|
||||
public App()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -43,7 +46,6 @@ namespace BetterLyrics.WinUI3
|
||||
ConfigureServices();
|
||||
|
||||
_logger = Ioc.Default.GetRequiredService<ILogger<App>>();
|
||||
_settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
|
||||
|
||||
UnhandledException += App_UnhandledException;
|
||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||
@@ -90,6 +92,7 @@ namespace BetterLyrics.WinUI3
|
||||
.AddSingleton<IPlaybackService, PlaybackService>()
|
||||
.AddSingleton<IMusicSearchService, MusicSearchService>()
|
||||
.AddSingleton<ILibWatcherService, LibWatcherService>()
|
||||
.AddSingleton<ILibreTranslateService, LibreTranslateService>()
|
||||
// ViewModels
|
||||
.AddSingleton<LyricsWindowViewModel>()
|
||||
.AddSingleton<SettingsWindowViewModel>()
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Helpers" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
|
||||
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" />
|
||||
<PackageReference Include="Fluent.LibreTranslate" Version="1.0.6" />
|
||||
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.3.0" />
|
||||
<PackageReference Include="iTunesSearch" Version="1.0.44" />
|
||||
<PackageReference Include="Lyricify.Lyrics.Helper-NativeAot" Version="0.1.4-alpha.5" />
|
||||
@@ -52,6 +51,7 @@
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250606001" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.2" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
<PackageReference Include="ShadowViewer.Controls.Notification" Version="1.2.1" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.10" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="9.0.6" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.6" />
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public bool IsTransitioning => _isTransitioning;
|
||||
public T Value => _currentValue;
|
||||
public T TargetValue => _targetValue;
|
||||
|
||||
public ValueTransition(T initialValue, float durationSeconds, Func<T, T, float, T>? interpolator = null, EasingType? easingType = null)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
@@ -26,31 +28,40 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public const string GithubUrl = "https://github.com/jayfunc/BetterLyrics";
|
||||
|
||||
public static string CacheFolder => ApplicationData.Current.LocalCacheFolder.Path;
|
||||
|
||||
|
||||
public const string UnlockWindowTag = "UnlockWindow";
|
||||
|
||||
public static string AmllTtmlDbIndexPath => Path.Combine(CacheFolder, "amll-ttml-db-index.json");
|
||||
public static string AmllTtmlDbLyricsCacheDirectory => Path.Combine(CacheFolder, "amll-ttml-db-lyrics");
|
||||
|
||||
public static string AssetsFolder => Path.Combine(Package.Current.InstalledPath, "Assets");
|
||||
public static string CacheFolder => ApplicationData.Current.LocalCacheFolder.Path;
|
||||
public static string KugouLyricsCacheDirectory => Path.Combine(CacheFolder, "kugou-lyrics");
|
||||
public static string LogDirectory => Path.Combine(CacheFolder, "logs");
|
||||
public static string LogFilePattern => Path.Combine(LogDirectory, "log-.txt");
|
||||
|
||||
public static string LrcLibLyricsCacheDirectory => Path.Combine(CacheFolder, "lrclib-lyrics");
|
||||
public static string NeteaseLyricsCacheDirectory => Path.Combine(CacheFolder, "netease-lyrics");
|
||||
public static string QQLyricsCacheDirectory => Path.Combine(CacheFolder, "qq-lyrics");
|
||||
public static string KugouLyricsCacheDirectory => Path.Combine(CacheFolder, "kugou-lyrics");
|
||||
public static string AmllTtmlDbLyricsCacheDirectory => Path.Combine(CacheFolder, "amll-ttml-db-lyrics");
|
||||
|
||||
public static string iTunesAlbumArtCacheDirectory => Path.Combine(CacheFolder, "itunes-album-art");
|
||||
|
||||
|
||||
private static string LocalFolder => ApplicationData.Current.LocalFolder.Path;
|
||||
|
||||
public static void EnsureDirectories()
|
||||
{
|
||||
Directory.CreateDirectory(LocalFolder);
|
||||
Directory.CreateDirectory(LogDirectory);
|
||||
|
||||
Directory.CreateDirectory(LrcLibLyricsCacheDirectory);
|
||||
Directory.CreateDirectory(QQLyricsCacheDirectory);
|
||||
Directory.CreateDirectory(KugouLyricsCacheDirectory);
|
||||
Directory.CreateDirectory(NeteaseLyricsCacheDirectory);
|
||||
Directory.CreateDirectory(AmllTtmlDbLyricsCacheDirectory);
|
||||
|
||||
Directory.CreateDirectory(iTunesAlbumArtCacheDirectory);
|
||||
}
|
||||
|
||||
public static async Task<DateTime> GetBuildDate()
|
||||
@@ -66,5 +77,39 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
// 返回修改日期
|
||||
return props.DateModified.DateTime;
|
||||
}
|
||||
|
||||
public static List<LanguageInfo> GetAllTranslationLanguagesInfo() =>
|
||||
[
|
||||
new LanguageInfo("ar", "العربية"),
|
||||
new LanguageInfo("az", "Azərbaycan dili"),
|
||||
new LanguageInfo("zh", "中文"),
|
||||
new LanguageInfo("cs", "Čeština"),
|
||||
new LanguageInfo("da", "Dansk"),
|
||||
new LanguageInfo("nl", "Nederlands"),
|
||||
new LanguageInfo("en", "English"),
|
||||
new LanguageInfo("eo", "Esperanto"),
|
||||
new LanguageInfo("fi", "Suomi"),
|
||||
new LanguageInfo("fr", "Français"),
|
||||
new LanguageInfo("de", "Deutsch"),
|
||||
new LanguageInfo("el", "Ελληνικά"),
|
||||
new LanguageInfo("he", "עברית"),
|
||||
new LanguageInfo("hi", "हिन्दी"),
|
||||
new LanguageInfo("hu", "Magyar"),
|
||||
new LanguageInfo("id", "Bahasa Indonesia"),
|
||||
new LanguageInfo("ga", "Gaeilge"),
|
||||
new LanguageInfo("it", "Italiano"),
|
||||
new LanguageInfo("ja", "日本語"),
|
||||
new LanguageInfo("ko", "한국어"),
|
||||
new LanguageInfo("fa", "فارسی"),
|
||||
new LanguageInfo("pl", "Polski"),
|
||||
new LanguageInfo("pt", "Português"),
|
||||
new LanguageInfo("ru", "Русский"),
|
||||
new LanguageInfo("sk", "Slovenčina"),
|
||||
new LanguageInfo("es", "Español"),
|
||||
new LanguageInfo("sv", "Svenska"),
|
||||
new LanguageInfo("tr", "Türkçe"),
|
||||
new LanguageInfo("uk", "Українська"),
|
||||
new LanguageInfo("vi", "Tiếng Việt"),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,5 +86,17 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
return Color.FromArgb(alpha, color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
public static Color WithBrightness(this Color color, double brightness)
|
||||
{
|
||||
// 确保亮度因子在合理范围内
|
||||
brightness = Math.Max(0, Math.Min(1, brightness));
|
||||
|
||||
var hsl = CommunityToolkit.WinUI.Helpers.ColorHelper.ToHsl(color);
|
||||
double h = hsl.H;
|
||||
double s = hsl.S;
|
||||
|
||||
return CommunityToolkit.WinUI.Helpers.ColorHelper.FromHsl(h, s, brightness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,10 +34,9 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
|
||||
// <20>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>úʹ<C3BA>С
|
||||
var windowManager = WindowManager.Get(window);
|
||||
if (_originalWindowBounds.TryGetValue(hwnd, out var bounds))
|
||||
{
|
||||
windowManager.AppWindow.MoveAndResize(
|
||||
window.AppWindow.MoveAndResize(
|
||||
new Windows.Graphics.RectInt32(
|
||||
(int)bounds.X,
|
||||
(int)bounds.Y,
|
||||
@@ -63,14 +62,13 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
IntPtr hwnd = WindowNative.GetWindowHandle(window);
|
||||
|
||||
// <20><>¼ԭʼ<D4AD><CABC><EFBFBD><EFBFBD>λ<EFBFBD>úʹ<C3BA>С
|
||||
var windowManager = WindowManager.Get(window);
|
||||
if (!_originalWindowBounds.ContainsKey(hwnd))
|
||||
{
|
||||
_originalWindowBounds[hwnd] = (
|
||||
windowManager.AppWindow.Position.X,
|
||||
windowManager.AppWindow.Position.Y,
|
||||
windowManager.Width,
|
||||
windowManager.Height
|
||||
window.AppWindow.Position.X,
|
||||
window.AppWindow.Position.Y,
|
||||
window.AppWindow.Size.Width,
|
||||
window.AppWindow.Size.Height
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,7 +79,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
int targetY = _settingsService.DesktopWindowTop;
|
||||
|
||||
// <20><><EFBFBD>ô<EFBFBD><C3B4>ڴ<EFBFBD>С<EFBFBD><D0A1>λ<EFBFBD><CEBB>
|
||||
windowManager.AppWindow.MoveAndResize(
|
||||
window.AppWindow.MoveAndResize(
|
||||
new Windows.Graphics.RectInt32(targetX, targetY, targetWidth, targetHeight)
|
||||
);
|
||||
|
||||
@@ -102,7 +100,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
public static void Lock(Window window)
|
||||
{
|
||||
window.SystemBackdrop = SystemBackdropHelper.CreateSystemBackdrop(BackdropType.Transparent);
|
||||
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>ޱ߿<DEB1><DFBF><EFBFBD><EFBFBD><CDB8>
|
||||
window.ToggleWindowStyle(true, WindowStyle.Popup | WindowStyle.Visible);
|
||||
window.ExtendsContentIntoTitleBar = false;
|
||||
|
||||
@@ -171,5 +171,22 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
await stream.AsStreamForRead().CopyToAsync(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
public static float GetAverageLuminance(CanvasBitmap bitmap)
|
||||
{
|
||||
var pixels = bitmap.GetPixelBytes();
|
||||
double sum = 0;
|
||||
for (int i = 0; i < pixels.Length; i += 4)
|
||||
{
|
||||
// BGRA
|
||||
byte b = pixels[i];
|
||||
byte g = pixels[i + 1];
|
||||
byte r = pixels[i + 2];
|
||||
// 忽略A
|
||||
double y = 0.299 * r + 0.587 * g + 0.114 * b;
|
||||
sum += y / 255.0;
|
||||
}
|
||||
return (float)(sum / (pixels.Length / 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using Fluent.LibreTranslate;
|
||||
using Lyricify.Lyrics.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Messages
|
||||
{
|
||||
public class ShowNotificatonMessage(Notification value) : ValueChangedMessage<Notification>(value) { }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public class DetectLanguageResult
|
||||
{
|
||||
[JsonPropertyName("confidence")]
|
||||
public double Confidence { get; set; }
|
||||
|
||||
[JsonPropertyName("language")]
|
||||
public string Language { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public partial class LanguageInfo : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
public partial string Code { get; set; }
|
||||
[ObservableProperty]
|
||||
public partial string Name { get; set; }
|
||||
|
||||
public LanguageInfo(string code, string name)
|
||||
{
|
||||
Code = code;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public class LyricsLine
|
||||
{
|
||||
private const float _animationDuration = 0.5f;
|
||||
private const float _animationDuration = 0.3f;
|
||||
public ValueTransition<float> AngleTransition { get; set; } = new(initialValue: 0f, durationSeconds: _animationDuration);
|
||||
public ValueTransition<float> BlurAmountTransition { get; set; } = new(initialValue: 0f, durationSeconds: _animationDuration);
|
||||
public ValueTransition<float> HighlightOpacityTransition { get; set; } = new(initialValue: 0f, durationSeconds: _animationDuration);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public class TranslateResponse
|
||||
{
|
||||
[JsonPropertyName("translatedText")]
|
||||
public string TranslatedText { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Renderer"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
@@ -14,5 +15,15 @@
|
||||
x:Name="LyricsCanvas"
|
||||
Draw="LyricsCanvas_Draw"
|
||||
Update="LyricsCanvas_Update" />
|
||||
<Grid
|
||||
Margin="36"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Visibility="{x:Bind ViewModel.IsTranslating, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<FontIcon
|
||||
x:Name="RotatingIcon"
|
||||
FontFamily="{StaticResource IconFontFamily}"
|
||||
Glyph="" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Renderer
|
||||
{
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace BetterLyrics.WinUI3.Serialization
|
||||
[JsonSerializable(typeof(List<MediaSourceProviderInfo>))]
|
||||
[JsonSerializable(typeof(List<LocalLyricsFolder>))]
|
||||
[JsonSerializable(typeof(List<string>))]
|
||||
[JsonSerializable(typeof(List<DetectLanguageResult>))]
|
||||
[JsonSerializable(typeof(TranslateResponse))]
|
||||
[JsonSerializable(typeof(JsonElement))]
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
internal partial class SourceGenerationContext : JsonSerializerContext { }
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services
|
||||
{
|
||||
public interface ILibreTranslateService
|
||||
{
|
||||
Task<string> TranslateAsync(string text, CancellationToken? token);
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
{
|
||||
public interface IMusicSearchService
|
||||
{
|
||||
Task <byte[]> SearchAlbumArtAsync(string title, string artist, string album);
|
||||
Task <byte[]?> SearchAlbumArtAsync(string title, string artist, string album);
|
||||
|
||||
Task<string?> SearchLyricsAsync(
|
||||
string title,
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace BetterLyrics.WinUI3.Services
|
||||
|
||||
bool AutoLockOnDesktopMode { get; set; }
|
||||
|
||||
string LibreTranslateServer { get; set; }
|
||||
int SelectedTargetLanguageIndex { get; set; }
|
||||
// Lyrics lib
|
||||
|
||||
List<LocalLyricsFolder> LocalLyricsFolders { get; set; }
|
||||
@@ -48,12 +50,20 @@ namespace BetterLyrics.WinUI3.Services
|
||||
|
||||
int LyricsBlurAmount { get; set; }
|
||||
|
||||
Color LyricsCustomFontColor { get; set; }
|
||||
Color LyricsCustomBgFontColor { get; set; }
|
||||
Color LyricsCustomFgFontColor { get; set; }
|
||||
Color LyricsCustomStrokeFontColor { get; set; }
|
||||
|
||||
LyricsFontColorType LyricsFontColorType { get; set; }
|
||||
LyricsFontColorType LyricsBgFontColorType { get; set; }
|
||||
LyricsFontColorType LyricsFgFontColorType { get; set; }
|
||||
LyricsFontColorType LyricsStrokeFontColorType { get; set; }
|
||||
|
||||
int LyricsFontSize { get; set; }
|
||||
|
||||
ElementTheme LyricsBackgroundTheme { get; set; }
|
||||
|
||||
int LyricsFontStrokeWidth { get; set; }
|
||||
|
||||
LyricsFontWeight LyricsFontWeight { get; set; }
|
||||
|
||||
LineRenderingType LyricsGlowEffectScope { get; set; }
|
||||
@@ -65,5 +75,11 @@ namespace BetterLyrics.WinUI3.Services
|
||||
List<MediaSourceProviderInfo> MediaSourceProvidersInfo { get; set; }
|
||||
|
||||
int LyricsVerticalEdgeOpacity { get; set; }
|
||||
|
||||
bool IgnoreFullscreenWindow { get; set; }
|
||||
|
||||
bool IsTranslationEnabled { get; set; }
|
||||
|
||||
LyricsDisplayType PreferredDisplayType { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services
|
||||
{
|
||||
public class LibreTranslateService : ILibreTranslateService
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public LibreTranslateService(ISettingsService settingsService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
public async Task<string> TranslateAsync(string text, CancellationToken? token)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
throw new ArgumentException("Text and target language must be provided.");
|
||||
}
|
||||
|
||||
string targetLangCode = AppInfo.GetAllTranslationLanguagesInfo()[_settingsService.SelectedTargetLanguageIndex].Code;
|
||||
|
||||
string originalLangCode = await DetectLanguageCode(text);
|
||||
token?.ThrowIfCancellationRequested();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(originalLangCode) || originalLangCode == targetLangCode)
|
||||
{
|
||||
return text; // No translation needed
|
||||
}
|
||||
|
||||
var url = $"{_settingsService.LibreTranslateServer}/translate";
|
||||
var response = await _httpClient.PostAsync(url, new FormUrlEncodedContent(
|
||||
[
|
||||
new("q", text),
|
||||
new("source", originalLangCode),
|
||||
new("target", targetLangCode),
|
||||
]));
|
||||
token?.ThrowIfCancellationRequested();
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
token?.ThrowIfCancellationRequested();
|
||||
|
||||
var result = System.Text.Json.JsonSerializer.Deserialize(json, SourceGenerationContext.Default.TranslateResponse);
|
||||
return result?.TranslatedText ?? string.Empty;
|
||||
}
|
||||
|
||||
private async Task<string> DetectLanguageCode(string text)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
throw new ArgumentException("Text must be provided.");
|
||||
}
|
||||
var url = $"{_settingsService.LibreTranslateServer}/detect";
|
||||
var response = await _httpClient.PostAsync(url, new FormUrlEncodedContent(
|
||||
[
|
||||
new("q", text),
|
||||
]));
|
||||
response.EnsureSuccessStatusCode();
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
var resultList = System.Text.Json.JsonSerializer.Deserialize(json, SourceGenerationContext.Default.ListDetectLanguageResult);
|
||||
return resultList?.OrderByDescending(x => x.Confidence).FirstOrDefault()?.Language ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,13 +22,9 @@ namespace BetterLyrics.WinUI3.Services
|
||||
public class MusicSearchService : IMusicSearchService
|
||||
{
|
||||
private readonly HttpClient _amllTtmlDbHttpClient;
|
||||
|
||||
private readonly HttpClient _lrcLibHttpClient;
|
||||
|
||||
private readonly HttpClient _iTunesHttpClinet;
|
||||
|
||||
private readonly iTunesSearchManager _iTunesSearchManager;
|
||||
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
@@ -44,12 +40,11 @@ namespace BetterLyrics.WinUI3.Services
|
||||
);
|
||||
_amllTtmlDbHttpClient = new();
|
||||
_iTunesHttpClinet = new();
|
||||
_iTunesSearchManager = new();
|
||||
}
|
||||
|
||||
public async Task<bool> DownloadAmllTtmlDbIndexAsync()
|
||||
{
|
||||
const string url = "https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/refs/heads/main/metadata/raw-lyrics-index.jsonl";
|
||||
const string url = "https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/refs/heads/main/metadata/raw-img-index.jsonl";
|
||||
try
|
||||
{
|
||||
using var response = await _amllTtmlDbHttpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
||||
@@ -87,7 +82,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
return "us";
|
||||
}
|
||||
|
||||
public async Task<byte[]> SearchAlbumArtAsync(string title, string artist, string album)
|
||||
public async Task<byte[]?> SearchAlbumArtAsync(string title, string artist, string album)
|
||||
{
|
||||
foreach (var folder in _settingsService.LocalLyricsFolders)
|
||||
{
|
||||
@@ -108,20 +103,62 @@ namespace BetterLyrics.WinUI3.Services
|
||||
}
|
||||
}
|
||||
|
||||
var resultItems = await _iTunesSearchManager.GetAlbumsAsync(album, 1, countryCode: GuessCountryCode(album, artist));
|
||||
var url = resultItems.Albums.Where(al => Normalize(al.ArtistName).Contains(Normalize(artist)))
|
||||
.FirstOrDefault()?.ArtworkUrl100.Replace("100x100bb.jpg", "100000x100000-999.jpg");
|
||||
if (url != null)
|
||||
{
|
||||
return await _iTunesHttpClinet.GetByteArrayAsync(url);
|
||||
}
|
||||
return await SearchiTunesAlbumArtAsync(artist, album);
|
||||
}
|
||||
|
||||
return await ImageHelper.CreateTextPlaceholderBytesAsync($"{artist} - {title}", 400, 400);
|
||||
private async Task<byte[]?> SearchiTunesAlbumArtAsync(string artist, string album)
|
||||
{
|
||||
// Source: https://gist.github.com/mcworkaholic/82fbf203e3f1043bbe534b5b2974c0ce
|
||||
try
|
||||
{
|
||||
string format = ".jpg";
|
||||
var cachedAlbumArt = ReadAlbumArtCache(artist, album, format, AppInfo.iTunesAlbumArtCacheDirectory);
|
||||
|
||||
if (cachedAlbumArt != null)
|
||||
{
|
||||
return cachedAlbumArt;
|
||||
}
|
||||
|
||||
// Build the iTunes API URL
|
||||
string url = $"https://itunes.apple.com/search?term=" + artist + "+" + album + "&country=" + GuessCountryCode(album, artist) + "&entity=album";
|
||||
url.Replace(" ", "-");
|
||||
// Make a request to the API
|
||||
|
||||
HttpResponseMessage response = await _iTunesHttpClinet.GetAsync(url);
|
||||
response.EnsureSuccessStatusCode();
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// Parse the JSON response
|
||||
var data = JsonSerializer.Deserialize(responseBody, Serialization.SourceGenerationContext.Default.JsonElement);
|
||||
|
||||
if (data.TryGetProperty("results", out var results) && results.ValueKind == JsonValueKind.Array && results.GetArrayLength() > 0)
|
||||
{
|
||||
// Get the first result
|
||||
var result = results[0];
|
||||
if (result.TryGetProperty("artworkUrl100", out var artworkUrlProp))
|
||||
{
|
||||
string artworkUrl = artworkUrlProp.GetString()?.Replace("100x100bb.jpg", "1200x1200bb.jpg") ?? string.Empty;
|
||||
var fetched = await _iTunesHttpClinet.GetByteArrayAsync(artworkUrl);
|
||||
|
||||
if (fetched != null && fetched.Length > 0)
|
||||
{
|
||||
// Write to cache
|
||||
WriteAlbumArtCache(artist, album, fetched, format, AppInfo.iTunesAlbumArtCacheDirectory);
|
||||
return fetched;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error searching iTunes album art for {Artist} - {Album}", artist, album);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<string?> SearchLyricsAsync(string title, string artist, string album, double durationMs, CancellationToken token)
|
||||
{
|
||||
_logger.LogInformation("Searching lyrics for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
|
||||
_logger.LogInformation("Searching img for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
|
||||
|
||||
foreach (var provider in _settingsService.LyricsSearchProvidersInfo)
|
||||
{
|
||||
@@ -136,7 +173,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
// Check cache first
|
||||
if (provider.Provider.IsRemote())
|
||||
{
|
||||
cachedLyrics = ReadCache(title, artist, lyricsFormat, provider.Provider.GetCacheDirectory());
|
||||
cachedLyrics = ReadLyricsCache(title, artist, lyricsFormat, provider.Provider.GetCacheDirectory());
|
||||
if (!string.IsNullOrWhiteSpace(cachedLyrics))
|
||||
{
|
||||
return cachedLyrics;
|
||||
@@ -186,7 +223,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
{
|
||||
if (provider.Provider.IsRemote())
|
||||
{
|
||||
WriteCache(title, artist, searchedLyrics, lyricsFormat, provider.Provider.GetCacheDirectory());
|
||||
WriteLyricsCache(title, artist, searchedLyrics, lyricsFormat, provider.Provider.GetCacheDirectory());
|
||||
}
|
||||
|
||||
return searchedLyrics;
|
||||
@@ -274,7 +311,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ReadCache(string title, string artist, LyricsFormat format, string cacheFolderPath)
|
||||
private string? ReadLyricsCache(string title, string artist, LyricsFormat format, string cacheFolderPath)
|
||||
{
|
||||
var safeArtist = SanitizeFileName(artist);
|
||||
var safeTitle = SanitizeFileName(title);
|
||||
@@ -286,6 +323,18 @@ namespace BetterLyrics.WinUI3.Services
|
||||
return null;
|
||||
}
|
||||
|
||||
private byte[]? ReadAlbumArtCache(string album, string artist, string format, string cacheFolderPath)
|
||||
{
|
||||
var safeArtist = SanitizeFileName(artist);
|
||||
var safeAlbum = SanitizeFileName(album);
|
||||
var cacheFilePath = Path.Combine(cacheFolderPath, $"{safeArtist} - {safeAlbum}{format}");
|
||||
if (File.Exists(cacheFilePath))
|
||||
{
|
||||
return File.ReadAllBytes(cacheFilePath);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<string?> SearchAmllTtmlDbAsync(string title, string artist)
|
||||
{
|
||||
// 检索本地 JSONL 索引文件,查找 rawLyricFile
|
||||
@@ -339,7 +388,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
return null;
|
||||
|
||||
// 下载歌词内容
|
||||
var url = $"https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/refs/heads/main/raw-lyrics/{rawLyricFile}";
|
||||
var url = $"https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/refs/heads/main/raw-img/{rawLyricFile}";
|
||||
try
|
||||
{
|
||||
var response = await _amllTtmlDbHttpClient.GetAsync(url);
|
||||
@@ -431,7 +480,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
return null;
|
||||
}
|
||||
|
||||
private void WriteCache(
|
||||
private void WriteLyricsCache(
|
||||
string title,
|
||||
string artist,
|
||||
string lyrics,
|
||||
@@ -447,5 +496,22 @@ namespace BetterLyrics.WinUI3.Services
|
||||
);
|
||||
File.WriteAllText(cacheFilePath, lyrics);
|
||||
}
|
||||
|
||||
private void WriteAlbumArtCache(
|
||||
string album,
|
||||
string artist,
|
||||
byte[] img,
|
||||
string format,
|
||||
string cacheFolderPath
|
||||
)
|
||||
{
|
||||
var safeArtist = SanitizeFileName(artist);
|
||||
var safeAlbum = SanitizeFileName(album);
|
||||
var cacheFilePath = Path.Combine(
|
||||
cacheFolderPath,
|
||||
$"{safeArtist} - {safeAlbum}{format}"
|
||||
);
|
||||
File.WriteAllBytes(cacheFilePath, img);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Threading;
|
||||
using Windows.Graphics.Imaging;
|
||||
using Windows.Media.Control;
|
||||
@@ -65,7 +66,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
MediaManager_OnFocusedSessionChanged(_mediaManager.GetFocusedSession());
|
||||
}
|
||||
|
||||
private async void MediaManager_OnFocusedSessionChanged(MediaManager.MediaSession mediaSession)
|
||||
private void MediaManager_OnFocusedSessionChanged(MediaManager.MediaSession mediaSession)
|
||||
{
|
||||
if (mediaSession == null || !IsMediaSourceEnabled(mediaSession.ControlSession.SourceAppUserModelId))
|
||||
{
|
||||
@@ -73,8 +74,20 @@ namespace BetterLyrics.WinUI3.Services
|
||||
}
|
||||
else
|
||||
{
|
||||
MediaManager_OnAnyMediaPropertyChanged(mediaSession, await mediaSession.ControlSession.TryGetMediaPropertiesAsync());
|
||||
MediaManager_OnAnyPlaybackStateChanged(mediaSession, mediaSession.ControlSession.GetPlaybackInfo());
|
||||
_dispatcherQueue.TryEnqueue(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var props = await mediaSession.ControlSession.TryGetMediaPropertiesAsync();
|
||||
MediaManager_OnAnyMediaPropertyChanged(mediaSession, props);
|
||||
MediaManager_OnAnyPlaybackStateChanged(mediaSession, mediaSession.ControlSession.GetPlaybackInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "TryGetMediaPropertiesAsync failed");
|
||||
SendNullMessages();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,37 +150,49 @@ namespace BetterLyrics.WinUI3.Services
|
||||
SourceAppUserModelId = id,
|
||||
};
|
||||
|
||||
byte[] bytes;
|
||||
byte[]? bytes;
|
||||
|
||||
if (mediaProperties.Thumbnail is IRandomAccessStreamReference streamReference)
|
||||
{
|
||||
bytes = await ImageHelper.ToByteArrayAsync(
|
||||
streamReference
|
||||
);
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes = await _musicSearchService.SearchAlbumArtAsync(
|
||||
songInfo.Title,
|
||||
songInfo.Artist,
|
||||
songInfo.Album
|
||||
);
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
var decoder = await ImageHelper.GetDecoderFromByte(bytes);
|
||||
bytes = await _musicSearchService.SearchAlbumArtAsync(
|
||||
songInfo.Title,
|
||||
songInfo.Artist,
|
||||
songInfo.Album
|
||||
);
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
if (bytes == null)
|
||||
{
|
||||
if (mediaProperties.Thumbnail is IRandomAccessStreamReference streamReference)
|
||||
{
|
||||
bytes = await ImageHelper.ToByteArrayAsync(streamReference);
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes = await ImageHelper.CreateTextPlaceholderBytesAsync($"{songInfo.Artist} - {songInfo.Title}", 400, 400);
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
|
||||
using var stream = new InMemoryRandomAccessStream();
|
||||
await stream.WriteAsync(bytes.AsBuffer());
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var decoder = await BitmapDecoder.CreateAsync(stream);
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
songInfo.AlbumArtSwBitmap?.Dispose();
|
||||
songInfo.AlbumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Premultiplied);
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
songInfo.AlbumArtAccentColor = ImageHelper.GetAccentColorsFromByte(bytes).FirstOrDefault();
|
||||
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.High,
|
||||
() =>
|
||||
{
|
||||
SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(songInfo));
|
||||
});
|
||||
() =>
|
||||
{
|
||||
SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(songInfo));
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
@@ -10,6 +7,9 @@ using BetterLyrics.WinUI3.Serialization;
|
||||
using CommunityToolkit.WinUI.Helpers;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Windows.Storage;
|
||||
using Windows.UI;
|
||||
|
||||
@@ -17,7 +17,9 @@ namespace BetterLyrics.WinUI3.Services
|
||||
{
|
||||
public class SettingsService : ISettingsService
|
||||
{
|
||||
public const string LyricsCustomFontColorKey = "LyricsCustomFontColor";
|
||||
public const string LyricsCustomBgFontColorKey = "LyricsCustomBgFontColor";
|
||||
public const string LyricsCustomFgFontColorKey = "LyricsCustomFgFontColor";
|
||||
public const string LyricsCustomStrokeFontColorKey = "LyricsCustomStrokeFontColor";
|
||||
|
||||
// App behavior
|
||||
|
||||
@@ -50,7 +52,13 @@ namespace BetterLyrics.WinUI3.Services
|
||||
private const string LyricsAlignmentTypeKey = "TextAlignmentType";
|
||||
private const string SongInfoAlignmentTypeKey = "SongInfoAlignmentType";
|
||||
private const string LyricsBlurAmountKey = "LyricsBlurAmount";
|
||||
private const string LyricsFontColorTypeKey = "LyricsFontColorType";
|
||||
|
||||
private const string LyricsBgFontColorTypeKey = "_lyricsBgFontColorType";
|
||||
private const string LyricsFgFontColorTypeKey = "LyricsFgFontColorType";
|
||||
private const string LyricsStrokeFontColorTypeKey = "LyricsStrokeFontColorType";
|
||||
|
||||
private const string LyricsFontStrokeWidthKey = "LyricsFontStrokeWidth";
|
||||
|
||||
private const string LyricsFontSizeKey = "LyricsFontSize";
|
||||
private const string LyricsFontWeightKey = "LyricsFontWeightKey";
|
||||
private const string LyricsGlowEffectScopeKey = "LyricsGlowEffectScope";
|
||||
@@ -60,6 +68,16 @@ namespace BetterLyrics.WinUI3.Services
|
||||
|
||||
private const string MediaSourceProvidersInfoKey = "MediaSourceProvidersInfo";
|
||||
|
||||
private const string IsTranslationEnabledKey = "IsTranslationEnabled";
|
||||
private const string LibreTranslateServerKey = "LibreTranslateServer";
|
||||
private const string SelectedTargetLanguageIndexKey = "SelectedTargetLanguageIndex";
|
||||
|
||||
private const string LyricsBackgroundThemeKey = "LyricsBackgroundTheme";
|
||||
|
||||
private const string IgnoreFullscreenWindowKey = "IgnoreFullscreenWindow";
|
||||
|
||||
private const string PreferredDisplayTypeKey = "PreferredDisplayTypeKey";
|
||||
|
||||
private readonly ApplicationDataContainer _localSettings;
|
||||
|
||||
public SettingsService()
|
||||
@@ -94,15 +112,15 @@ namespace BetterLyrics.WinUI3.Services
|
||||
// App appearance
|
||||
SetDefault(LanguageKey, (int)Language.FollowSystem);
|
||||
|
||||
SetDefault(DesktopWindowHeightKey, 500);
|
||||
SetDefault(DesktopWindowHeightKey, 600);
|
||||
SetDefault(DesktopWindowLeftKey, 200);
|
||||
SetDefault(DesktopWindowTopKey, 200);
|
||||
SetDefault(DesktopWindowWidthKey, 800);
|
||||
SetDefault(DesktopWindowWidthKey, 1200);
|
||||
|
||||
SetDefault(StandardWindowHeightKey, 800);
|
||||
SetDefault(StandardWindowLeftKey, 200);
|
||||
SetDefault(StandardWindowTopKey, 200);
|
||||
SetDefault(StandardWindowWidthKey, 1000);
|
||||
SetDefault(StandardWindowWidthKey, 1600);
|
||||
|
||||
SetDefault(AutoLockOnDesktopModeKey, false);
|
||||
// App behavior
|
||||
@@ -110,22 +128,53 @@ namespace BetterLyrics.WinUI3.Services
|
||||
// Album art
|
||||
SetDefault(IsCoverOverlayEnabledKey, true);
|
||||
SetDefault(IsDynamicCoverOverlayEnabledKey, true);
|
||||
SetDefault(CoverOverlayOpacityKey, 75); // 100 % = 1.0
|
||||
SetDefault(CoverOverlayOpacityKey, 100); // 100 % = 1.0
|
||||
SetDefault(CoverOverlayBlurAmountKey, 200);
|
||||
SetDefault(CoverImageRadiusKey, 24); // 24 %
|
||||
SetDefault(CoverImageRadiusKey, 12); // 12 %
|
||||
// Lyrics
|
||||
SetDefault(LyricsAlignmentTypeKey, (int)TextAlignmentType.Center);
|
||||
SetDefault(SongInfoAlignmentTypeKey, (int)TextAlignmentType.Left);
|
||||
SetDefault(LyricsFontWeightKey, (int)LyricsFontWeight.Bold);
|
||||
SetDefault(LyricsBlurAmountKey, 5);
|
||||
SetDefault(LyricsFontColorTypeKey, (int)LyricsFontColorType.AdaptiveGrayed);
|
||||
SetDefault(LyricsCustomFontColorKey, Colors.White.ToInt());
|
||||
|
||||
SetDefault(LyricsBackgroundThemeKey, (int)ElementTheme.Default);
|
||||
|
||||
SetDefault(LyricsBgFontColorTypeKey, (int)LyricsFontColorType.AdaptiveGrayed);
|
||||
SetDefault(LyricsFgFontColorTypeKey, (int)LyricsFontColorType.AdaptiveGrayed);
|
||||
SetDefault(LyricsStrokeFontColorTypeKey, (int)LyricsFontColorType.AdaptiveGrayed);
|
||||
|
||||
SetDefault(LyricsCustomBgFontColorKey, Colors.White.ToInt());
|
||||
SetDefault(LyricsCustomFgFontColorKey, Colors.White.ToInt());
|
||||
SetDefault(LyricsCustomStrokeFontColorKey, Colors.White.ToInt());
|
||||
|
||||
SetDefault(LyricsFontSizeKey, 28);
|
||||
SetDefault(LyricsLineSpacingFactorKey, 0.5f);
|
||||
SetDefault(LyricsVerticalEdgeOpacityKey, 0);
|
||||
SetDefault(IsLyricsGlowEffectEnabledKey, true);
|
||||
SetDefault(LyricsGlowEffectScopeKey, (int)LineRenderingType.CurrentCharOnly);
|
||||
SetDefault(IsFanLyricsEnabledKey, false);
|
||||
|
||||
SetDefault(LibreTranslateServerKey, "");
|
||||
SetDefault(IsTranslationEnabledKey, false);
|
||||
SetDefault(SelectedTargetLanguageIndexKey, 6);
|
||||
|
||||
SetDefault(LyricsFontStrokeWidthKey, 3);
|
||||
|
||||
SetDefault(IgnoreFullscreenWindowKey, false);
|
||||
|
||||
SetDefault(PreferredDisplayTypeKey, (int)LyricsDisplayType.SplitView);
|
||||
}
|
||||
|
||||
public LyricsDisplayType PreferredDisplayType
|
||||
{
|
||||
get => (LyricsDisplayType)GetValue<int>(PreferredDisplayTypeKey);
|
||||
set => SetValue(PreferredDisplayTypeKey, (int)value);
|
||||
}
|
||||
|
||||
public ElementTheme LyricsBackgroundTheme
|
||||
{
|
||||
get => (ElementTheme)GetValue<int>(LyricsBackgroundThemeKey);
|
||||
set => SetValue(LyricsBackgroundThemeKey, (int)value);
|
||||
}
|
||||
|
||||
public AutoStartWindowType AutoStartWindowType
|
||||
@@ -271,16 +320,46 @@ namespace BetterLyrics.WinUI3.Services
|
||||
set => SetValue(LyricsBlurAmountKey, value);
|
||||
}
|
||||
|
||||
public Color LyricsCustomFontColor
|
||||
public Color LyricsCustomBgFontColor
|
||||
{
|
||||
get => GetValue<int>(LyricsCustomFontColorKey)!.ToColor();
|
||||
set => SetValue(LyricsCustomFontColorKey, value.ToInt());
|
||||
get => GetValue<int>(LyricsCustomBgFontColorKey)!.ToColor();
|
||||
set => SetValue(LyricsCustomBgFontColorKey, value.ToInt());
|
||||
}
|
||||
|
||||
public LyricsFontColorType LyricsFontColorType
|
||||
public Color LyricsCustomFgFontColor
|
||||
{
|
||||
get => (LyricsFontColorType)GetValue<int>(LyricsFontColorTypeKey);
|
||||
set => SetValue(LyricsFontColorTypeKey, (int)value);
|
||||
get => GetValue<int>(LyricsCustomFgFontColorKey)!.ToColor();
|
||||
set => SetValue(LyricsCustomFgFontColorKey, value.ToInt());
|
||||
}
|
||||
|
||||
public Color LyricsCustomStrokeFontColor
|
||||
{
|
||||
get => GetValue<int>(LyricsCustomStrokeFontColorKey)!.ToColor();
|
||||
set => SetValue(LyricsCustomStrokeFontColorKey, value.ToInt());
|
||||
}
|
||||
|
||||
public LyricsFontColorType LyricsBgFontColorType
|
||||
{
|
||||
get => (LyricsFontColorType)GetValue<int>(LyricsBgFontColorTypeKey);
|
||||
set => SetValue(LyricsBgFontColorTypeKey, (int)value);
|
||||
}
|
||||
|
||||
public LyricsFontColorType LyricsFgFontColorType
|
||||
{
|
||||
get => (LyricsFontColorType)GetValue<int>(LyricsFgFontColorTypeKey);
|
||||
set => SetValue(LyricsFgFontColorTypeKey, (int)value);
|
||||
}
|
||||
|
||||
public LyricsFontColorType LyricsStrokeFontColorType
|
||||
{
|
||||
get => (LyricsFontColorType)GetValue<int>(LyricsStrokeFontColorTypeKey);
|
||||
set => SetValue(LyricsStrokeFontColorTypeKey, (int)value);
|
||||
}
|
||||
|
||||
public int LyricsFontStrokeWidth
|
||||
{
|
||||
get => GetValue<int>(LyricsFontStrokeWidthKey);
|
||||
set => SetValue(LyricsFontStrokeWidthKey, value);
|
||||
}
|
||||
|
||||
public int LyricsFontSize
|
||||
@@ -347,6 +426,30 @@ namespace BetterLyrics.WinUI3.Services
|
||||
set => SetValue(LyricsVerticalEdgeOpacityKey, value);
|
||||
}
|
||||
|
||||
public string LibreTranslateServer
|
||||
{
|
||||
get => GetValue<string>(LibreTranslateServerKey)!;
|
||||
set => SetValue(LibreTranslateServerKey, value);
|
||||
}
|
||||
|
||||
public bool IsTranslationEnabled
|
||||
{
|
||||
get => GetValue<bool>(IsTranslationEnabledKey);
|
||||
set => SetValue(IsTranslationEnabledKey, value);
|
||||
}
|
||||
|
||||
public int SelectedTargetLanguageIndex
|
||||
{
|
||||
get => GetValue<int>(SelectedTargetLanguageIndexKey);
|
||||
set => SetValue(SelectedTargetLanguageIndexKey, value);
|
||||
}
|
||||
|
||||
public bool IgnoreFullscreenWindow
|
||||
{
|
||||
get => GetValue<bool>(IgnoreFullscreenWindowKey);
|
||||
set => SetValue(IgnoreFullscreenWindowKey, value);
|
||||
}
|
||||
|
||||
private T? GetValue<T>(string key)
|
||||
{
|
||||
if (_localSettings.Values.TryGetValue(key, out object? value))
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
<value>Add a folder</value>
|
||||
</data>
|
||||
<data name="SettingsPageTheme.Header" xml:space="preserve">
|
||||
<value>Lyrics window theme</value>
|
||||
<value>Lyrics background theme</value>
|
||||
</data>
|
||||
<data name="SettingsPageLanguage.Header" xml:space="preserve">
|
||||
<value>Language</value>
|
||||
@@ -147,6 +147,9 @@
|
||||
<data name="SettingsPageLyricsFontColorAdaptiveColored.Content" xml:space="preserve">
|
||||
<value>Adaptive to lyrics background (Colored)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorAdaptiveColored.Content" xml:space="preserve">
|
||||
<value>Adaptive to lyrics background (Colored)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLight.Content" xml:space="preserve">
|
||||
<value>Light</value>
|
||||
</data>
|
||||
@@ -301,7 +304,7 @@
|
||||
<value>Welcome to BetterLyrics</value>
|
||||
</data>
|
||||
<data name="MainPageWelcomeTeachingTip.Subtitle" xml:space="preserve">
|
||||
<value>Let's setup lyrics database now</value>
|
||||
<value>Hover the mouse over the top or bottom area of the app to display more function options</value>
|
||||
</data>
|
||||
<data name="MainPageNoMusicPlaying.Text" xml:space="preserve">
|
||||
<value>No music playing now</value>
|
||||
@@ -321,12 +324,18 @@
|
||||
<data name="SettingsPageCache.Description" xml:space="preserve">
|
||||
<value>Including log files, network lyrics cache</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColor.Header" xml:space="preserve">
|
||||
<value>Font color</value>
|
||||
<data name="SettingsPageLyricsBgFontColor.Header" xml:space="preserve">
|
||||
<value>Font color (Non-current playback area)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColor.Header" xml:space="preserve">
|
||||
<value>Font color (Current playback area)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColorAdaptiveGrayed.Content" xml:space="preserve">
|
||||
<value>Adaptive to lyrics background (Grayed)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorAdaptiveGrayed.Content" xml:space="preserve">
|
||||
<value>Adaptive to lyrics background (Grayed)</value>
|
||||
</data>
|
||||
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
||||
<value>Album art area style</value>
|
||||
</data>
|
||||
@@ -531,6 +540,9 @@
|
||||
<data name="SettingsPageLyricsFontColorCustom.Content" xml:space="preserve">
|
||||
<value>Custom</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorCustom.Content" xml:space="preserve">
|
||||
<value>Custom</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyrics.Content" xml:space="preserve">
|
||||
<value>Lyrics style and effect</value>
|
||||
</data>
|
||||
@@ -579,4 +591,67 @@
|
||||
<data name="MainPagePositionOffsetSlider.Header" xml:space="preserve">
|
||||
<value>Lyrics timeline offset (ms)</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationConfig.Header" xml:space="preserve">
|
||||
<value>Configure translation services</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateServer.Header" xml:space="preserve">
|
||||
<value>Server address</value>
|
||||
</data>
|
||||
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
||||
<value>Test server</value>
|
||||
</data>
|
||||
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
|
||||
<value>Target language</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationInfo.Header" xml:space="preserve">
|
||||
<value>Translation service powered by LibreTranslate</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationInfoLink.Text" xml:space="preserve">
|
||||
<value>Visit https://github.com/LibreTranslate/LibreTranslate for installation instructions and more information (this software is not affiliated with this translation service in any way)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateTestSuccessInfo" xml:space="preserve">
|
||||
<value>Server test successful</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateTestFailedInfo" xml:space="preserve">
|
||||
<value>Server test failed</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontStrokeWidth.Header" xml:space="preserve">
|
||||
<value>Lyrics stroke width (Desktop mode only)</value>
|
||||
</data>
|
||||
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
||||
<value>Follow system</value>
|
||||
</data>
|
||||
<data name="SettingsPageAutoStart.Header" xml:space="preserve">
|
||||
<value>Automatic startup</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
||||
<value>Lyrics stroke color (Desktop mode only)</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Header" xml:space="preserve">
|
||||
<value>Always stay on top of fullscreen applications</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Description" xml:space="preserve">
|
||||
<value>Force this app to appear on top of full-screen apps when docked or desktop mode is enabled</value>
|
||||
</data>
|
||||
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
||||
<value>More</value>
|
||||
</data>
|
||||
<data name="LyricsPageTimelineOffsetButtonToolTip.Content" xml:space="preserve">
|
||||
<value>Lyrics timeline offset</value>
|
||||
</data>
|
||||
<data name="LyricsPageTranslationButtonToolTip.Content" xml:space="preserve">
|
||||
<value>Translate</value>
|
||||
</data>
|
||||
<data name="LyricsPageDisplayTypeButtonToolTip.Content" xml:space="preserve">
|
||||
<value>Display type</value>
|
||||
</data>
|
||||
<data name="LyricsPageSettingsButtonToolTip.Content" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
<data name="TranslateServerNotSet" xml:space="preserve">
|
||||
<value>Translate server is not set, please configure it in settings first</value>
|
||||
</data>
|
||||
<data name="LyricsPagePositionOffsetHint.Text" xml:space="preserve">
|
||||
<value>Will automatically reset to 0 when switching songs</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -139,7 +139,7 @@
|
||||
<value>フォルダーを追加します</value>
|
||||
</data>
|
||||
<data name="SettingsPageTheme.Header" xml:space="preserve">
|
||||
<value>歌詞ウィンドウのテーマ</value>
|
||||
<value>歌詞の背景テーマ</value>
|
||||
</data>
|
||||
<data name="SettingsPageLanguage.Header" xml:space="preserve">
|
||||
<value>言語</value>
|
||||
@@ -147,6 +147,9 @@
|
||||
<data name="SettingsPageLyricsFontColorAdaptiveColored.Content" xml:space="preserve">
|
||||
<value>歌詞の背景に適応する(色付き)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorAdaptiveColored.Content" xml:space="preserve">
|
||||
<value>歌詞の背景に適応する(色付き)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLight.Content" xml:space="preserve">
|
||||
<value>ライト</value>
|
||||
</data>
|
||||
@@ -301,7 +304,7 @@
|
||||
<value>BetterLyrics へようこそ</value>
|
||||
</data>
|
||||
<data name="MainPageWelcomeTeachingTip.Subtitle" xml:space="preserve">
|
||||
<value>今すぐ歌詞データベースをセットアップしましょう</value>
|
||||
<value>マウスをアプリの上または下部の領域にホバリングして、より多くの機能オプションを表示します</value>
|
||||
</data>
|
||||
<data name="MainPageNoMusicPlaying.Text" xml:space="preserve">
|
||||
<value>今は音楽が再生されていません</value>
|
||||
@@ -321,12 +324,18 @@
|
||||
<data name="SettingsPageCache.Description" xml:space="preserve">
|
||||
<value>ログファイル、ネットワーク歌詞キャッシュを含む</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColor.Header" xml:space="preserve">
|
||||
<value>フォントカラー</value>
|
||||
<data name="SettingsPageLyricsBgFontColor.Header" xml:space="preserve">
|
||||
<value>フォントカラー(非電流再生エリア)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColor.Header" xml:space="preserve">
|
||||
<value>フォントカラー(現在の再生エリア)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColorAdaptiveGrayed.Content" xml:space="preserve">
|
||||
<value>歌詞の背景に適応する(灰色)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorAdaptiveGrayed.Content" xml:space="preserve">
|
||||
<value>歌詞の背景に適応する(灰色)</value>
|
||||
</data>
|
||||
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
||||
<value>アルバムエリアスタイル</value>
|
||||
</data>
|
||||
@@ -531,6 +540,9 @@
|
||||
<data name="SettingsPageLyricsFontColorCustom.Content" xml:space="preserve">
|
||||
<value>カスタマイズ</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorCustom.Content" xml:space="preserve">
|
||||
<value>カスタマイズ</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyrics.Content" xml:space="preserve">
|
||||
<value>歌詞のスタイルと効果</value>
|
||||
</data>
|
||||
@@ -579,4 +591,67 @@
|
||||
<data name="MainPagePositionOffsetSlider.Header" xml:space="preserve">
|
||||
<value>歌詞タイムラインオフセット(ミリ秒)</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationConfig.Header" xml:space="preserve">
|
||||
<value>翻訳サービスを構成します</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateServer.Header" xml:space="preserve">
|
||||
<value>サーバーアドレス</value>
|
||||
</data>
|
||||
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
||||
<value>テストサーバー</value>
|
||||
</data>
|
||||
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
|
||||
<value>ターゲット言語</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationInfo.Header" xml:space="preserve">
|
||||
<value>LibreTranslate を搭載した翻訳サービス</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationInfoLink.Text" xml:space="preserve">
|
||||
<value>https://github.com/LibreTranslate/LibreTranslate にアクセスしてください。</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateTestSuccessInfo" xml:space="preserve">
|
||||
<value>サーバーテストが成功しました</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateTestFailedInfo" xml:space="preserve">
|
||||
<value>サーバーテストに失敗しました</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontStrokeWidth.Header" xml:space="preserve">
|
||||
<value>歌詞ストローク幅(デスクトップモードのみ)</value>
|
||||
</data>
|
||||
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
||||
<value>システムをフォローします</value>
|
||||
</data>
|
||||
<data name="SettingsPageAutoStart.Header" xml:space="preserve">
|
||||
<value>自動起動</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
||||
<value>歌詞ストロークカラー(デスクトップモードのみ)</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Header" xml:space="preserve">
|
||||
<value>常にフルスクリーンアプリケーションを常に把握してください</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Description" xml:space="preserve">
|
||||
<value>このアプリは、ドッキングまたはデスクトップモードが有効になっているときにフルスクリーンアプリの上に表示されます</value>
|
||||
</data>
|
||||
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
||||
<value>もっと</value>
|
||||
</data>
|
||||
<data name="LyricsPageTimelineOffsetButtonToolTip.Content" xml:space="preserve">
|
||||
<value>歌詞タイムラインオフセット</value>
|
||||
</data>
|
||||
<data name="LyricsPageTranslationButtonToolTip.Content" xml:space="preserve">
|
||||
<value>翻訳する</value>
|
||||
</data>
|
||||
<data name="LyricsPageDisplayTypeButtonToolTip.Content" xml:space="preserve">
|
||||
<value>表示タイプ</value>
|
||||
</data>
|
||||
<data name="LyricsPageSettingsButtonToolTip.Content" xml:space="preserve">
|
||||
<value>設定</value>
|
||||
</data>
|
||||
<data name="TranslateServerNotSet" xml:space="preserve">
|
||||
<value>翻訳サーバーは設定されていません。最初に設定で構成してください</value>
|
||||
</data>
|
||||
<data name="LyricsPagePositionOffsetHint.Text" xml:space="preserve">
|
||||
<value>曲を切り替えると、0 に自動的にリセットされます</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -139,7 +139,7 @@
|
||||
<value>폴더를 추가하십시오</value>
|
||||
</data>
|
||||
<data name="SettingsPageTheme.Header" xml:space="preserve">
|
||||
<value>가사 창 테마</value>
|
||||
<value>가사 배경 테마</value>
|
||||
</data>
|
||||
<data name="SettingsPageLanguage.Header" xml:space="preserve">
|
||||
<value>언어</value>
|
||||
@@ -147,6 +147,9 @@
|
||||
<data name="SettingsPageLyricsFontColorAdaptiveColored.Content" xml:space="preserve">
|
||||
<value>가사 배경 (색상)에 적응</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorAdaptiveColored.Content" xml:space="preserve">
|
||||
<value>가사 배경 (색상)에 적응</value>
|
||||
</data>
|
||||
<data name="SettingsPageLight.Content" xml:space="preserve">
|
||||
<value>빛</value>
|
||||
</data>
|
||||
@@ -301,7 +304,7 @@
|
||||
<value>Betterlyrics에 오신 것을 환영합니다</value>
|
||||
</data>
|
||||
<data name="MainPageWelcomeTeachingTip.Subtitle" xml:space="preserve">
|
||||
<value>지금 가사 데이터베이스를 설정합시다</value>
|
||||
<value>더 많은 기능 옵션을 표시하려면 앱의 상단 또는 하단 영역 위로 마우스를 가져옵니다.</value>
|
||||
</data>
|
||||
<data name="MainPageNoMusicPlaying.Text" xml:space="preserve">
|
||||
<value>지금 음악이 재생되지 않습니다</value>
|
||||
@@ -321,12 +324,18 @@
|
||||
<data name="SettingsPageCache.Description" xml:space="preserve">
|
||||
<value>로그 파일, 네트워크 가사 캐시 포함</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColor.Header" xml:space="preserve">
|
||||
<value>글꼴 색상</value>
|
||||
<data name="SettingsPageLyricsBgFontColor.Header" xml:space="preserve">
|
||||
<value>글꼴 색상 (비 전류 재생 영역)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColor.Header" xml:space="preserve">
|
||||
<value>글꼴 색상 (현재 재생 영역)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColorAdaptiveGrayed.Content" xml:space="preserve">
|
||||
<value>가사 배경 (회색)에 적응</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorAdaptiveGrayed.Content" xml:space="preserve">
|
||||
<value>가사 배경 (회색)에 적응</value>
|
||||
</data>
|
||||
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
||||
<value>앨범 영역 스타일</value>
|
||||
</data>
|
||||
@@ -531,6 +540,9 @@
|
||||
<data name="SettingsPageLyricsFontColorCustom.Content" xml:space="preserve">
|
||||
<value>사용자 정의하십시오</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorCustom.Content" xml:space="preserve">
|
||||
<value>사용자 정의하십시오</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyrics.Content" xml:space="preserve">
|
||||
<value>가사 스타일과 효과</value>
|
||||
</data>
|
||||
@@ -579,4 +591,67 @@
|
||||
<data name="MainPagePositionOffsetSlider.Header" xml:space="preserve">
|
||||
<value>가사 타임 라인 오프셋 (밀리초)</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationConfig.Header" xml:space="preserve">
|
||||
<value>번역 서비스를 구성하십시오</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateServer.Header" xml:space="preserve">
|
||||
<value>서버 주소</value>
|
||||
</data>
|
||||
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
||||
<value>테스트 서버</value>
|
||||
</data>
|
||||
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
|
||||
<value>대상 언어</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationInfo.Header" xml:space="preserve">
|
||||
<value>LibreTranslate 가 구동하는 번역 서비스</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationInfoLink.Text" xml:space="preserve">
|
||||
<value>설치 지침 및 자세한 정보는 https://github.com/LibreTranslate/LibreTranslate 를 방문하십시오 (이 소프트웨어는이 번역 서비스와 제휴하지 않습니다).</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateTestSuccessInfo" xml:space="preserve">
|
||||
<value>서버 테스트 성공</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateTestFailedInfo" xml:space="preserve">
|
||||
<value>서버 테스트가 실패했습니다</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontStrokeWidth.Header" xml:space="preserve">
|
||||
<value>가사 뇌졸중 너비 (데스크탑 모드 만)</value>
|
||||
</data>
|
||||
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
||||
<value>시스템을 따르십시오</value>
|
||||
</data>
|
||||
<data name="SettingsPageAutoStart.Header" xml:space="preserve">
|
||||
<value>자동 시작</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
||||
<value>가사 스트로크 컬러 (데스크탑 모드 만)</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Header" xml:space="preserve">
|
||||
<value>항상 전체 화면 응용 프로그램 위에 머물러 있습니다</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Description" xml:space="preserve">
|
||||
<value>도킹 또는 데스크탑 모드가 활성화 될 때이 앱이 전체 화면 앱 위에 나타나도록 강요</value>
|
||||
</data>
|
||||
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
||||
<value>더</value>
|
||||
</data>
|
||||
<data name="LyricsPageTimelineOffsetButtonToolTip.Content" xml:space="preserve">
|
||||
<value>가사 타임 라인 오프셋</value>
|
||||
</data>
|
||||
<data name="LyricsPageTranslationButtonToolTip.Content" xml:space="preserve">
|
||||
<value>번역하다</value>
|
||||
</data>
|
||||
<data name="LyricsPageDisplayTypeButtonToolTip.Content" xml:space="preserve">
|
||||
<value>디스플레이 유형</value>
|
||||
</data>
|
||||
<data name="LyricsPageSettingsButtonToolTip.Content" xml:space="preserve">
|
||||
<value>설정</value>
|
||||
</data>
|
||||
<data name="TranslateServerNotSet" xml:space="preserve">
|
||||
<value>번역 서버가 설정되지 않았습니다. 먼저 설정으로 구성하십시오.</value>
|
||||
</data>
|
||||
<data name="LyricsPagePositionOffsetHint.Text" xml:space="preserve">
|
||||
<value>노래를 전환 할 때 자동으로 0 으로 재설정됩니다</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -139,7 +139,7 @@
|
||||
<value>添加文件夹</value>
|
||||
</data>
|
||||
<data name="SettingsPageTheme.Header" xml:space="preserve">
|
||||
<value>歌词窗口主题</value>
|
||||
<value>歌词背景主题</value>
|
||||
</data>
|
||||
<data name="SettingsPageLanguage.Header" xml:space="preserve">
|
||||
<value>语言</value>
|
||||
@@ -147,6 +147,9 @@
|
||||
<data name="SettingsPageLyricsFontColorAdaptiveColored.Content" xml:space="preserve">
|
||||
<value>适应歌词背景(彩色)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorAdaptiveColored.Content" xml:space="preserve">
|
||||
<value>适应歌词背景(彩色)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLight.Content" xml:space="preserve">
|
||||
<value>浅色</value>
|
||||
</data>
|
||||
@@ -301,7 +304,7 @@
|
||||
<value>欢迎使用 BetterLyrics</value>
|
||||
</data>
|
||||
<data name="MainPageWelcomeTeachingTip.Subtitle" xml:space="preserve">
|
||||
<value>现在就来初始化歌词数据库吧</value>
|
||||
<value>将鼠标悬停在应用程序的顶部或底部区域以显示更多功能选项</value>
|
||||
</data>
|
||||
<data name="MainPageNoMusicPlaying.Text" xml:space="preserve">
|
||||
<value>当前没有正在播放的音乐</value>
|
||||
@@ -321,12 +324,18 @@
|
||||
<data name="SettingsPageCache.Description" xml:space="preserve">
|
||||
<value>包括日志文件,网络歌词缓存</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColor.Header" xml:space="preserve">
|
||||
<value>字体颜色</value>
|
||||
<data name="SettingsPageLyricsBgFontColor.Header" xml:space="preserve">
|
||||
<value>字体颜色(非当前播放区域)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColor.Header" xml:space="preserve">
|
||||
<value>字体颜色(当前播放区域)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColorAdaptiveGrayed.Content" xml:space="preserve">
|
||||
<value>适应歌词背景(灰色)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorAdaptiveGrayed.Content" xml:space="preserve">
|
||||
<value>适应歌词背景(灰色)</value>
|
||||
</data>
|
||||
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
||||
<value>专辑区域样式</value>
|
||||
</data>
|
||||
@@ -531,6 +540,9 @@
|
||||
<data name="SettingsPageLyricsFontColorCustom.Content" xml:space="preserve">
|
||||
<value>自定义</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorCustom.Content" xml:space="preserve">
|
||||
<value>自定义</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyrics.Content" xml:space="preserve">
|
||||
<value>歌词样式与动效</value>
|
||||
</data>
|
||||
@@ -579,4 +591,67 @@
|
||||
<data name="MainPagePositionOffsetSlider.Header" xml:space="preserve">
|
||||
<value>歌词时间轴偏移(毫秒)</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationConfig.Header" xml:space="preserve">
|
||||
<value>配置翻译服务</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateServer.Header" xml:space="preserve">
|
||||
<value>服务器地址</value>
|
||||
</data>
|
||||
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
||||
<value>测试服务器</value>
|
||||
</data>
|
||||
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
|
||||
<value>目标语言</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationInfo.Header" xml:space="preserve">
|
||||
<value>翻译服务由 LibreTranslate 驱动</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationInfoLink.Text" xml:space="preserve">
|
||||
<value>访问 https://github.com/LibreTranslate/LibreTranslate 获取安装教程及更多信息(本软件与该翻译服务无任何联系)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateTestSuccessInfo" xml:space="preserve">
|
||||
<value>服务器测试成功</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateTestFailedInfo" xml:space="preserve">
|
||||
<value>服务器测试失败</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontStrokeWidth.Header" xml:space="preserve">
|
||||
<value>歌词描边宽度(仅桌面模式)</value>
|
||||
</data>
|
||||
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
||||
<value>跟随系统</value>
|
||||
</data>
|
||||
<data name="SettingsPageAutoStart.Header" xml:space="preserve">
|
||||
<value>自动启动</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
||||
<value>歌词描边颜色(仅桌面模式)</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Header" xml:space="preserve">
|
||||
<value>始终显示在全屏应用上方</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Description" xml:space="preserve">
|
||||
<value>当启用停靠模式或桌面模式时强制将本应用显示在全屏应用的上方</value>
|
||||
</data>
|
||||
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
||||
<value>更多</value>
|
||||
</data>
|
||||
<data name="LyricsPageTimelineOffsetButtonToolTip.Content" xml:space="preserve">
|
||||
<value>歌词时间偏移</value>
|
||||
</data>
|
||||
<data name="LyricsPageTranslationButtonToolTip.Content" xml:space="preserve">
|
||||
<value>翻译</value>
|
||||
</data>
|
||||
<data name="LyricsPageDisplayTypeButtonToolTip.Content" xml:space="preserve">
|
||||
<value>显示类型</value>
|
||||
</data>
|
||||
<data name="LyricsPageSettingsButtonToolTip.Content" xml:space="preserve">
|
||||
<value>设置</value>
|
||||
</data>
|
||||
<data name="TranslateServerNotSet" xml:space="preserve">
|
||||
<value>未设置翻译服务器,请先在设置中进行配置</value>
|
||||
</data>
|
||||
<data name="LyricsPagePositionOffsetHint.Text" xml:space="preserve">
|
||||
<value>切换歌曲时将自动重置为 0</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -139,7 +139,7 @@
|
||||
<value>新增資料夾</value>
|
||||
</data>
|
||||
<data name="SettingsPageTheme.Header" xml:space="preserve">
|
||||
<value>歌詞窗口主題</value>
|
||||
<value>歌詞背景主題</value>
|
||||
</data>
|
||||
<data name="SettingsPageLanguage.Header" xml:space="preserve">
|
||||
<value>語言</value>
|
||||
@@ -147,6 +147,9 @@
|
||||
<data name="SettingsPageLyricsFontColorAdaptiveColored.Content" xml:space="preserve">
|
||||
<value>適應歌詞背景(彩色)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorAdaptiveColored.Content" xml:space="preserve">
|
||||
<value>適應歌詞背景(彩色)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLight.Content" xml:space="preserve">
|
||||
<value>淺色</value>
|
||||
</data>
|
||||
@@ -301,7 +304,7 @@
|
||||
<value>歡迎使用 BetterLyrics</value>
|
||||
</data>
|
||||
<data name="MainPageWelcomeTeachingTip.Subtitle" xml:space="preserve">
|
||||
<value>現在就來初始化歌詞資料庫吧</value>
|
||||
<value>將鼠標懸停在應用程序的頂部或底部區域以顯示更多功能選項</value>
|
||||
</data>
|
||||
<data name="MainPageNoMusicPlaying.Text" xml:space="preserve">
|
||||
<value>目前沒有正在播放的音樂</value>
|
||||
@@ -321,12 +324,18 @@
|
||||
<data name="SettingsPageCache.Description" xml:space="preserve">
|
||||
<value>包括日誌文件,網絡歌詞緩存</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColor.Header" xml:space="preserve">
|
||||
<value>字體顏色</value>
|
||||
<data name="SettingsPageLyricsBgFontColor.Header" xml:space="preserve">
|
||||
<value>字體顏色(非當前播放區域)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColor.Header" xml:space="preserve">
|
||||
<value>字體顏色(當前播放區域)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColorAdaptiveGrayed.Content" xml:space="preserve">
|
||||
<value>適應歌詞背景(灰色)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorAdaptiveGrayed.Content" xml:space="preserve">
|
||||
<value>適應歌詞背景(灰色)</value>
|
||||
</data>
|
||||
<data name="SettingsPageAlbumStyle.Content" xml:space="preserve">
|
||||
<value>专辑区域样式</value>
|
||||
</data>
|
||||
@@ -531,6 +540,9 @@
|
||||
<data name="SettingsPageLyricsFontColorCustom.Content" xml:space="preserve">
|
||||
<value>自定義</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFgFontColorCustom.Content" xml:space="preserve">
|
||||
<value>自定義</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyrics.Content" xml:space="preserve">
|
||||
<value>歌詞樣式與動效</value>
|
||||
</data>
|
||||
@@ -579,4 +591,67 @@
|
||||
<data name="MainPagePositionOffsetSlider.Header" xml:space="preserve">
|
||||
<value>歌詞時間軸偏移(毫秒)</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationConfig.Header" xml:space="preserve">
|
||||
<value>配置翻譯服務</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateServer.Header" xml:space="preserve">
|
||||
<value>服務器地址</value>
|
||||
</data>
|
||||
<data name="SettingsPageServerTestButton.Content" xml:space="preserve">
|
||||
<value>測試服務器</value>
|
||||
</data>
|
||||
<data name="SettingsPageTargetLanguage.Header" xml:space="preserve">
|
||||
<value>目標語言</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationInfo.Header" xml:space="preserve">
|
||||
<value>翻译服务由 LibreTranslate 驱动</value>
|
||||
</data>
|
||||
<data name="SettingsPageTranslationInfoLink.Text" xml:space="preserve">
|
||||
<value>造訪 https://github.com/LibreTranslate/LibreTranslate 以取得安裝教學及更多資訊(本軟體與此翻譯服務無任何關聯)</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateTestSuccessInfo" xml:space="preserve">
|
||||
<value>服務器測試成功</value>
|
||||
</data>
|
||||
<data name="SettingsPageLibreTranslateTestFailedInfo" xml:space="preserve">
|
||||
<value>服務器測試失敗</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontStrokeWidth.Header" xml:space="preserve">
|
||||
<value>歌詞描邊寬度(僅桌面模式)</value>
|
||||
</data>
|
||||
<data name="SettingsPageFollowSystem.Content" xml:space="preserve">
|
||||
<value>跟随系统</value>
|
||||
</data>
|
||||
<data name="SettingsPageAutoStart.Header" xml:space="preserve">
|
||||
<value>自動啟動</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsStrokeFontColor.Header" xml:space="preserve">
|
||||
<value>歌词描边颜色(仅桌面模式)</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Header" xml:space="preserve">
|
||||
<value>始終顯示在全螢幕應用程式上方</value>
|
||||
</data>
|
||||
<data name="SettingsPageIgnoreFullscreenWindow.Description" xml:space="preserve">
|
||||
<value>啟用停靠模式或桌面模式時強制將本應用程式顯示在全螢幕應用程式的上方</value>
|
||||
</data>
|
||||
<data name="HostWindowMoreButtonToolTip.Content" xml:space="preserve">
|
||||
<value>更多</value>
|
||||
</data>
|
||||
<data name="LyricsPageTimelineOffsetButtonToolTip.Content" xml:space="preserve">
|
||||
<value>歌詞時間偏移</value>
|
||||
</data>
|
||||
<data name="LyricsPageTranslationButtonToolTip.Content" xml:space="preserve">
|
||||
<value>翻譯</value>
|
||||
</data>
|
||||
<data name="LyricsPageDisplayTypeButtonToolTip.Content" xml:space="preserve">
|
||||
<value>顯示類型</value>
|
||||
</data>
|
||||
<data name="LyricsPageSettingsButtonToolTip.Content" xml:space="preserve">
|
||||
<value>設定</value>
|
||||
</data>
|
||||
<data name="TranslateServerNotSet" xml:space="preserve">
|
||||
<value>未設定翻譯伺服器,請先在設定中進行配置</value>
|
||||
</data>
|
||||
<data name="LyricsPagePositionOffsetHint.Text" xml:space="preserve">
|
||||
<value>將在切換歌曲時自動重設為 0</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -24,6 +24,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
public LyricsPageViewModel(ISettingsService settingsService, IPlaybackService playbackService) : base(settingsService)
|
||||
{
|
||||
LyricsFontSize = _settingsService.LyricsFontSize;
|
||||
IsTranslationEnabled = _settingsService.IsTranslationEnabled;
|
||||
PreferredDisplayType = _settingsService.PreferredDisplayType;
|
||||
|
||||
_playbackService = playbackService;
|
||||
_playbackService.SongInfoChanged += PlaybackService_SongInfoChanged;
|
||||
@@ -56,7 +58,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
public partial int LyricsFontSize { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial LyricsDisplayType? PreferredDisplayType { get; set; } = LyricsDisplayType.SplitView;
|
||||
public partial LyricsDisplayType PreferredDisplayType { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial SongInfo? SongInfo { get; set; } = null;
|
||||
@@ -69,6 +71,16 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial bool IsTranslationEnabled { get; set; } = false;
|
||||
|
||||
partial void OnIsTranslationEnabledChanged(bool value)
|
||||
{
|
||||
_settingsService.IsTranslationEnabled = value;
|
||||
}
|
||||
|
||||
partial void OnPreferredDisplayTypeChanged(LyricsDisplayType value)
|
||||
{
|
||||
_settingsService.PreferredDisplayType = value;
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<bool> message)
|
||||
{
|
||||
if (message.Sender is LyricsWindowViewModel)
|
||||
@@ -112,7 +124,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
else
|
||||
{
|
||||
PreferredDisplayType = _preferredDisplayTypeBeforeSwitchToNonStandardMode;
|
||||
PreferredDisplayType = _preferredDisplayTypeBeforeSwitchToNonStandardMode ?? LyricsDisplayType.SplitView;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ using Microsoft.Graphics.Canvas.Text;
|
||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Text;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -32,16 +33,22 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
DrawBlurredLyrics(control, blurredLyricsDs);
|
||||
}
|
||||
|
||||
if (_lastAlbumArtSwBitmap != null && _lastAlbumArtCanvasBitmap == null)
|
||||
{
|
||||
_lastAlbumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _lastAlbumArtSwBitmap);
|
||||
}
|
||||
if (_albumArtSwBitmap != null && _albumArtCanvasBitmap == null)
|
||||
{
|
||||
_albumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _albumArtSwBitmap);
|
||||
}
|
||||
|
||||
using var combined = new CanvasCommandList(control);
|
||||
using var combinedDs = combined.CreateDrawingSession();
|
||||
|
||||
DrawAlbumArtBackground(control, combinedDs);
|
||||
|
||||
if (_isDockMode)
|
||||
{
|
||||
DrawImmersiveBackground(control, combinedDs);
|
||||
}
|
||||
|
||||
combinedDs.DrawImage(blurredLyrics);
|
||||
|
||||
if (_isDesktopMode)
|
||||
@@ -54,15 +61,13 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
|
||||
DrawAlbumArt(control, ds);
|
||||
|
||||
DrawTitleAndArtist(control, ds);
|
||||
|
||||
if (_isDebugOverlayEnabled)
|
||||
{
|
||||
var currentPlayingLineIndex = GetCurrentPlayingLineIndex();
|
||||
var currentPlayingLine = _multiLangLyrics
|
||||
.SafeGet(_langIndex)
|
||||
?.SafeGet(currentPlayingLineIndex);
|
||||
?.SafeGet(_playingLineIndex);
|
||||
|
||||
if (currentPlayingLine != null)
|
||||
{
|
||||
@@ -73,36 +78,35 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
out float charProgress
|
||||
);
|
||||
|
||||
ds.DrawText(
|
||||
$"[DEBUG]\n" +
|
||||
$"Cur playing {currentPlayingLineIndex}, char start idx {charStartIndex}, length {charLength}, prog {charProgress}\n" +
|
||||
$"Visible lines [{_startVisibleLineIndex}, {_endVisibleLineIndex}]\n" +
|
||||
$"Cur time {_totalTime + _positionOffset}\n" +
|
||||
$"Lang size {_multiLangLyrics.Count}\n" +
|
||||
$"Song duration {TimeSpan.FromMilliseconds(SongInfo?.DurationMs ?? 0)}",
|
||||
new Vector2(10, 10),
|
||||
ThemeTypeSent == Microsoft.UI.Xaml.ElementTheme.Light ? Colors.Black : Colors.White
|
||||
);
|
||||
//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 {_multiLangLyrics.Count}\n" +
|
||||
// $"Song duration {TimeSpan.FromMilliseconds(SongInfo?.DurationMs ?? 0)}",
|
||||
// new Vector2(10, 10),
|
||||
// ThemeTypeSent == Microsoft.UI.Xaml.ElementTheme.Light ? Colors.Black : Colors.White
|
||||
//);
|
||||
|
||||
//for (int i = _startVisibleLineIndex; i <= _endVisibleLineIndex; i++)
|
||||
//{
|
||||
// LyricsLine? line = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(i);
|
||||
// if (line != null)
|
||||
// {
|
||||
// ds.DrawText(
|
||||
// $"[{i}] {line.Text} {line.ScaleTransition.Value}",
|
||||
// new Vector2(10, 30 + (i - _startVisibleLineIndex) * 20),
|
||||
// ThemeTypeSent == Microsoft.UI.Xaml.ElementTheme.Light ? Colors.Black : Colors.White
|
||||
// );
|
||||
// }
|
||||
//}
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBackgroundImgae(ICanvasAnimatedControl control, CanvasDrawingSession ds, SoftwareBitmap swBitmap, float opacity)
|
||||
private void DrawBackgroundImgae(ICanvasAnimatedControl control, CanvasDrawingSession ds, CanvasBitmap canvasBitmap, float opacity)
|
||||
{
|
||||
using var canvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, swBitmap);
|
||||
float imageWidth = (float)canvasBitmap.Size.Width;
|
||||
float imageHeight = (float)canvasBitmap.Size.Height;
|
||||
|
||||
@@ -111,26 +115,40 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
float x = _canvasWidth / 2 - imageWidth * scaleFactor / 2;
|
||||
float y = _canvasHeight / 2 - imageHeight * scaleFactor / 2;
|
||||
|
||||
// Source: https://zhuanlan.zhihu.com/p/37178216
|
||||
float bright = _lyricsBgBrightnessTransition.Value / 1f * 2f; // 明度参数,范围在0.0f到2.0f之间
|
||||
|
||||
float whiteX = Math.Min(2 - bright, 1);
|
||||
float whiteY = 1f;
|
||||
float blackX = Math.Max(1 - bright, 0);
|
||||
float blackY = 0f;
|
||||
|
||||
ds.DrawImage(new OpacityEffect
|
||||
{
|
||||
Source = new ScaleEffect
|
||||
Source = new BrightnessEffect
|
||||
{
|
||||
Scale = new Vector2(scaleFactor),
|
||||
Source = canvasBitmap,
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
private void DrawForegroundImgae(ICanvasAnimatedControl control, CanvasDrawingSession ds, SoftwareBitmap swBitmap, float opacity)
|
||||
private void DrawForegroundImgae(ICanvasAnimatedControl control, CanvasDrawingSession ds, CanvasBitmap canvasBitmap, float opacity)
|
||||
{
|
||||
using var canvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, swBitmap);
|
||||
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.1f) return;
|
||||
if (scaleFactor < 0.01f) return;
|
||||
|
||||
float cornerRadius = _albumArtCornerRadius / 100f * _albumArtSize / 2;
|
||||
|
||||
@@ -161,16 +179,16 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
ds.Transform = Matrix3x2.CreateRotation(_rotateAngle, control.Size.ToVector2() * 0.5f);
|
||||
|
||||
var overlappedCovers = new CanvasCommandList(control.Device);
|
||||
using var overlappedCovers = new CanvasCommandList(control.Device);
|
||||
using var overlappedCoversDs = overlappedCovers.CreateDrawingSession();
|
||||
|
||||
if (_lastAlbumArtSwBitmap != null)
|
||||
if (_lastAlbumArtCanvasBitmap != null)
|
||||
{
|
||||
DrawBackgroundImgae(control, overlappedCoversDs, _lastAlbumArtSwBitmap, 1 - _albumArtBgTransition.Value);
|
||||
DrawBackgroundImgae(control, overlappedCoversDs, _lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
||||
}
|
||||
if (_albumArtSwBitmap != null)
|
||||
if (_albumArtCanvasBitmap != null)
|
||||
{
|
||||
DrawBackgroundImgae(control, overlappedCoversDs, _albumArtSwBitmap, _albumArtBgTransition.Value);
|
||||
DrawBackgroundImgae(control, overlappedCoversDs, _albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
||||
}
|
||||
|
||||
using var coverOverlayEffect = new OpacityEffect
|
||||
@@ -191,13 +209,13 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
using var albumArt = new CanvasCommandList(control.Device);
|
||||
using var albumArtDs = albumArt.CreateDrawingSession();
|
||||
if (_albumArtSwBitmap != null)
|
||||
if (_albumArtCanvasBitmap != null)
|
||||
{
|
||||
DrawForegroundImgae(control, albumArtDs, _albumArtSwBitmap, _albumArtBgTransition.Value);
|
||||
DrawForegroundImgae(control, albumArtDs, _albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
||||
}
|
||||
if (_lastAlbumArtSwBitmap != null)
|
||||
if (_lastAlbumArtCanvasBitmap != null)
|
||||
{
|
||||
DrawForegroundImgae(control, albumArtDs, _lastAlbumArtSwBitmap, 1 - _albumArtBgTransition.Value);
|
||||
DrawForegroundImgae(control, albumArtDs, _lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
||||
}
|
||||
|
||||
using var opacity = new CanvasCommandList(control.Device);
|
||||
@@ -242,20 +260,18 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
ds.DrawTextLayout(
|
||||
titleLayout,
|
||||
new Vector2(_albumArtXTransition.Value, _titleY),
|
||||
_fontColor.WithAlpha((byte)(_albumArtOpacityTransition.Value * 255 * opacity)));
|
||||
_bgFontColor.WithAlpha((byte)(_albumArtOpacityTransition.Value * 255 * opacity)));
|
||||
ds.DrawTextLayout(
|
||||
artistLayout,
|
||||
new Vector2(_albumArtXTransition.Value, _titleY + (float)titleLayout.LayoutBounds.Height),
|
||||
_fontColor.WithAlpha((byte)(_albumArtOpacityTransition.Value * 128 * opacity)));
|
||||
_bgFontColor.WithAlpha((byte)(_albumArtOpacityTransition.Value * 128 * opacity)));
|
||||
}
|
||||
|
||||
private void DrawBlurredLyrics(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
||||
{
|
||||
var currentPlayingLineIndex = GetCurrentPlayingLineIndex();
|
||||
|
||||
var currentPlayingLine = _multiLangLyrics
|
||||
.SafeGet(_langIndex)
|
||||
?.SafeGet(currentPlayingLineIndex);
|
||||
?.SafeGet(_playingLineIndex);
|
||||
|
||||
if (currentPlayingLine == null)
|
||||
{
|
||||
@@ -314,157 +330,176 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
* Matrix3x2.CreateRotation(line.AngleTransition.Value, currentPlayingLine.Position)
|
||||
* Matrix3x2.CreateTranslation(_lyricsXTransition.Value, _canvasYScrollTransition.Value + _canvasHeight / 2);
|
||||
|
||||
// Create the original lyrics line
|
||||
using var lyrics = new CanvasCommandList(control.Device);
|
||||
using var lyricsDs = lyrics.CreateDrawingSession();
|
||||
lyricsDs.DrawTextLayout(textLayout, position, _fontColor);
|
||||
// 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); // 前景填充
|
||||
}
|
||||
|
||||
// Mock gradient blurred lyrics layer
|
||||
// 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层
|
||||
// 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层(背景歌词层次)
|
||||
// Current line will not be blurred
|
||||
ds.DrawImage(
|
||||
new GaussianBlurEffect
|
||||
{
|
||||
Source = new OpacityEffect { Source = lyrics, Opacity = line.OpacityTransition.Value * _lyricsOpacityTransition.Value },
|
||||
Source = new OpacityEffect { Source = bgLyrics, Opacity = line.OpacityTransition.Value * _lyricsOpacityTransition.Value },
|
||||
BlurAmount = line.BlurAmountTransition.Value,
|
||||
Optimization = EffectOptimization.Quality,
|
||||
BorderMode = EffectBorderMode.Soft,
|
||||
}
|
||||
);
|
||||
|
||||
// 再叠加当前行歌词层
|
||||
using var mask = new CanvasCommandList(control.Device);
|
||||
using var maskDs = mask.CreateDrawingSession();
|
||||
|
||||
using var highlightMask = new CanvasCommandList(control.Device);
|
||||
using var highlightMaskDs = highlightMask.CreateDrawingSession();
|
||||
|
||||
if (i == currentPlayingLineIndex)
|
||||
if (line.HighlightOpacityTransition.Value != 0)
|
||||
{
|
||||
GetLinePlayingProgress(
|
||||
line,
|
||||
out int charStartIndex,
|
||||
out int charLength,
|
||||
out float charProgress
|
||||
);
|
||||
var regions = textLayout.GetCharacterRegions(0, charStartIndex);
|
||||
var highlightRegion = textLayout
|
||||
.GetCharacterRegions(charStartIndex, charLength)
|
||||
.FirstOrDefault();
|
||||
if (regions.Length > 0)
|
||||
// 再叠加高亮行歌词层(前景歌词层)
|
||||
using var mask = new CanvasCommandList(control.Device);
|
||||
using var maskDs = mask.CreateDrawingSession();
|
||||
|
||||
using var highlightMask = new CanvasCommandList(control.Device);
|
||||
using var highlightMaskDs = highlightMask.CreateDrawingSession();
|
||||
|
||||
if (i == _playingLineIndex)
|
||||
{
|
||||
// Draw the mask for the current line
|
||||
for (int j = 0; j < regions.Length; j++)
|
||||
GetLinePlayingProgress(
|
||||
line,
|
||||
out int charStartIndex,
|
||||
out int charLength,
|
||||
out float charProgress
|
||||
);
|
||||
var regions = textLayout.GetCharacterRegions(0, charStartIndex);
|
||||
var highlightRegion = textLayout
|
||||
.GetCharacterRegions(charStartIndex, charLength)
|
||||
.FirstOrDefault();
|
||||
if (regions.Length > 0)
|
||||
{
|
||||
var region = regions[j];
|
||||
var rect = new Rect(
|
||||
region.LayoutBounds.X,
|
||||
region.LayoutBounds.Y + position.Y,
|
||||
region.LayoutBounds.Width,
|
||||
region.LayoutBounds.Height
|
||||
);
|
||||
maskDs.FillRectangle(rect, Colors.Black);
|
||||
}
|
||||
}
|
||||
|
||||
float highlightTotalWidth = (float)highlightRegion.LayoutBounds.Width;
|
||||
// Draw the highlight for the current character
|
||||
float highlightWidth = highlightTotalWidth * charProgress;
|
||||
|
||||
float fadingWidth = (float)highlightRegion.LayoutBounds.Height / 2;
|
||||
|
||||
// Rects
|
||||
var highlightRect = new Rect(
|
||||
highlightRegion.LayoutBounds.X,
|
||||
highlightRegion.LayoutBounds.Y + position.Y,
|
||||
highlightWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
|
||||
var fadeInRect = new Rect(
|
||||
highlightRect.Right - fadingWidth,
|
||||
highlightRegion.LayoutBounds.Y + position.Y,
|
||||
fadingWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
var fadeOutRect = new Rect(
|
||||
highlightRect.Right,
|
||||
highlightRegion.LayoutBounds.Y + position.Y,
|
||||
fadingWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
|
||||
// Brushes
|
||||
using var fadeInBrush = GetHorizontalFillBrush(
|
||||
control,
|
||||
[(0f, 0f), (1f, 1f)],
|
||||
(float)highlightRect.Right - fadingWidth,
|
||||
fadingWidth
|
||||
);
|
||||
using var fadeOutBrush = GetHorizontalFillBrush(
|
||||
control,
|
||||
[(0f, 1f), (1f, 0f)],
|
||||
(float)highlightRect.Right,
|
||||
fadingWidth
|
||||
);
|
||||
|
||||
maskDs.FillRectangle(highlightRect, Colors.White);
|
||||
maskDs.FillRectangle(fadeOutRect, fadeOutBrush);
|
||||
|
||||
highlightMaskDs.FillRectangle(fadeInRect, fadeInBrush);
|
||||
highlightMaskDs.FillRectangle(fadeOutRect, fadeOutBrush);
|
||||
}
|
||||
else
|
||||
{
|
||||
float height = 0f;
|
||||
var regions = textLayout.GetCharacterRegions(0, string.Join("", line.CharTimings.Select(x => x.Text)).Length);
|
||||
if (regions.Length > 0)
|
||||
{
|
||||
height = (float)regions[^1].LayoutBounds.Bottom - (float)regions[0].LayoutBounds.Top;
|
||||
}
|
||||
|
||||
maskDs.FillRectangle(
|
||||
new Rect(
|
||||
textLayout.LayoutBounds.X,
|
||||
position.Y,
|
||||
textLayout.LayoutBounds.Width,
|
||||
height
|
||||
),
|
||||
Colors.White
|
||||
);
|
||||
}
|
||||
|
||||
ds.DrawImage(
|
||||
new OpacityEffect
|
||||
{
|
||||
Source = new BlendEffect
|
||||
{
|
||||
Background = IsLyricsGlowEffectEnabled
|
||||
? new GaussianBlurEffect
|
||||
{
|
||||
Source = new AlphaMaskEffect
|
||||
{
|
||||
Source = lyrics,
|
||||
AlphaMask = LyricsGlowEffectScope switch
|
||||
{
|
||||
LineRenderingType.UntilCurrentChar => mask,
|
||||
LineRenderingType.CurrentCharOnly => highlightMask,
|
||||
_ => mask,
|
||||
},
|
||||
},
|
||||
BlurAmount = _lyricsGlowEffectAmount,
|
||||
Optimization = EffectOptimization.Quality,
|
||||
}
|
||||
: new CanvasCommandList(control.Device),
|
||||
Foreground = new AlphaMaskEffect
|
||||
// Draw the mask for the current line
|
||||
for (int j = 0; j < regions.Length; j++)
|
||||
{
|
||||
Source = lyrics,
|
||||
AlphaMask = mask,
|
||||
},
|
||||
},
|
||||
Opacity = line.HighlightOpacityTransition.Value * _lyricsOpacityTransition.Value,
|
||||
var region = regions[j];
|
||||
var rect = new Rect(
|
||||
region.LayoutBounds.X,
|
||||
region.LayoutBounds.Y + position.Y,
|
||||
region.LayoutBounds.Width,
|
||||
region.LayoutBounds.Height
|
||||
);
|
||||
maskDs.FillRectangle(rect, Colors.Black);
|
||||
}
|
||||
}
|
||||
|
||||
float highlightTotalWidth = (float)highlightRegion.LayoutBounds.Width;
|
||||
// Draw the highlight for the current character
|
||||
float highlightWidth = highlightTotalWidth * charProgress;
|
||||
|
||||
float fadingWidth = (float)highlightRegion.LayoutBounds.Height / 2;
|
||||
|
||||
// Rects
|
||||
var highlightRect = new Rect(
|
||||
highlightRegion.LayoutBounds.X,
|
||||
highlightRegion.LayoutBounds.Y + position.Y,
|
||||
highlightWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
|
||||
var fadeInRect = new Rect(
|
||||
highlightRect.Right - fadingWidth,
|
||||
highlightRegion.LayoutBounds.Y + position.Y,
|
||||
fadingWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
var fadeOutRect = new Rect(
|
||||
highlightRect.Right,
|
||||
highlightRegion.LayoutBounds.Y + position.Y,
|
||||
fadingWidth,
|
||||
highlightRegion.LayoutBounds.Height
|
||||
);
|
||||
|
||||
// Brushes
|
||||
using var fadeInBrush = GetHorizontalFillBrush(
|
||||
control,
|
||||
[(0f, 0f), (1f, 1f)],
|
||||
(float)highlightRect.Right - fadingWidth,
|
||||
fadingWidth
|
||||
);
|
||||
using var fadeOutBrush = GetHorizontalFillBrush(
|
||||
control,
|
||||
[(0f, 1f), (1f, 0f)],
|
||||
(float)highlightRect.Right,
|
||||
fadingWidth
|
||||
);
|
||||
|
||||
maskDs.FillRectangle(highlightRect, Colors.White);
|
||||
maskDs.FillRectangle(fadeOutRect, fadeOutBrush);
|
||||
|
||||
highlightMaskDs.FillRectangle(fadeInRect, fadeInBrush);
|
||||
highlightMaskDs.FillRectangle(fadeOutRect, fadeOutBrush);
|
||||
}
|
||||
);
|
||||
else
|
||||
{
|
||||
float height = 0f;
|
||||
var regions = textLayout.GetCharacterRegions(0, string.Join("", line.CharTimings.Select(x => x.Text)).Length);
|
||||
if (regions.Length > 0)
|
||||
{
|
||||
height = (float)regions[^1].LayoutBounds.Bottom - (float)regions[0].LayoutBounds.Top;
|
||||
}
|
||||
|
||||
maskDs.FillRectangle(
|
||||
new Rect(
|
||||
textLayout.LayoutBounds.X,
|
||||
position.Y,
|
||||
textLayout.LayoutBounds.Width,
|
||||
height
|
||||
),
|
||||
Colors.White
|
||||
);
|
||||
}
|
||||
|
||||
ds.DrawImage(
|
||||
new OpacityEffect
|
||||
{
|
||||
Source = new BlendEffect
|
||||
{
|
||||
Background = IsLyricsGlowEffectEnabled
|
||||
? new GaussianBlurEffect
|
||||
{
|
||||
Source = new AlphaMaskEffect
|
||||
{
|
||||
Source = fgLyrics,
|
||||
AlphaMask = LyricsGlowEffectScope switch
|
||||
{
|
||||
LineRenderingType.UntilCurrentChar => mask,
|
||||
LineRenderingType.CurrentCharOnly => highlightMask,
|
||||
_ => mask,
|
||||
},
|
||||
},
|
||||
BlurAmount = _lyricsGlowEffectAmount,
|
||||
Optimization = EffectOptimization.Quality,
|
||||
}
|
||||
: new CanvasCommandList(control.Device),
|
||||
Foreground = new AlphaMaskEffect
|
||||
{
|
||||
Source = fgLyrics,
|
||||
AlphaMask = mask,
|
||||
},
|
||||
},
|
||||
Opacity = line.HighlightOpacityTransition.Value * _lyricsOpacityTransition.Value,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Reset scale
|
||||
ds.Transform = Matrix3x2.Identity;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using Windows.UI;
|
||||
@@ -18,6 +20,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
IRecipient<PropertyChangedMessage<TextAlignmentType>>,
|
||||
IRecipient<PropertyChangedMessage<LyricsFontWeight>>,
|
||||
IRecipient<PropertyChangedMessage<LineRenderingType>>,
|
||||
IRecipient<PropertyChangedMessage<ElementTheme>>,
|
||||
IRecipient<PropertyChangedMessage<ObservableCollection<LyricsSearchProviderInfo>>>,
|
||||
IRecipient<PropertyChangedMessage<ObservableCollection<LocalLyricsFolder>>>
|
||||
{
|
||||
@@ -28,6 +31,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.LocalLyricsFolders))
|
||||
{
|
||||
// Music lib changed, re-fetch lyrics
|
||||
_logger.LogInformation("Local lyrics folders changed, refreshing lyrics.");
|
||||
RefreshLyricsAsync();
|
||||
}
|
||||
}
|
||||
@@ -40,6 +44,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.LyricsSearchProvidersInfo))
|
||||
{
|
||||
// Lyrics search providers info changed, re-fetch lyrics
|
||||
_logger.LogInformation("Lyrics search providers info changed, refreshing lyrics.");
|
||||
RefreshLyricsAsync();
|
||||
}
|
||||
}
|
||||
@@ -66,6 +71,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.IsFanLyricsEnabled))
|
||||
{
|
||||
_isFanLyricsEnabled = message.NewValue;
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
}
|
||||
else if (message.Sender is LyricsWindowViewModel)
|
||||
@@ -84,6 +90,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
if (message.PropertyName == nameof(LyricsPageViewModel.IsTranslationEnabled))
|
||||
{
|
||||
_isTranslationEnabled = message.NewValue;
|
||||
_logger.LogInformation("Translation enabled state changed: {IsEnabled}", _isTranslationEnabled);
|
||||
UpdateTranslationsAsync();
|
||||
}
|
||||
}
|
||||
@@ -96,16 +103,25 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
if (message.PropertyName == nameof(LyricsWindowViewModel.ActivatedWindowAccentColor))
|
||||
{
|
||||
_immersiveBgTransition.StartTransition(message.NewValue);
|
||||
_lyricsWindowBgColor = message.NewValue;
|
||||
_adaptiveFontColor = Helper.ColorHelper.GetForegroundColor(_lyricsWindowBgColor);
|
||||
_environmentalColor = message.NewValue;
|
||||
UpdateFontColor();
|
||||
}
|
||||
}
|
||||
else if (message.Sender is SettingsPageViewModel)
|
||||
{
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.LyricsCustomFontColor))
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.LyricsCustomBgFontColor))
|
||||
{
|
||||
_customFontColor = message.NewValue;
|
||||
_customBgFontColor = message.NewValue;
|
||||
UpdateFontColor();
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsCustomFgFontColor))
|
||||
{
|
||||
_customFgFontColor = message.NewValue;
|
||||
UpdateFontColor();
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsCustomStrokeFontColor))
|
||||
{
|
||||
_customStrokeFontColor = message.NewValue;
|
||||
UpdateFontColor();
|
||||
}
|
||||
}
|
||||
@@ -141,15 +157,27 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsVerticalEdgeOpacity))
|
||||
{
|
||||
LyricsVerticalEdgeOpacity = message.NewValue;
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsBlurAmount))
|
||||
{
|
||||
LyricsBlurAmount = message.NewValue;
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFontSize))
|
||||
{
|
||||
LyricsFontSize = message.NewValue;
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.SelectedTargetLanguageIndex))
|
||||
{
|
||||
_targetLanguageIndex = message.NewValue;
|
||||
_logger.LogInformation("Target language index changed: {Index}", _targetLanguageIndex);
|
||||
UpdateTranslationsAsync();
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFontStrokeWidth))
|
||||
{
|
||||
_lyricsFontStrokeWidth = message.NewValue;
|
||||
}
|
||||
}
|
||||
else if (message.Sender is LyricsPageViewModel)
|
||||
{
|
||||
@@ -196,9 +224,20 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
if (message.Sender is SettingsPageViewModel)
|
||||
{
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFontColorType))
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.LyricsBgFontColorType))
|
||||
{
|
||||
LyricsFontColorType = message.NewValue;
|
||||
_lyricsBgFontColorType = message.NewValue;
|
||||
UpdateFontColor();
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFgFontColorType))
|
||||
{
|
||||
_lyricsFgFontColorType = message.NewValue;
|
||||
UpdateFontColor();
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsStrokeFontColorType))
|
||||
{
|
||||
_lyricsStrokeFontColorType = message.NewValue;
|
||||
UpdateFontColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,25 +253,32 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnLyricsFontColorTypeChanged(LyricsFontColorType value)
|
||||
public void Receive(PropertyChangedMessage<ElementTheme> message)
|
||||
{
|
||||
UpdateFontColor();
|
||||
if (message.Sender is SettingsPageViewModel)
|
||||
{
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.LyricsBackgroundTheme))
|
||||
{
|
||||
_lyricsBgTheme = message.NewValue;
|
||||
UpdateFontColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnLyricsFontSizeChanged(int value)
|
||||
{
|
||||
_isRelayoutNeeded = true;
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
|
||||
partial void OnLyricsFontWeightChanged(LyricsFontWeight value)
|
||||
{
|
||||
_lyricsTextFormat.FontWeight = value.ToFontWeight();
|
||||
_isRelayoutNeeded = true;
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
|
||||
partial void OnLyricsLineSpacingFactorChanged(float value)
|
||||
{
|
||||
_isRelayoutNeeded = true;
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private readonly ValueTransition<Color> _immersiveBgTransition = new(
|
||||
initialValue: Colors.Transparent,
|
||||
durationSeconds: 1f,
|
||||
durationSeconds: 0.3f,
|
||||
interpolator: (from, to, progress) => Helper.ColorHelper.GetInterpolatedColor(progress, from, to)
|
||||
);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private readonly ValueTransition<float> _lyricsOpacityTransition = new(
|
||||
initialValue: 0f,
|
||||
durationSeconds: 1f
|
||||
durationSeconds: 0.3f
|
||||
);
|
||||
|
||||
private readonly ValueTransition<float> _albumArtBgTransition = new(
|
||||
@@ -52,5 +52,10 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
durationSeconds: 1f
|
||||
);
|
||||
|
||||
private readonly ValueTransition<float> _lyricsBgBrightnessTransition = new(
|
||||
initialValue: 0f,
|
||||
durationSeconds: 1f
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,28 +14,39 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
public partial class LyricsRendererViewModel
|
||||
{
|
||||
private bool _isCanvasWidthChanged = false;
|
||||
private bool _isCanvasHeightChanged = false;
|
||||
|
||||
private bool _isDisplayTypeChanged = false;
|
||||
|
||||
private bool _isPlayingLineChanged = false;
|
||||
private bool _isVisibleLinesBoundaryChanged = false;
|
||||
|
||||
public void Update(ICanvasAnimatedControl control, CanvasAnimatedUpdateEventArgs args)
|
||||
{
|
||||
bool isCanvasWidthChanged = _canvasWidth != control.Size.Width;
|
||||
bool isDisplayTypeChanged = _displayType != _displayTypeReceived;
|
||||
|
||||
_canvasWidth = (float)control.Size.Width;
|
||||
_canvasHeight = (float)control.Size.Height;
|
||||
|
||||
_albumArtY = 36 + (_canvasHeight - 36 * 2) * 3 / 16f;
|
||||
|
||||
_displayType = _displayTypeReceived;
|
||||
_elapsedTime = args.Timing.ElapsedTime;
|
||||
|
||||
if (_isPlaying)
|
||||
{
|
||||
_totalTime += args.Timing.ElapsedTime;
|
||||
_totalTime += _elapsedTime;
|
||||
}
|
||||
|
||||
ElapsedTime = args.Timing.ElapsedTime;
|
||||
var playingLineIndex = GetCurrentPlayingLineIndex();
|
||||
|
||||
_immersiveBgTransition.Update(ElapsedTime);
|
||||
_albumArtBgTransition.Update(ElapsedTime);
|
||||
_songInfoOpacityTransition.Update(ElapsedTime);
|
||||
_isCanvasWidthChanged = _canvasWidth != control.Size.Width;
|
||||
_isCanvasHeightChanged = _canvasHeight != control.Size.Height;
|
||||
_isDisplayTypeChanged = _displayType != _displayTypeReceived;
|
||||
_isPlayingLineChanged = _playingLineIndex != playingLineIndex;
|
||||
|
||||
_canvasWidth = (float)control.Size.Width;
|
||||
_canvasHeight = (float)control.Size.Height;
|
||||
_displayType = _displayTypeReceived;
|
||||
_playingLineIndex = playingLineIndex;
|
||||
|
||||
_immersiveBgTransition.Update(_elapsedTime);
|
||||
_albumArtBgTransition.Update(_elapsedTime);
|
||||
_lyricsBgBrightnessTransition.Update(_elapsedTime);
|
||||
_songInfoOpacityTransition.Update(_elapsedTime);
|
||||
|
||||
if (IsDynamicCoverOverlayEnabled)
|
||||
{
|
||||
@@ -43,16 +54,24 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_rotateAngle %= MathF.PI * 2;
|
||||
}
|
||||
|
||||
_albumArtSize = MathF.Min(
|
||||
(_canvasHeight - _topMargin - _bottomMargin) * 8.5f / 16,
|
||||
(_canvasWidth - _leftMargin - _middleMargin - _rightMargin) / 2);
|
||||
_albumArtSize = MathF.Max(0, _albumArtSize);
|
||||
|
||||
_titleY = _albumArtY + _albumArtSize * 1.05f;
|
||||
|
||||
if (isDisplayTypeChanged || isCanvasWidthChanged)
|
||||
if (_isCanvasHeightChanged)
|
||||
{
|
||||
bool jumpTo = !isDisplayTypeChanged && isCanvasWidthChanged;
|
||||
_albumArtY = 36 + (_canvasHeight - 36 * 2) * 3 / 16f;
|
||||
}
|
||||
|
||||
if (_isCanvasWidthChanged || _isCanvasHeightChanged)
|
||||
{
|
||||
_albumArtSize = MathF.Min(
|
||||
(_canvasHeight - _topMargin - _bottomMargin) * 8.5f / 16,
|
||||
(_canvasWidth - _leftMargin - _middleMargin - _rightMargin) / 2);
|
||||
_albumArtSize = MathF.Max(0, _albumArtSize);
|
||||
|
||||
_titleY = _albumArtY + _albumArtSize * 1.05f;
|
||||
}
|
||||
|
||||
if (_isDisplayTypeChanged || _isCanvasWidthChanged)
|
||||
{
|
||||
bool jumpTo = !_isDisplayTypeChanged && _isCanvasWidthChanged;
|
||||
switch (_displayType)
|
||||
{
|
||||
case LyricsDisplayType.AlbumArtOnly:
|
||||
@@ -64,14 +83,12 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_lyricsOpacityTransition.StartTransition(1f, jumpTo);
|
||||
_albumArtOpacityTransition.StartTransition(0f, jumpTo);
|
||||
_lyricsXTransition.StartTransition(_leftMargin, jumpTo);
|
||||
_isRelayoutNeeded = true;
|
||||
break;
|
||||
case LyricsDisplayType.SplitView:
|
||||
_lyricsOpacityTransition.StartTransition(1f, jumpTo);
|
||||
_albumArtOpacityTransition.StartTransition(1f, jumpTo);
|
||||
_lyricsXTransition.StartTransition((_canvasWidth - _leftMargin - _middleMargin - _rightMargin) / 2 + _leftMargin + _middleMargin, jumpTo);
|
||||
_albumArtXTransition.StartTransition(_leftMargin + ((_canvasWidth - _leftMargin - _middleMargin - _rightMargin) / 2 - _albumArtSize) / 2, jumpTo);
|
||||
_isRelayoutNeeded = true;
|
||||
break;
|
||||
case LyricsDisplayType.PlaceholderOnly:
|
||||
break;
|
||||
@@ -80,31 +97,31 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
_lyricsXTransition.Update(ElapsedTime);
|
||||
_albumArtXTransition.Update(ElapsedTime);
|
||||
_lyricsOpacityTransition.Update(ElapsedTime);
|
||||
_albumArtOpacityTransition.Update(ElapsedTime);
|
||||
_lyricsXTransition.Update(_elapsedTime);
|
||||
_albumArtXTransition.Update(_elapsedTime);
|
||||
_lyricsOpacityTransition.Update(_elapsedTime);
|
||||
_albumArtOpacityTransition.Update(_elapsedTime);
|
||||
|
||||
if (_lyricsXTransition.IsTransitioning)
|
||||
if (_isCanvasWidthChanged || _lyricsXTransition.IsTransitioning)
|
||||
{
|
||||
_isRelayoutNeeded = true;
|
||||
_maxLyricsWidth = _canvasWidth - _lyricsXTransition.Value - _rightMargin;
|
||||
_maxLyricsWidth = Math.Max(_maxLyricsWidth, 0);
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
|
||||
_maxLyricsWidth = _canvasWidth - _lyricsXTransition.Value - _rightMargin;
|
||||
_maxLyricsWidth = Math.Max(_maxLyricsWidth, 0);
|
||||
|
||||
if (_isRelayoutNeeded)
|
||||
if (_isLayoutChanged)
|
||||
{
|
||||
ReLayout(control);
|
||||
_isRelayoutNeeded = false;
|
||||
UpdateCanvasYScrollOffset(control, false);
|
||||
UpdateCanvasYScrollOffset(control, true, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateCanvasYScrollOffset(control, true);
|
||||
UpdateCanvasYScrollOffset(control, false, true);
|
||||
}
|
||||
|
||||
UpdateLinesProps();
|
||||
|
||||
_isLayoutChanged = false;
|
||||
}
|
||||
|
||||
private void ReLayout(ICanvasAnimatedControl control)
|
||||
@@ -150,48 +167,35 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateCanvasYScrollOffset(ICanvasAnimatedControl control, bool withAnimation)
|
||||
private void UpdateCanvasYScrollOffset(ICanvasAnimatedControl control, bool forceScroll, bool withAnimation)
|
||||
{
|
||||
var currentPlayingLineIndex = GetCurrentPlayingLineIndex();
|
||||
|
||||
var (startLineIndex, endLineIndex) = GetMaxLyricsLineIndexBoundaries();
|
||||
|
||||
if (startLineIndex < 0 || endLineIndex < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (startLineIndex < 0 || endLineIndex < 0) return;
|
||||
|
||||
// Set _scrollOffsetY
|
||||
LyricsLine? currentPlayingLine = _multiLangLyrics
|
||||
.SafeGet(_langIndex)
|
||||
?.SafeGet(currentPlayingLineIndex);
|
||||
|
||||
var playingTextLayout = currentPlayingLine?.CanvasTextLayout;
|
||||
|
||||
if (currentPlayingLine == null || playingTextLayout == null)
|
||||
if ((!_isPlayingLineChanged && forceScroll) || _isPlayingLineChanged)
|
||||
{
|
||||
return;
|
||||
LyricsLine? currentPlayingLine = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(_playingLineIndex);
|
||||
|
||||
if (currentPlayingLine == null) return;
|
||||
|
||||
var playingTextLayout = currentPlayingLine?.CanvasTextLayout;
|
||||
|
||||
if (playingTextLayout == null) return;
|
||||
|
||||
float? targetYScrollOffset = (float?)(-currentPlayingLine!.Position.Y + _multiLangLyrics.SafeGet(_langIndex)?[0].Position.Y - playingTextLayout.LayoutBounds.Height / 2);
|
||||
|
||||
if (!targetYScrollOffset.HasValue) return;
|
||||
|
||||
_canvasYScrollTransition.StartTransition(targetYScrollOffset.Value, !withAnimation);
|
||||
}
|
||||
|
||||
float targetYScrollOffset =
|
||||
(float?)(
|
||||
-currentPlayingLine.Position.Y
|
||||
+ _multiLangLyrics.SafeGet(_langIndex)?[0].Position.Y
|
||||
- playingTextLayout.LayoutBounds.Height / 2
|
||||
) ?? 0f;
|
||||
_canvasYScrollTransition.Update(_elapsedTime);
|
||||
|
||||
if (withAnimation && !_canvasYScrollTransition.IsTransitioning)
|
||||
{
|
||||
_canvasYScrollTransition.StartTransition(targetYScrollOffset);
|
||||
}
|
||||
else if (!withAnimation)
|
||||
{
|
||||
_canvasYScrollTransition.StartTransition(targetYScrollOffset, true);
|
||||
}
|
||||
|
||||
_canvasYScrollTransition.Update(ElapsedTime);
|
||||
|
||||
_startVisibleLineIndex = _endVisibleLineIndex = -1;
|
||||
int startVisibleLineIndex = -1;
|
||||
int endVisibleLineIndex = -1;
|
||||
|
||||
// Update visible line indices
|
||||
for (int i = startLineIndex; i <= endLineIndex; i++)
|
||||
@@ -213,9 +217,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
>= 0
|
||||
)
|
||||
{
|
||||
if (_startVisibleLineIndex == -1)
|
||||
if (startVisibleLineIndex == -1)
|
||||
{
|
||||
_startVisibleLineIndex = i;
|
||||
startVisibleLineIndex = i;
|
||||
}
|
||||
}
|
||||
if (
|
||||
@@ -226,46 +230,127 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
>= control.Size.Height
|
||||
)
|
||||
{
|
||||
if (_endVisibleLineIndex == -1)
|
||||
if (endVisibleLineIndex == -1)
|
||||
{
|
||||
_endVisibleLineIndex = i;
|
||||
endVisibleLineIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_startVisibleLineIndex != -1 && _endVisibleLineIndex == -1)
|
||||
if (startVisibleLineIndex != -1 && endVisibleLineIndex == -1)
|
||||
{
|
||||
_endVisibleLineIndex = endLineIndex;
|
||||
endVisibleLineIndex = endLineIndex;
|
||||
}
|
||||
|
||||
_isVisibleLinesBoundaryChanged = _startVisibleLineIndex != startVisibleLineIndex || _endVisibleLineIndex != endVisibleLineIndex;
|
||||
|
||||
_startVisibleLineIndex = startVisibleLineIndex;
|
||||
_endVisibleLineIndex = endVisibleLineIndex;
|
||||
}
|
||||
|
||||
private protected void UpdateFontColor()
|
||||
private void UpdateFontColor()
|
||||
{
|
||||
ThemeTypeSent = Helper.ColorHelper.GetElementThemeFromBackgroundColor(_lyricsWindowBgColor);
|
||||
if (_isDesktopMode || _isDockMode)
|
||||
{
|
||||
ThemeTypeSent = Helper.ColorHelper.GetElementThemeFromBackgroundColor(_environmentalColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
ThemeTypeSent = _lyricsBgTheme;
|
||||
}
|
||||
|
||||
float brightness = 0f;
|
||||
|
||||
Color grayedEnvironmentalColor = Colors.Transparent;
|
||||
|
||||
Color fallbackFg = Colors.Transparent;
|
||||
switch (ThemeTypeSent)
|
||||
{
|
||||
case ElementTheme.Default:
|
||||
switch (Application.Current.RequestedTheme)
|
||||
{
|
||||
case ApplicationTheme.Light:
|
||||
_adaptiveGrayedFontColor = _darkColor;
|
||||
brightness = 0.7f;
|
||||
break;
|
||||
case ApplicationTheme.Dark:
|
||||
_adaptiveGrayedFontColor = _lightColor;
|
||||
brightness = 0.3f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ElementTheme.Light:
|
||||
fallbackFg = _darkFontColor;
|
||||
_adaptiveGrayedFontColor = _darkColor;
|
||||
brightness = 0.7f;
|
||||
break;
|
||||
case ElementTheme.Dark:
|
||||
fallbackFg = _lightFontColor;
|
||||
_adaptiveGrayedFontColor = _lightColor;
|
||||
brightness = 0.3f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (LyricsFontColorType)
|
||||
if (_adaptiveGrayedFontColor == _lightColor)
|
||||
{
|
||||
case Enums.LyricsFontColorType.AdaptiveGrayed:
|
||||
_fontColor = fallbackFg;
|
||||
grayedEnvironmentalColor = _darkColor;
|
||||
} else if (_adaptiveGrayedFontColor == _darkColor)
|
||||
{
|
||||
grayedEnvironmentalColor = _lightColor;
|
||||
}
|
||||
|
||||
_lyricsBgBrightnessTransition.StartTransition(brightness);
|
||||
|
||||
if (_isDesktopMode || _isDockMode)
|
||||
{
|
||||
_adaptiveColoredFontColor = Helper.ColorHelper.GetForegroundColor(_environmentalColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
_adaptiveColoredFontColor = Helper.ColorHelper.GetForegroundColor(_albumArtAccentColor?.WithBrightness(brightness) ?? Colors.Transparent);
|
||||
}
|
||||
|
||||
switch (_lyricsBgFontColorType)
|
||||
{
|
||||
case LyricsFontColorType.AdaptiveGrayed:
|
||||
_bgFontColor = _adaptiveGrayedFontColor;
|
||||
break;
|
||||
case Enums.LyricsFontColorType.AdaptiveColored:
|
||||
_fontColor = _adaptiveFontColor ?? fallbackFg;
|
||||
case LyricsFontColorType.AdaptiveColored:
|
||||
_bgFontColor = _adaptiveColoredFontColor ?? _adaptiveGrayedFontColor;
|
||||
break;
|
||||
case Enums.LyricsFontColorType.Custom:
|
||||
_fontColor = _customFontColor ?? fallbackFg;
|
||||
case LyricsFontColorType.Custom:
|
||||
_bgFontColor = _customBgFontColor ?? _adaptiveGrayedFontColor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (_lyricsFgFontColorType)
|
||||
{
|
||||
case LyricsFontColorType.AdaptiveGrayed:
|
||||
_fgFontColor = _adaptiveGrayedFontColor;
|
||||
break;
|
||||
case LyricsFontColorType.AdaptiveColored:
|
||||
_fgFontColor = _adaptiveColoredFontColor ?? _adaptiveGrayedFontColor;
|
||||
break;
|
||||
case LyricsFontColorType.Custom:
|
||||
_fgFontColor = _customFgFontColor ?? _adaptiveGrayedFontColor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (_lyricsStrokeFontColorType)
|
||||
{
|
||||
case LyricsFontColorType.AdaptiveGrayed:
|
||||
_strokeFontColor = grayedEnvironmentalColor.WithBrightness(0.7);
|
||||
break;
|
||||
case LyricsFontColorType.AdaptiveColored:
|
||||
_strokeFontColor = _environmentalColor.WithBrightness(0.7);
|
||||
break;
|
||||
case LyricsFontColorType.Custom:
|
||||
_strokeFontColor = _customStrokeFontColor ?? _environmentalColor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -274,65 +359,42 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private void UpdateLinesProps()
|
||||
{
|
||||
var currentPlayingLineIndex = GetCurrentPlayingLineIndex();
|
||||
|
||||
var currentPlayingLine = _multiLangLyrics
|
||||
.SafeGet(_langIndex)
|
||||
?.SafeGet(currentPlayingLineIndex);
|
||||
?.SafeGet(_playingLineIndex);
|
||||
|
||||
if (currentPlayingLine == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (currentPlayingLine == null) return;
|
||||
|
||||
for (int i = _startVisibleLineIndex; i <= _endVisibleLineIndex; i++)
|
||||
{
|
||||
var line = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(i);
|
||||
|
||||
if (line == null)
|
||||
if (line == null) continue;
|
||||
|
||||
if (_isLayoutChanged || _isVisibleLinesBoundaryChanged || _isPlayingLineChanged)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
float distanceFromPlayingLine = Math.Abs(line.Position.Y - currentPlayingLine.Position.Y);
|
||||
float distanceFactor = Math.Clamp(distanceFromPlayingLine / (_canvasHeight / 2), 0, 1);
|
||||
|
||||
float distanceFromPlayingLine = Math.Abs(line.Position.Y - currentPlayingLine.Position.Y);
|
||||
|
||||
float distanceFactor = Math.Clamp(distanceFromPlayingLine / (_canvasHeight / 2), 0, 1);
|
||||
|
||||
if (!line.AngleTransition.IsTransitioning)
|
||||
line.AngleTransition.StartTransition(
|
||||
_isFanLyricsEnabled
|
||||
line.AngleTransition.StartTransition(_isFanLyricsEnabled
|
||||
? (float)Math.PI
|
||||
* (30f / 180f)
|
||||
* distanceFactor
|
||||
* (i - currentPlayingLineIndex > 0 ? 1 : -1)
|
||||
* (i > _playingLineIndex ? 1 : -1)
|
||||
: 0
|
||||
);
|
||||
|
||||
if (!line.BlurAmountTransition.IsTransitioning)
|
||||
line.BlurAmountTransition.StartTransition(LyricsBlurAmount * distanceFactor);
|
||||
|
||||
if (!line.ScaleTransition.IsTransitioning)
|
||||
line.ScaleTransition.StartTransition(
|
||||
_highlightedScale - distanceFactor * (_highlightedScale - _defaultScale)
|
||||
);
|
||||
|
||||
if (!line.OpacityTransition.IsTransitioning)
|
||||
line.ScaleTransition.StartTransition(_highlightedScale - distanceFactor * (_highlightedScale - _defaultScale));
|
||||
line.OpacityTransition.StartTransition(_defaultOpacity - distanceFactor * _defaultOpacity * (1 - LyricsVerticalEdgeOpacity / 100f));
|
||||
|
||||
// Only calculate highlight opacity for the current line and the two lines around it
|
||||
// to avoid unnecessary calculations
|
||||
if (!line.HighlightOpacityTransition.IsTransitioning)
|
||||
{
|
||||
line.HighlightOpacityTransition.StartTransition(
|
||||
distanceFromPlayingLine == 0 ? 1f : 0f
|
||||
);
|
||||
line.HighlightOpacityTransition.StartTransition(i == _playingLineIndex ? 1f : 0f);
|
||||
}
|
||||
|
||||
line.AngleTransition.Update(ElapsedTime);
|
||||
line.ScaleTransition.Update(ElapsedTime);
|
||||
line.BlurAmountTransition.Update(ElapsedTime);
|
||||
line.OpacityTransition.Update(ElapsedTime);
|
||||
line.HighlightOpacityTransition.Update(ElapsedTime);
|
||||
line.AngleTransition.Update(_elapsedTime);
|
||||
line.ScaleTransition.Update(_elapsedTime);
|
||||
line.BlurAmountTransition.Update(_elapsedTime);
|
||||
line.OpacityTransition.Update(_elapsedTime);
|
||||
line.HighlightOpacityTransition.Update(_elapsedTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Fluent.LibreTranslate;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
@@ -29,12 +28,16 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
public partial class LyricsRendererViewModel : BaseViewModel
|
||||
{
|
||||
private TimeSpan _elapsedTime = TimeSpan.Zero;
|
||||
private TimeSpan _totalTime = TimeSpan.Zero;
|
||||
private TimeSpan _positionOffset = TimeSpan.Zero;
|
||||
|
||||
private SoftwareBitmap? _lastAlbumArtSwBitmap = null;
|
||||
private SoftwareBitmap? _albumArtSwBitmap = null;
|
||||
|
||||
private CanvasBitmap? _lastAlbumArtCanvasBitmap = null;
|
||||
private CanvasBitmap? _albumArtCanvasBitmap = null;
|
||||
|
||||
private float _albumArtSize = 0f;
|
||||
private int _albumArtCornerRadius = 0;
|
||||
|
||||
@@ -67,6 +70,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
private readonly IMusicSearchService _musicSearchService;
|
||||
private readonly ILibWatcherService _libWatcherService;
|
||||
private readonly IPlaybackService _playbackService;
|
||||
private readonly ILibreTranslateService _libreTranslateService;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private readonly float _leftMargin = 36f;
|
||||
@@ -75,13 +79,32 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
private readonly float _topMargin = 36f;
|
||||
private readonly float _bottomMargin = 36f;
|
||||
|
||||
private Color _fontColor;
|
||||
private Color? _adaptiveFontColor = null;
|
||||
private Color? _customFontColor;
|
||||
private Color _lightFontColor = Colors.White;
|
||||
private Color _darkFontColor = Colors.Black;
|
||||
private Color _adaptiveGrayedFontColor = Colors.Transparent;
|
||||
private Color? _adaptiveColoredFontColor = null;
|
||||
|
||||
private Color? _albumArtAccentColor = null;
|
||||
private Color _lyricsWindowBgColor = Colors.Transparent;
|
||||
private Color _environmentalColor = Colors.Transparent;
|
||||
|
||||
private Color _lightColor = Colors.White;
|
||||
private Color _darkColor = Colors.Black;
|
||||
|
||||
private Color _bgFontColor;
|
||||
private Color _fgFontColor;
|
||||
private Color _strokeFontColor;
|
||||
|
||||
private Color? _customBgFontColor;
|
||||
private Color? _customFgFontColor;
|
||||
private Color? _customStrokeFontColor;
|
||||
|
||||
private LyricsFontColorType _lyricsBgFontColorType;
|
||||
private LyricsFontColorType _lyricsFgFontColorType;
|
||||
private LyricsFontColorType _lyricsStrokeFontColorType;
|
||||
|
||||
private ElementTheme _lyricsBgTheme;
|
||||
|
||||
private int _lyricsFontStrokeWidth;
|
||||
|
||||
private int _playingLineIndex = -1;
|
||||
|
||||
private int _startVisibleLineIndex = -1;
|
||||
private int _endVisibleLineIndex = -1;
|
||||
@@ -93,13 +116,14 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private bool _isPlaying = true;
|
||||
|
||||
private bool _isRelayoutNeeded = true;
|
||||
private bool _isLayoutChanged = true;
|
||||
|
||||
private int _langIndex = 0;
|
||||
|
||||
private List<List<LyricsLine>> _multiLangLyrics = [];
|
||||
private List<string> _translations = [];
|
||||
private bool _isTranslationEnabled = false;
|
||||
private int _targetLanguageIndex = 6;
|
||||
|
||||
private CanvasTextFormat _lyricsTextFormat = new()
|
||||
{
|
||||
@@ -131,13 +155,13 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
private Task? _showTranslationsTask;
|
||||
private CancellationTokenSource? _showTranslationsCts;
|
||||
|
||||
public LyricsRendererViewModel(
|
||||
ISettingsService settingsService, IPlaybackService playbackService,
|
||||
IMusicSearchService musicSearchService, ILibWatcherService libWatcherService) : base(settingsService)
|
||||
public LyricsRendererViewModel(ISettingsService settingsService, IPlaybackService playbackService, IMusicSearchService musicSearchService, ILibWatcherService libWatcherService, ILibreTranslateService libreTranslateService) : base(settingsService)
|
||||
{
|
||||
_musicSearchService = musicSearchService;
|
||||
_playbackService = playbackService;
|
||||
_libWatcherService = libWatcherService;
|
||||
_libreTranslateService = libreTranslateService;
|
||||
|
||||
_logger = Ioc.Default.GetRequiredService<ILogger<LyricsRendererViewModel>>();
|
||||
|
||||
_albumArtCornerRadius = _settingsService.CoverImageRadius;
|
||||
@@ -145,7 +169,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
CoverOverlayOpacity = _settingsService.CoverOverlayOpacity;
|
||||
CoverOverlayBlurAmount = _settingsService.CoverOverlayBlurAmount;
|
||||
|
||||
LyricsFontColorType = _settingsService.LyricsFontColorType;
|
||||
_lyricsBgFontColorType = _settingsService.LyricsBgFontColorType;
|
||||
_lyricsFgFontColorType = _settingsService.LyricsFgFontColorType;
|
||||
|
||||
LyricsFontWeight = _settingsService.LyricsFontWeight;
|
||||
LyricsAlignmentType = _settingsService.LyricsAlignmentType;
|
||||
LyricsVerticalEdgeOpacity = _settingsService.LyricsVerticalEdgeOpacity;
|
||||
@@ -154,9 +180,19 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
LyricsBlurAmount = _settingsService.LyricsBlurAmount;
|
||||
IsLyricsGlowEffectEnabled = _settingsService.IsLyricsGlowEffectEnabled;
|
||||
LyricsGlowEffectScope = _settingsService.LyricsGlowEffectScope;
|
||||
_customFontColor = _settingsService.LyricsCustomFontColor;
|
||||
|
||||
_customBgFontColor = _settingsService.LyricsCustomBgFontColor;
|
||||
_customFgFontColor = _settingsService.LyricsCustomFgFontColor;
|
||||
|
||||
_lyricsBgTheme = _settingsService.LyricsBackgroundTheme;
|
||||
|
||||
_isFanLyricsEnabled = _settingsService.IsFanLyricsEnabled;
|
||||
|
||||
_lyricsFontStrokeWidth = _settingsService.LyricsFontStrokeWidth;
|
||||
|
||||
_isTranslationEnabled = _settingsService.IsTranslationEnabled;
|
||||
_targetLanguageIndex = _settingsService.SelectedTargetLanguageIndex;
|
||||
|
||||
_titleTextFormat.HorizontalAlignment = _artistTextFormat.HorizontalAlignment = _settingsService.SongInfoAlignmentType.ToCanvasHorizontalAlignment();
|
||||
|
||||
_libWatcherService.MusicLibraryFilesChanged +=
|
||||
@@ -169,6 +205,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
UpdateFontColor();
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsTranslating { get; set; } = false;
|
||||
|
||||
public int CoverOverlayBlurAmount { get; set; }
|
||||
|
||||
public int CoverOverlayOpacity { get; set; }
|
||||
@@ -176,8 +215,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
private LyricsDisplayType _displayTypeReceived = LyricsDisplayType.PlaceholderOnly;
|
||||
private LyricsDisplayType _displayType = LyricsDisplayType.PlaceholderOnly;
|
||||
|
||||
public TimeSpan ElapsedTime { get; set; } = TimeSpan.Zero;
|
||||
|
||||
public bool IsDynamicCoverOverlayEnabled { get; set; }
|
||||
|
||||
public bool IsLyricsGlowEffectEnabled { get; set; }
|
||||
@@ -186,9 +223,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
public int LyricsBlurAmount { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial LyricsFontColorType LyricsFontColorType { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial int LyricsFontSize { get; set; }
|
||||
|
||||
@@ -301,6 +335,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private void LibWatcherService_MusicLibraryFilesChanged(object? sender, LibChangedEventArgs e)
|
||||
{
|
||||
_logger.LogInformation("Music library files changed: {ChangeType} {FilePath}, refreshing lyrics...", e.ChangeType, e.FilePath);
|
||||
RefreshLyricsAsync();
|
||||
}
|
||||
|
||||
@@ -324,15 +359,16 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
if (SongInfo?.AlbumArtSwBitmap != _albumArtSwBitmap)
|
||||
{
|
||||
_lastAlbumArtSwBitmap = _albumArtSwBitmap;
|
||||
_lastAlbumArtCanvasBitmap = null;
|
||||
|
||||
_albumArtSwBitmap = SongInfo?.AlbumArtSwBitmap;
|
||||
_albumArtCanvasBitmap = null;
|
||||
|
||||
_albumArtAccentColor = SongInfo?.AlbumArtAccentColor;
|
||||
_lyricsWindowBgColor = _albumArtAccentColor ?? Colors.Gray;
|
||||
|
||||
_albumArtBgTransition.Reset(0f);
|
||||
_albumArtBgTransition.StartTransition(1f);
|
||||
|
||||
if (!_isDesktopMode && !_isDockMode) _adaptiveFontColor = Helper.ColorHelper.GetForegroundColor(_lyricsWindowBgColor);
|
||||
UpdateFontColor();
|
||||
}
|
||||
|
||||
@@ -347,6 +383,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_songInfoOpacityTransition.Reset(0f);
|
||||
_songInfoOpacityTransition.StartTransition(1f);
|
||||
|
||||
_logger.LogInformation("Song info changed: Title={Title}, Artist={Artist}, refreshing lyrics...", _songTitle, _songArtist);
|
||||
await RefreshLyricsAsync();
|
||||
|
||||
_totalTime = TimeSpan.Zero;
|
||||
@@ -372,6 +409,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private async Task UpdateTranslationsAsync()
|
||||
{
|
||||
IsTranslating = true;
|
||||
if (_isTranslationEnabled)
|
||||
{
|
||||
await ShowWithTranslationsAsync();
|
||||
@@ -380,6 +418,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
ShowOriginalsOnly();
|
||||
}
|
||||
IsTranslating = false;
|
||||
}
|
||||
|
||||
private async Task ShowWithTranslationsAsync()
|
||||
@@ -400,11 +439,23 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private async Task ShowTranslationsCoreAsync(CancellationToken token)
|
||||
{
|
||||
_logger.LogInformation("Showing translations for lyrics...");
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(_settingsService.LibreTranslateServer))
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
App.Current.LyricsWindowNotificationPanel?.Notify(
|
||||
App.ResourceLoader!.GetString("TranslateServerNotSet"),
|
||||
Microsoft.UI.Xaml.Controls.InfoBarSeverity.Warning
|
||||
);
|
||||
});
|
||||
ShowOriginalsOnly();
|
||||
return;
|
||||
}
|
||||
var text = string.Join("\n", _multiLangLyrics.FirstOrDefault()?.Select(x => x.OriginalText) ?? []);
|
||||
GlobalLibreTranslateSettings.Server = new LibreTranslateServer("http://localhost:5000");
|
||||
var translated = await text.TranslateAsync(LanguageCode.Chinese);
|
||||
var translated = await _libreTranslateService.TranslateAsync(text, token);
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
_translations = translated.Split('\n').ToList();
|
||||
@@ -424,25 +475,27 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
break;
|
||||
}
|
||||
|
||||
if (totallySame) return; // No need to show translations
|
||||
|
||||
foreach (var langLyrics in _multiLangLyrics)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (var line in langLyrics)
|
||||
{
|
||||
line.DisplayedText = $"{line.OriginalText}\n{_translations[i]}";
|
||||
line.DisplayedText = totallySame ? line.OriginalText : $"{line.OriginalText}\n{_translations[i]}";
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
_isRelayoutNeeded = true;
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
IsTranslating = false;
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
private void ShowOriginalsOnly()
|
||||
{
|
||||
_logger.LogInformation("Showing original lyrics only, translations disabled.");
|
||||
foreach (var langLyrics in _multiLangLyrics)
|
||||
{
|
||||
foreach (var line in langLyrics)
|
||||
@@ -450,7 +503,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
line.DisplayedText = line.OriginalText;
|
||||
}
|
||||
}
|
||||
_isRelayoutNeeded = true;
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
|
||||
private async Task RefreshLyricsCoreAsync(CancellationToken token)
|
||||
@@ -485,8 +538,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
(int?)SongInfo?.DurationMs ?? (int)TimeSpan.FromMinutes(99).TotalMilliseconds
|
||||
);
|
||||
_logger.LogInformation("Parsed lyrics: {MultiLangLyricsCount} languages", _multiLangLyrics.Count);
|
||||
ShowOriginalsOnly();
|
||||
await UpdateTranslationsAsync();
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
@@ -506,7 +559,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
},
|
||||
]
|
||||
);
|
||||
_isRelayoutNeeded = true;
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
using System.Threading.Tasks;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Messages;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
@@ -13,6 +12,7 @@ using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Windows.UI;
|
||||
using WinRT.Interop;
|
||||
@@ -27,23 +27,9 @@ namespace BetterLyrics.WinUI3
|
||||
{
|
||||
private ForegroundWindowWatcherHelper? _watcherHelper = null;
|
||||
|
||||
public LyricsWindowViewModel(ISettingsService settingsService)
|
||||
: base(settingsService)
|
||||
public LyricsWindowViewModel(ISettingsService settingsService) : base(settingsService)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Register<ShowNotificatonMessage>(
|
||||
this,
|
||||
async (r, m) =>
|
||||
{
|
||||
Notification = m.Value;
|
||||
if (!Notification.IsForeverDismissable)
|
||||
{
|
||||
Notification.Visibility = Notification.IsForeverDismissable ? Visibility.Visible : Visibility.Collapsed;
|
||||
ShowInfoBar = true;
|
||||
await Task.Delay(AnimationHelper.StackedNotificationsShowingDuration);
|
||||
ShowInfoBar = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
_ignoreFullscreenWindow = _settingsService.IgnoreFullscreenWindow;
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
@@ -77,6 +63,8 @@ namespace BetterLyrics.WinUI3
|
||||
[ObservableProperty]
|
||||
public partial double TitleBarHeight { get; set; } = 36;
|
||||
|
||||
private bool _ignoreFullscreenWindow = false;
|
||||
|
||||
public void Receive(PropertyChangedMessage<bool> message)
|
||||
{
|
||||
if (message.Sender is SystemTrayViewModel)
|
||||
@@ -89,6 +77,13 @@ namespace BetterLyrics.WinUI3
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (message.Sender is SettingsPageViewModel)
|
||||
{
|
||||
if (message.PropertyName == nameof(SettingsPageViewModel.IgnoreFullscreenWindow))
|
||||
{
|
||||
_ignoreFullscreenWindow = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<ElementTheme> message)
|
||||
@@ -113,10 +108,7 @@ namespace BetterLyrics.WinUI3
|
||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
if (window == null) return;
|
||||
|
||||
DockModeHelper.UpdateAppBarHeight(
|
||||
WindowNative.GetWindowHandle(window),
|
||||
message.NewValue * 3
|
||||
);
|
||||
DockModeHelper.UpdateAppBarHeight(WindowNative.GetWindowHandle(window), message.NewValue * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,6 +124,10 @@ namespace BetterLyrics.WinUI3
|
||||
hwnd,
|
||||
onWindowChanged =>
|
||||
{
|
||||
if (_ignoreFullscreenWindow && window.AppWindow.Presenter is OverlappedPresenter presenter)
|
||||
{
|
||||
presenter.IsAlwaysOnTop = true;
|
||||
}
|
||||
UpdateAccentColor(hwnd, mode);
|
||||
}
|
||||
);
|
||||
@@ -148,6 +144,8 @@ namespace BetterLyrics.WinUI3
|
||||
private void LockWindow()
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
if (window == null) return;
|
||||
|
||||
DesktopModeHelper.Lock(window);
|
||||
IsLyricsWindowLocked = true;
|
||||
}
|
||||
@@ -175,7 +173,6 @@ namespace BetterLyrics.WinUI3
|
||||
else
|
||||
{
|
||||
DesktopModeHelper.Disable(window);
|
||||
StopWatchWindowColorChange();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,17 +180,18 @@ namespace BetterLyrics.WinUI3
|
||||
private void ToggleDockMode()
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
if (window == null) return;
|
||||
|
||||
StopWatchWindowColorChange();
|
||||
|
||||
IsDockMode = !IsDockMode;
|
||||
if (IsDockMode)
|
||||
{
|
||||
StartWatchWindowColorChange(WindowColorSampleMode.BelowWindow);
|
||||
DockModeHelper.Enable(window, _settingsService.LyricsFontSize * 3);
|
||||
DockModeHelper.Enable(window, _settingsService.LyricsFontSize * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
StartWatchWindowColorChange(WindowColorSampleMode.WindowEdge);
|
||||
DockModeHelper.Disable(window);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Messages;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
@@ -17,11 +9,23 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.UI.Xaml;
|
||||
using ShadowViewer.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.Globalization;
|
||||
using Windows.Media.Playback;
|
||||
using Windows.System;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Popups;
|
||||
using WinRT.Interop;
|
||||
using AppInfo = BetterLyrics.WinUI3.Helper.AppInfo;
|
||||
|
||||
namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
@@ -29,11 +33,18 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
private readonly ILibWatcherService _libWatcherService;
|
||||
private readonly IPlaybackService _playbackService;
|
||||
private readonly ILibreTranslateService _libreTranslateService;
|
||||
|
||||
public SettingsPageViewModel(ISettingsService settingsService, ILibWatcherService libWatcherService, IPlaybackService playbackService) : base(settingsService)
|
||||
private readonly string _autoStartupTaskId = "AutoStartup";
|
||||
|
||||
public SettingsPageViewModel(ISettingsService settingsService, ILibWatcherService libWatcherService, IPlaybackService playbackService, ILibreTranslateService libreTranslateService) : base(settingsService)
|
||||
{
|
||||
_libWatcherService = libWatcherService;
|
||||
_playbackService = playbackService;
|
||||
_libreTranslateService = libreTranslateService;
|
||||
|
||||
LibreTranslateServer = _settingsService.LibreTranslateServer;
|
||||
SelectedTargetLanguageIndex = _settingsService.SelectedTargetLanguageIndex;
|
||||
|
||||
LocalLyricsFolders = [.. _settingsService.LocalLyricsFolders];
|
||||
LyricsSearchProvidersInfo = [.. _settingsService.LyricsSearchProvidersInfo];
|
||||
@@ -58,15 +69,28 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
IsLyricsGlowEffectEnabled = _settingsService.IsLyricsGlowEffectEnabled;
|
||||
LyricsGlowEffectScope = _settingsService.LyricsGlowEffectScope;
|
||||
IsFanLyricsEnabled = _settingsService.IsFanLyricsEnabled;
|
||||
LyricsFontColorType = _settingsService.LyricsFontColorType;
|
||||
LyricsCustomFontColor = _settingsService.LyricsCustomFontColor;
|
||||
|
||||
LyricsBgFontColorType = _settingsService.LyricsBgFontColorType;
|
||||
LyricsFgFontColorType = _settingsService.LyricsFgFontColorType;
|
||||
LyricsStrokeFontColorType = _settingsService.LyricsStrokeFontColorType;
|
||||
|
||||
LyricsCustomBgFontColor = _settingsService.LyricsCustomBgFontColor;
|
||||
LyricsCustomFgFontColor = _settingsService.LyricsCustomFgFontColor;
|
||||
LyricsCustomStrokeFontColor = _settingsService.LyricsCustomStrokeFontColor;
|
||||
|
||||
LyricsFontStrokeWidth = _settingsService.LyricsFontStrokeWidth;
|
||||
|
||||
LyricsBackgroundTheme = _settingsService.LyricsBackgroundTheme;
|
||||
|
||||
MediaSourceProvidersInfo = [.. _settingsService.MediaSourceProvidersInfo];
|
||||
|
||||
IgnoreFullscreenWindow = _settingsService.IgnoreFullscreenWindow;
|
||||
|
||||
_playbackService.MediaSourceProvidersInfoChanged += PlaybackService_SessionIdsChanged;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
BuildDate = (await AppInfo.GetBuildDate()).ToString("(yyyy/MM/dd HH:mm:ss)");
|
||||
BuildDate = (await Helper.AppInfo.GetBuildDate()).ToString("(yyyy/MM/dd HH:mm:ss)");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -75,6 +99,10 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
MediaSourceProvidersInfo = [.. e.MediaSourceProviersInfo];
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial ElementTheme LyricsBackgroundTheme { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial AutoStartWindowType AutoStartWindowType { get; set; }
|
||||
|
||||
@@ -140,11 +168,27 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial Color LyricsCustomFontColor { get; set; }
|
||||
public partial Color LyricsCustomBgFontColor { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial LyricsFontColorType LyricsFontColorType { get; set; }
|
||||
public partial Color LyricsCustomFgFontColor { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial Color LyricsCustomStrokeFontColor { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial LyricsFontColorType LyricsBgFontColorType { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial LyricsFontColorType LyricsFgFontColorType { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial LyricsFontColorType LyricsStrokeFontColorType { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
@@ -173,6 +217,34 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
public string BuildDate { get; set; } = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string LibreTranslateServer { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial int SelectedTargetLanguageIndex { get; set; } = 0;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsLibreTranslateServerTesting { get; set; } = false;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial int LyricsFontStrokeWidth { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial bool IgnoreFullscreenWindow { get; set; }
|
||||
|
||||
partial void OnLyricsBackgroundThemeChanged(ElementTheme value)
|
||||
{
|
||||
_settingsService.LyricsBackgroundTheme = value;
|
||||
}
|
||||
|
||||
partial void OnLyricsFontStrokeWidthChanged(int value)
|
||||
{
|
||||
_settingsService.LyricsFontStrokeWidth = value;
|
||||
}
|
||||
|
||||
public void OnLyricsSearchProvidersReordered()
|
||||
{
|
||||
_settingsService.LyricsSearchProvidersInfo = [.. LyricsSearchProvidersInfo];
|
||||
@@ -223,64 +295,22 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private void AddFolderAsync(string path)
|
||||
{
|
||||
var normalizedPath =
|
||||
Path.GetFullPath(path).TrimEnd(Path.DirectorySeparatorChar)
|
||||
+ Path.DirectorySeparatorChar;
|
||||
var normalizedPath = Path.GetFullPath(path).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
|
||||
|
||||
if (
|
||||
LocalLyricsFolders.Any(x =>
|
||||
Path.GetFullPath(x.Path)
|
||||
.TrimEnd(Path.DirectorySeparatorChar)
|
||||
.Equals(
|
||||
normalizedPath.TrimEnd(Path.DirectorySeparatorChar),
|
||||
StringComparison.OrdinalIgnoreCase
|
||||
)
|
||||
)
|
||||
)
|
||||
if (LocalLyricsFolders.Any(x => Path.GetFullPath(x.Path).TrimEnd(Path.DirectorySeparatorChar).Equals(normalizedPath.TrimEnd(Path.DirectorySeparatorChar), StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send(
|
||||
new ShowNotificatonMessage(
|
||||
new Notification(
|
||||
App.ResourceLoader!.GetString("SettingsPagePathExistedInfo")
|
||||
)
|
||||
)
|
||||
);
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPagePathExistedInfo"));
|
||||
}
|
||||
else if (
|
||||
LocalLyricsFolders.Any(item =>
|
||||
normalizedPath.StartsWith(
|
||||
Path.GetFullPath(item.Path).TrimEnd(Path.DirectorySeparatorChar)
|
||||
+ Path.DirectorySeparatorChar,
|
||||
StringComparison.OrdinalIgnoreCase
|
||||
)
|
||||
)
|
||||
)
|
||||
else if (LocalLyricsFolders.Any(item => normalizedPath.StartsWith(Path.GetFullPath(item.Path).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
// 添加的文件夹是现有文件夹的子文件夹
|
||||
WeakReferenceMessenger.Default.Send(
|
||||
new ShowNotificatonMessage(
|
||||
new Notification(
|
||||
App.ResourceLoader!.GetString("SettingsPagePathBeIncludedInfo")
|
||||
)
|
||||
)
|
||||
);
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPagePathBeIncludedInfo"));
|
||||
}
|
||||
else if (
|
||||
LocalLyricsFolders.Any(item =>
|
||||
Path.GetFullPath(item.Path)
|
||||
.TrimEnd(Path.DirectorySeparatorChar)
|
||||
.StartsWith(normalizedPath, StringComparison.OrdinalIgnoreCase)
|
||||
)
|
||||
else if (LocalLyricsFolders.Any(item => Path.GetFullPath(item.Path).TrimEnd(Path.DirectorySeparatorChar).StartsWith(normalizedPath, StringComparison.OrdinalIgnoreCase))
|
||||
)
|
||||
{
|
||||
// 添加的文件夹是现有文件夹的父文件夹
|
||||
WeakReferenceMessenger.Default.Send(
|
||||
new ShowNotificatonMessage(
|
||||
new Notification(
|
||||
App.ResourceLoader!.GetString("SettingsPagePathIncludingOthersInfo")
|
||||
)
|
||||
)
|
||||
);
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPagePathIncludingOthersInfo"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -347,6 +377,79 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void LibreTranslateServerTest()
|
||||
{
|
||||
IsLibreTranslateServerTesting = true;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string result = await _libreTranslateService.TranslateAsync("Hello, world!", null);
|
||||
_dispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageLibreTranslateTestSuccessInfo"), Microsoft.UI.Xaml.Controls.InfoBarSeverity.Success);
|
||||
IsLibreTranslateServerTesting = false;
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageLibreTranslateTestFailedInfo"), Microsoft.UI.Xaml.Controls.InfoBarSeverity.Error);
|
||||
IsLibreTranslateServerTesting = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<bool> ToggleAutoStartupAsync(bool target)
|
||||
{
|
||||
StartupTask startupTask = await StartupTask.GetAsync(_autoStartupTaskId);
|
||||
if (target)
|
||||
{
|
||||
await startupTask.RequestEnableAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
startupTask.Disable();
|
||||
}
|
||||
return await DetectIsAutoStartupEnabledAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> DetectIsAutoStartupEnabledAsync()
|
||||
{
|
||||
bool result = false;
|
||||
var startupTask = await StartupTask.GetAsync(_autoStartupTaskId);
|
||||
switch (startupTask.State)
|
||||
{
|
||||
case StartupTaskState.Disabled:
|
||||
case StartupTaskState.DisabledByUser:
|
||||
case StartupTaskState.DisabledByPolicy:
|
||||
result = false;
|
||||
break;
|
||||
case StartupTaskState.Enabled:
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
partial void OnIgnoreFullscreenWindowChanged(bool value)
|
||||
{
|
||||
_settingsService.IgnoreFullscreenWindow = value;
|
||||
}
|
||||
|
||||
partial void OnSelectedTargetLanguageIndexChanged(int value)
|
||||
{
|
||||
_settingsService.SelectedTargetLanguageIndex = value;
|
||||
}
|
||||
|
||||
partial void OnLibreTranslateServerChanged(string value)
|
||||
{
|
||||
_settingsService.LibreTranslateServer = value;
|
||||
}
|
||||
|
||||
partial void OnAutoStartWindowTypeChanged(AutoStartWindowType value)
|
||||
{
|
||||
_settingsService.AutoStartWindowType = value;
|
||||
@@ -430,14 +533,34 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_settingsService.LyricsBlurAmount = value;
|
||||
}
|
||||
|
||||
partial void OnLyricsCustomFontColorChanged(Color value)
|
||||
partial void OnLyricsCustomBgFontColorChanged(Color value)
|
||||
{
|
||||
_settingsService.LyricsCustomFontColor = value;
|
||||
_settingsService.LyricsCustomBgFontColor = value;
|
||||
}
|
||||
|
||||
partial void OnLyricsFontColorTypeChanged(LyricsFontColorType value)
|
||||
partial void OnLyricsCustomFgFontColorChanged(Color value)
|
||||
{
|
||||
_settingsService.LyricsFontColorType = value;
|
||||
_settingsService.LyricsCustomFgFontColor = value;
|
||||
}
|
||||
|
||||
partial void OnLyricsCustomStrokeFontColorChanged(Color value)
|
||||
{
|
||||
_settingsService.LyricsCustomStrokeFontColor = value;
|
||||
}
|
||||
|
||||
partial void OnLyricsBgFontColorTypeChanged(LyricsFontColorType value)
|
||||
{
|
||||
_settingsService.LyricsBgFontColorType = value;
|
||||
}
|
||||
|
||||
partial void OnLyricsFgFontColorTypeChanged(LyricsFontColorType value)
|
||||
{
|
||||
_settingsService.LyricsFgFontColorType = value;
|
||||
}
|
||||
|
||||
partial void OnLyricsStrokeFontColorTypeChanged(LyricsFontColorType value)
|
||||
{
|
||||
_settingsService.LyricsStrokeFontColorType = value;
|
||||
}
|
||||
|
||||
partial void OnLyricsFontSizeChanged(int value)
|
||||
|
||||
@@ -40,24 +40,12 @@
|
||||
Padding="12"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="Transparent"
|
||||
Opacity="0">
|
||||
Opacity="0"
|
||||
PointerEntered="BottomCommandGrid_PointerEntered"
|
||||
PointerExited="BottomCommandGrid_PointerExited">
|
||||
<Grid.OpacityTransition>
|
||||
<ScalarTransition />
|
||||
</Grid.OpacityTransition>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:EventTriggerBehavior EventName="PointerEntered">
|
||||
<interactivity:ChangePropertyAction
|
||||
PropertyName="Opacity"
|
||||
TargetObject="{x:Bind BottomCommandGrid}"
|
||||
Value="1" />
|
||||
</interactivity:EventTriggerBehavior>
|
||||
<interactivity:EventTriggerBehavior EventName="PointerExited">
|
||||
<interactivity:ChangePropertyAction
|
||||
PropertyName="Opacity"
|
||||
TargetObject="{x:Bind BottomCommandGrid}"
|
||||
Value="0" />
|
||||
</interactivity:EventTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
|
||||
<StackPanel
|
||||
x:Name="BottomLeftCommandStackPanel"
|
||||
@@ -98,6 +86,9 @@
|
||||
<RotateTransform Angle="90" CenterX="0.5" CenterY="0.5" />
|
||||
</FontIcon.RenderTransform>
|
||||
</FontIcon>
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Name="TimelineOffsetToolTip" x:Uid="LyricsPageTimelineOffsetButtonToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<StackPanel>
|
||||
@@ -120,8 +111,10 @@
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
RelativePanel.AlignRightWithPanel="True"
|
||||
RelativePanel.AlignVerticalCenterWithPanel="True" />
|
||||
RelativePanel.AlignVerticalCenterWithPanel="True"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
</RelativePanel>
|
||||
<TextBlock Opacity="0.5" x:Uid="LyricsPagePositionOffsetHint"/>
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
@@ -132,7 +125,11 @@
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsChecked="{x:Bind ViewModel.IsTranslationEnabled, Mode=TwoWay}"
|
||||
Style="{StaticResource GhostToggleButtonStyle}" />
|
||||
Style="{StaticResource GhostToggleButtonStyle}">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Name="TranslationToolTip" x:Uid="LyricsPageTranslationButtonToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
</ToggleButton>
|
||||
|
||||
<!-- Display type -->
|
||||
<Button
|
||||
@@ -141,9 +138,9 @@
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}">
|
||||
<Button.OpacityTransition>
|
||||
<ScalarTransition />
|
||||
</Button.OpacityTransition>
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Name="PresentationTypeToolTip" x:Uid="LyricsPageDisplayTypeButtonToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<Flyout.FlyoutPresenterStyle>
|
||||
@@ -167,7 +164,11 @@
|
||||
Command="{x:Bind ViewModel.OpenSettingsWindowCommand}"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
Style="{StaticResource GhostButtonStyle}">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Name="SettingsToolTip" x:Uid="LyricsPageSettingsButtonToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
@@ -178,7 +179,7 @@
|
||||
x:Uid="MainPageWelcomeTeachingTip"
|
||||
Closed="WelcomeTeachingTip_Closed"
|
||||
IsOpen="{x:Bind ViewModel.IsWelcomeTeachingTipOpen, Mode=OneWay}"
|
||||
Target="{x:Bind SettingsButton}" />
|
||||
Target="{x:Bind RootGrid}" />
|
||||
|
||||
<uc:SystemTray />
|
||||
|
||||
|
||||
@@ -45,5 +45,15 @@ namespace BetterLyrics.WinUI3.Views
|
||||
{
|
||||
ViewModel.PositionOffset = 0;
|
||||
}
|
||||
|
||||
private void BottomCommandGrid_PointerEntered(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
|
||||
{
|
||||
BottomCommandGrid.Opacity = 1;
|
||||
}
|
||||
|
||||
private void BottomCommandGrid_PointerExited(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
|
||||
{
|
||||
BottomCommandGrid.Opacity = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Views"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:media="using:CommunityToolkit.WinUI.Media"
|
||||
xmlns:scontrols="using:ShadowViewer.Controls"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
<Window.SystemBackdrop>
|
||||
@@ -24,24 +25,12 @@
|
||||
x:Name="TopCommandGrid"
|
||||
VerticalAlignment="Top"
|
||||
Background="Transparent"
|
||||
Opacity="0">
|
||||
Opacity="0"
|
||||
PointerEntered="TopCommandGrid_PointerEntered"
|
||||
PointerExited="TopCommandGrid_PointerExited">
|
||||
<Grid.OpacityTransition>
|
||||
<ScalarTransition />
|
||||
</Grid.OpacityTransition>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:EventTriggerBehavior EventName="PointerEntered">
|
||||
<interactivity:ChangePropertyAction
|
||||
PropertyName="Opacity"
|
||||
TargetObject="{x:Bind TopCommandGrid}"
|
||||
Value="1" />
|
||||
</interactivity:EventTriggerBehavior>
|
||||
<interactivity:EventTriggerBehavior EventName="PointerExited">
|
||||
<interactivity:ChangePropertyAction
|
||||
PropertyName="Opacity"
|
||||
TargetObject="{x:Bind TopCommandGrid}"
|
||||
Value="0" />
|
||||
</interactivity:EventTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
|
||||
<StackPanel
|
||||
x:Name="TopLeftCommandStackPanel"
|
||||
@@ -74,20 +63,6 @@
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Name="LockToolTip" x:Uid="HostWindowLockToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:EventTriggerBehavior EventName="PointerEntered">
|
||||
<interactivity:ChangePropertyAction
|
||||
PropertyName="IsOpen"
|
||||
TargetObject="{x:Bind LockToolTip}"
|
||||
Value="True" />
|
||||
</interactivity:EventTriggerBehavior>
|
||||
<interactivity:EventTriggerBehavior EventName="PointerExited">
|
||||
<interactivity:ChangePropertyAction
|
||||
PropertyName="IsOpen"
|
||||
TargetObject="{x:Bind LockToolTip}"
|
||||
Value="False" />
|
||||
</interactivity:EventTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</Button>
|
||||
<!-- More -->
|
||||
<Button x:Name="MoreButton" Style="{StaticResource TitleBarButtonStyle}">
|
||||
@@ -95,6 +70,9 @@
|
||||
FontFamily="{StaticResource IconFontFamily}"
|
||||
FontSize="{x:Bind ViewModel.TitleBarFontSize, Mode=OneWay}"
|
||||
Glyph="" />
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Name="MoreButtonToolTip" x:Uid="HostWindowMoreButtonToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<ToggleMenuFlyoutItem
|
||||
@@ -135,7 +113,7 @@
|
||||
<FontIcon
|
||||
FontFamily="{StaticResource IconFontFamily}"
|
||||
FontSize="{x:Bind ViewModel.TitleBarFontSize, Mode=OneWay}"
|
||||
Glyph="" />
|
||||
Glyph="" />
|
||||
</Button>
|
||||
<!-- Window Maximise -->
|
||||
<Button
|
||||
@@ -145,7 +123,7 @@
|
||||
<FontIcon
|
||||
FontFamily="{StaticResource IconFontFamily}"
|
||||
FontSize="{x:Bind ViewModel.TitleBarFontSize, Mode=OneWay}"
|
||||
Glyph="" />
|
||||
Glyph="" />
|
||||
</Button>
|
||||
<!-- Window Restore -->
|
||||
<Button
|
||||
@@ -156,7 +134,7 @@
|
||||
<FontIcon
|
||||
FontFamily="{StaticResource IconFontFamily}"
|
||||
FontSize="{x:Bind ViewModel.TitleBarFontSize, Mode=OneWay}"
|
||||
Glyph="" />
|
||||
Glyph="" />
|
||||
</Button>
|
||||
<!-- Window Close -->
|
||||
<Button
|
||||
@@ -166,54 +144,22 @@
|
||||
<FontIcon
|
||||
FontFamily="{StaticResource IconFontFamily}"
|
||||
FontSize="{x:Bind ViewModel.TitleBarFontSize, Mode=OneWay}"
|
||||
Glyph="" />
|
||||
Glyph="" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
|
||||
<InfoBar
|
||||
x:Name="HostInfoBar"
|
||||
Margin="36"
|
||||
<scontrols:NotificationPanel
|
||||
x:Name="TipContainerCenter"
|
||||
Margin="0,0,0,52"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="{ThemeResource SystemFillColorSolidAttentionBackgroundBrush}"
|
||||
IsClosable="False"
|
||||
IsOpen="{x:Bind ViewModel.ShowInfoBar, Mode=OneWay}"
|
||||
Message="{x:Bind ViewModel.Notification.Message, Mode=OneWay}"
|
||||
Opacity="0"
|
||||
Severity="{x:Bind ViewModel.Notification.Severity, Mode=OneWay}">
|
||||
<InfoBar.RenderTransform>
|
||||
<TranslateTransform x:Name="HostInfoBarTransform" Y="20" />
|
||||
</InfoBar.RenderTransform>
|
||||
<InfoBar.Resources>
|
||||
<Storyboard x:Key="InfoBarShowAndHideStoryboard">
|
||||
<!-- Opacity -->
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="HostInfoBar" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:3.6" Value="1" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:3.9" Value="0" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
|
||||
<!-- Y -->
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="HostInfoBarTransform" Storyboard.TargetProperty="Y">
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="20" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:3.6" Value="0" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:3.9" Value="20" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</InfoBar.Resources>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{Binding ElementName=HostInfoBar, Path=IsOpen, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="True">
|
||||
<interactivity:ControlStoryboardAction Storyboard="{StaticResource InfoBarShowAndHideStoryboard}" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</InfoBar>
|
||||
Canvas.ZIndex="1"
|
||||
FlowDirection="RightToLeft"
|
||||
Loaded="TipContainerCenter_Loaded"
|
||||
Orientation="Vertical"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -252,5 +252,20 @@ namespace BetterLyrics.WinUI3.Views
|
||||
presenter.Restore();
|
||||
}
|
||||
}
|
||||
|
||||
private void TopCommandGrid_PointerEntered(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
TopCommandGrid.Opacity = 1;
|
||||
}
|
||||
|
||||
private void TopCommandGrid_PointerExited(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
TopCommandGrid.Opacity = 0;
|
||||
}
|
||||
|
||||
private void TipContainerCenter_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
App.Current.LyricsWindowNotificationPanel = TipContainerCenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Views"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:models="using:BetterLyrics.WinUI3.Models"
|
||||
xmlns:scontrols="using:ShadowViewer.Controls"
|
||||
xmlns:uc="using:BetterLyrics.WinUI3.Controls"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
xmlns:vm="using:BetterLyrics.WinUI3.ViewModels"
|
||||
@@ -111,19 +112,25 @@
|
||||
|
||||
<TextBlock x:Uid="SettingsPageAppBehavior" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
<controls:SettingsCard x:Uid="SettingsPageAutoStartWindow">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AutoStartWindowType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartInAppLyrics" />
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartDockLyrics" />
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartDesktopLyrics" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageAutoStart" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch x:Name="AutoStartupToggleSwitch" Loaded="AutoStartupToggleSwitch_Loaded" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageAutoLock">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AutoLockOnDesktopMode, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</StackPanel>
|
||||
<controls:SettingsCard x:Uid="SettingsPageAutoStartWindow" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.AutoStartWindowType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartInAppLyrics" />
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartDockLyrics" />
|
||||
<ComboBoxItem x:Uid="SettingsPageAutoStartDesktopLyrics" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageAutoLock" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AutoLockOnDesktopMode, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageIgnoreFullscreenWindow" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.IgnoreFullscreenWindow, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
</StackPanel>
|
||||
</controls:Case>
|
||||
@@ -132,11 +139,19 @@
|
||||
<controls:Case Value="Background">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDynamicLyricsBackground">
|
||||
<controls:SettingsCard x:Uid="SettingsPageTheme" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox x:Name="ThemeComboBox" SelectedIndex="{x:Bind ViewModel.LyricsBackgroundTheme, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageFollowSystem" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLight" />
|
||||
<ComboBoxItem x:Uid="SettingsPageDark" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDynamicLyricsBackground" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.IsDynamicCoverOverlayEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBackgroundOpacity">
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBackgroundOpacity" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock x:Uid="SettingsPageSliderPrefix" VerticalAlignment="Center" />
|
||||
<TextBlock VerticalAlignment="Center" Text="{x:Bind ViewModel.CoverOverlayOpacity, Mode=OneWay}" />
|
||||
@@ -155,7 +170,7 @@
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBackgroundBlurAmount">
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBackgroundBlurAmount" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock x:Uid="SettingsPageSliderPrefix" VerticalAlignment="Center" />
|
||||
<TextBlock
|
||||
@@ -379,8 +394,26 @@
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsFontColor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.LyricsFontColorType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsFontStrokeWidth" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock x:Uid="SettingsPageSliderPrefix" VerticalAlignment="Center" />
|
||||
<TextBlock
|
||||
Margin="0,0,14,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind ViewModel.LyricsFontStrokeWidth, Mode=OneWay}" />
|
||||
<Slider
|
||||
Maximum="5"
|
||||
Minimum="0"
|
||||
SnapsTo="Ticks"
|
||||
StepFrequency="1"
|
||||
TickFrequency="1"
|
||||
TickPlacement="Outside"
|
||||
Value="{x:Bind ViewModel.LyricsFontStrokeWidth, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsStrokeFontColor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.LyricsStrokeFontColorType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveColored" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveGrayed" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorCustom" />
|
||||
@@ -396,16 +429,84 @@
|
||||
IsColorSliderVisible="True"
|
||||
IsHexInputVisible="True"
|
||||
IsMoreButtonVisible="True"
|
||||
Color="{x:Bind ViewModel.LyricsCustomFontColor, Mode=TwoWay}">
|
||||
Color="{x:Bind ViewModel.LyricsCustomStrokeFontColor, Mode=TwoWay}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
Binding="{x:Bind ViewModel.LyricsStrokeFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
Binding="{x:Bind ViewModel.LyricsStrokeFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ColorPicker>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsBgFontColor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.LyricsBgFontColorType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveColored" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveGrayed" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorCustom" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<ColorPicker
|
||||
ColorSpectrumShape="Box"
|
||||
IsAlphaEnabled="True"
|
||||
IsAlphaSliderVisible="True"
|
||||
IsAlphaTextInputVisible="True"
|
||||
IsColorChannelTextInputVisible="True"
|
||||
IsColorSliderVisible="True"
|
||||
IsHexInputVisible="True"
|
||||
IsMoreButtonVisible="True"
|
||||
Color="{x:Bind ViewModel.LyricsCustomBgFontColor, Mode=TwoWay}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsBgFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsBgFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ColorPicker>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsFgFontColor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.LyricsFgFontColorType, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveColored" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorAdaptiveGrayed" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsFontColorCustom" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<ColorPicker
|
||||
ColorSpectrumShape="Box"
|
||||
IsAlphaEnabled="True"
|
||||
IsAlphaSliderVisible="True"
|
||||
IsAlphaTextInputVisible="True"
|
||||
IsColorChannelTextInputVisible="True"
|
||||
IsColorSliderVisible="True"
|
||||
IsHexInputVisible="True"
|
||||
IsMoreButtonVisible="True"
|
||||
Color="{x:Bind ViewModel.LyricsCustomFgFontColor, Mode=TwoWay}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsFgFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.LyricsFgFontColorType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
|
||||
ComparisonCondition="NotEqual"
|
||||
Value="2">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
@@ -524,11 +625,70 @@
|
||||
<!-- Lyrics translation -->
|
||||
<controls:Case Value="Translation">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
<controls:SettingsExpander>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox Text="http://127.0.0.1:5000" />
|
||||
<Button Content="Verify" />
|
||||
</StackPanel>
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageTranslationConfig"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="True">
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageLibreTranslateServer">
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<TextBox
|
||||
x:Name="LibreTranslateServerTextBox"
|
||||
IsEnabled="{x:Bind ViewModel.IsLibreTranslateServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}"
|
||||
PlaceholderText="http://localhost:5000"
|
||||
Text="{x:Bind ViewModel.LibreTranslateServer, Mode=TwoWay}" />
|
||||
<Button
|
||||
x:Uid="SettingsPageServerTestButton"
|
||||
Command="{x:Bind ViewModel.LibreTranslateServerTestCommand}"
|
||||
IsEnabled="{x:Bind ViewModel.IsLibreTranslateServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageTargetLanguage">
|
||||
<ComboBox SelectedIndex="{x:Bind ViewModel.SelectedTargetLanguageIndex, Mode=TwoWay}">
|
||||
<ComboBoxItem Content="العربية" Tag="ar" />
|
||||
<ComboBoxItem Content="Azərbaycan dili" Tag="az" />
|
||||
<ComboBoxItem Content="中文" Tag="zh" />
|
||||
<ComboBoxItem Content="Čeština" Tag="cs" />
|
||||
<ComboBoxItem Content="Dansk" Tag="da" />
|
||||
<ComboBoxItem Content="Nederlands" Tag="nl" />
|
||||
<ComboBoxItem Content="English" Tag="en" />
|
||||
<ComboBoxItem Content="Esperanto" Tag="eo" />
|
||||
<ComboBoxItem Content="Suomi" Tag="fi" />
|
||||
<ComboBoxItem Content="Français" Tag="fr" />
|
||||
<ComboBoxItem Content="Deutsch" Tag="de" />
|
||||
<ComboBoxItem Content="Ελληνικά" Tag="el" />
|
||||
<ComboBoxItem Content="עברית" Tag="he" />
|
||||
<ComboBoxItem Content="हिन्दी" Tag="hi" />
|
||||
<ComboBoxItem Content="Magyar" Tag="hu" />
|
||||
<ComboBoxItem Content="Bahasa Indonesia" Tag="id" />
|
||||
<ComboBoxItem Content="Gaeilge" Tag="ga" />
|
||||
<ComboBoxItem Content="Italiano" Tag="it" />
|
||||
<ComboBoxItem Content="日本語" Tag="ja" />
|
||||
<ComboBoxItem Content="한국어" Tag="ko" />
|
||||
<ComboBoxItem Content="فارسی" Tag="fa" />
|
||||
<ComboBoxItem Content="Polski" Tag="pl" />
|
||||
<ComboBoxItem Content="Português" Tag="pt" />
|
||||
<ComboBoxItem Content="Русский" Tag="ru" />
|
||||
<ComboBoxItem Content="Slovenčina" Tag="sk" />
|
||||
<ComboBoxItem Content="Español" Tag="es" />
|
||||
<ComboBoxItem Content="Svenska" Tag="sv" />
|
||||
<ComboBoxItem Content="Türkçe" Tag="tr" />
|
||||
<ComboBoxItem Content="Українська" Tag="uk" />
|
||||
<ComboBoxItem Content="Tiếng Việt" Tag="vi" />
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageTranslationInfo">
|
||||
<controls:SettingsCard.Description>
|
||||
<HyperlinkButton Margin="0,6,0,0" NavigateUri="https://github.com/LibreTranslate/LibreTranslate">
|
||||
<TextBlock
|
||||
x:Uid="SettingsPageTranslationInfoLink"
|
||||
FontSize="14"
|
||||
TextWrapping="Wrap" />
|
||||
</HyperlinkButton>
|
||||
</controls:SettingsCard.Description>
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
</StackPanel>
|
||||
</controls:Case>
|
||||
@@ -583,5 +743,16 @@
|
||||
</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>
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace BetterLyrics.WinUI3.Views
|
||||
{
|
||||
public sealed partial class SettingsPage : Page
|
||||
{
|
||||
private bool _isUserToggle;
|
||||
|
||||
public SettingsPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -87,5 +89,21 @@ 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();
|
||||
AutoStartupToggleSwitch.Toggled += AutoStartupToggleSwitch_Toggled;
|
||||
}
|
||||
|
||||
private void AutoStartupToggleSwitch_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.ToggleAutoStartupAsync(AutoStartupToggleSwitch.IsOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user