This commit is contained in:
Zhe Fang
2025-08-17 20:49:45 -04:00
parent ad33eed57c
commit 516d388009
29 changed files with 346 additions and 125 deletions

View File

@@ -26,7 +26,6 @@
<None Remove="Controls\AllLyricsSettingsControl.xaml" /> <None Remove="Controls\AllLyricsSettingsControl.xaml" />
<None Remove="Controls\AppSettingsControl.xaml" /> <None Remove="Controls\AppSettingsControl.xaml" />
<None Remove="Controls\ExtendedSlider.xaml" /> <None Remove="Controls\ExtendedSlider.xaml" />
<None Remove="Controls\LyricsBavkgroundSettingsControl.xaml" />
<None Remove="Controls\LyricsSettingsControl.xaml" /> <None Remove="Controls\LyricsSettingsControl.xaml" />
<None Remove="Controls\MediaSettingsControl.xaml" /> <None Remove="Controls\MediaSettingsControl.xaml" />
<None Remove="Controls\PlaybackSettingsControl.xaml" /> <None Remove="Controls\PlaybackSettingsControl.xaml" />
@@ -61,6 +60,7 @@
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" /> <PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" /> <PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" />
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.3.0" /> <PackageReference Include="H.NotifyIcon.WinUI" Version="2.3.0" />
<PackageReference Include="Hqub.Last.fm" Version="2.5.1" />
<PackageReference Include="Lyricify.Lyrics.Helper-NativeAot" Version="0.1.4-alpha.5" /> <PackageReference Include="Lyricify.Lyrics.Helper-NativeAot" Version="0.1.4-alpha.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.8" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.8" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.8" />
@@ -87,11 +87,6 @@
<PackageReference Include="WinUIEx" Version="2.6.0" /> <PackageReference Include="WinUIEx" Version="2.6.0" />
<PackageReference Include="z440.atl.core" Version="7.2.0" /> <PackageReference Include="z440.atl.core" Version="7.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Reference Include="Hqub.Lastfm">
<HintPath>..\..\..\Last.fm\src\Hqub.Lastfm\bin\Release\netstandard2.0\Hqub.Lastfm.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Page Update="Rendering\InAppLyricsRenderer.xaml"> <Page Update="Rendering\InAppLyricsRenderer.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@@ -222,7 +217,7 @@
</Page> </Page>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Update="Controls\LyricsBavkgroundSettingsControl.xaml"> <Page Update="Controls\LyricsBackgroundSettingsControl.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
</ItemGroup> </ItemGroup>

View File

@@ -55,6 +55,7 @@
<ComboBoxItem x:Uid="SettingsPageAutoStartInAppLyrics" /> <ComboBoxItem x:Uid="SettingsPageAutoStartInAppLyrics" />
<ComboBoxItem x:Uid="SettingsPageAutoStartDockLyrics" /> <ComboBoxItem x:Uid="SettingsPageAutoStartDockLyrics" />
<ComboBoxItem x:Uid="SettingsPageAutoStartDesktopLyrics" /> <ComboBoxItem x:Uid="SettingsPageAutoStartDesktopLyrics" />
<ComboBoxItem x:Uid="SettingsPageAutoStartPIPLyrics" />
</ComboBox> </ComboBox>
</controls:SettingsCard> </controls:SettingsCard>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<UserControl <UserControl
x:Class="BetterLyrics.WinUI3.Controls.LyricsBavkgroundSettingsControl" x:Class="BetterLyrics.WinUI3.Controls.LyricsBackgroundSettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:CommunityToolkit.WinUI.Controls" xmlns:controls="using:CommunityToolkit.WinUI.Controls"

View File

@@ -20,11 +20,11 @@ using Windows.Foundation.Collections;
namespace BetterLyrics.WinUI3.Controls namespace BetterLyrics.WinUI3.Controls
{ {
public sealed partial class LyricsBavkgroundSettingsControl : UserControl public sealed partial class LyricsBackgroundSettingsControl : UserControl
{ {
public LyricsBackgroundSettingsControlViewModel ViewModel => (LyricsBackgroundSettingsControlViewModel)DataContext; public LyricsBackgroundSettingsControlViewModel ViewModel => (LyricsBackgroundSettingsControlViewModel)DataContext;
public LyricsBavkgroundSettingsControl() public LyricsBackgroundSettingsControl()
{ {
InitializeComponent(); InitializeComponent();
DataContext = Ioc.Default.GetRequiredService<LyricsBackgroundSettingsControlViewModel>(); DataContext = Ioc.Default.GetRequiredService<LyricsBackgroundSettingsControlViewModel>();

View File

@@ -319,6 +319,7 @@
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsFanLyricsEnabled, Mode=TwoWay}" /> <ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsFanLyricsEnabled, Mode=TwoWay}" />
</controls:SettingsCard> </controls:SettingsCard>
<!-- 滚动动画 -->
<controls:SettingsExpander <controls:SettingsExpander
x:Uid="SettingsPageScrollEasing" x:Uid="SettingsPageScrollEasing"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
@@ -341,7 +342,6 @@
<controls:SettingsExpander.Items> <controls:SettingsExpander.Items>
<controls:SettingsCard x:Uid="SettingsPageScrollTopDuration"> <controls:SettingsCard x:Uid="SettingsPageScrollTopDuration">
<local:ExtendedSlider <local:ExtendedSlider
x:Uid="SettingsPageLyricsScrollTopDurationExtendedSlider"
Default="500" Default="500"
Frequency="50" Frequency="50"
Maximum="1000" Maximum="1000"
@@ -351,7 +351,6 @@
</controls:SettingsCard> </controls:SettingsCard>
<controls:SettingsCard x:Uid="SettingsPageScrollDuration"> <controls:SettingsCard x:Uid="SettingsPageScrollDuration">
<local:ExtendedSlider <local:ExtendedSlider
x:Uid="SettingsPageLyricsScrollDurationExtendedSlider"
Default="500" Default="500"
Frequency="50" Frequency="50"
Maximum="1000" Maximum="1000"
@@ -361,7 +360,6 @@
</controls:SettingsCard> </controls:SettingsCard>
<controls:SettingsCard x:Uid="SettingsPageScrollBottomDuration"> <controls:SettingsCard x:Uid="SettingsPageScrollBottomDuration">
<local:ExtendedSlider <local:ExtendedSlider
x:Uid="SettingsPageLyricsScrollBottomDurationExtendedSlider"
Default="500" Default="500"
Frequency="50" Frequency="50"
Maximum="1000" Maximum="1000"
@@ -369,6 +367,24 @@
Unit="ms" Unit="ms"
Value="{x:Bind LyricsEffectSettings.LyricsScrollBottomDuration, Mode=TwoWay}" /> Value="{x:Bind LyricsEffectSettings.LyricsScrollBottomDuration, Mode=TwoWay}" />
</controls:SettingsCard> </controls:SettingsCard>
<controls:SettingsCard x:Uid="SettingsPageScrollTopDelay">
<local:ExtendedSlider
Default="0"
Frequency="50"
Maximum="2000"
Minimum="0"
Unit="ms"
Value="{x:Bind LyricsEffectSettings.LyricsScrollTopDelay, Mode=TwoWay}" />
</controls:SettingsCard>
<controls:SettingsCard x:Uid="SettingsPageScrollBottomDelay">
<local:ExtendedSlider
Default="0"
Frequency="50"
Maximum="2000"
Minimum="0"
Unit="ms"
Value="{x:Bind LyricsEffectSettings.LyricsScrollBottomDelay, Mode=TwoWay}" />
</controls:SettingsCard>
</controls:SettingsExpander.Items> </controls:SettingsExpander.Items>
</controls:SettingsExpander> </controls:SettingsExpander>

View File

@@ -24,6 +24,14 @@
FontSize=12, FontSize=12,
Glyph=&#xE894;}" Glyph=&#xE894;}"
Style="{StaticResource GhostButtonStyle}" /> Style="{StaticResource GhostButtonStyle}" />
<Button
Margin="3,0,0,0"
HorizontalAlignment="Right"
Click="CheckButton_Click"
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
FontSize=12,
Glyph=&#xE721;}"
Style="{StaticResource GhostButtonStyle}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@@ -1,3 +1,4 @@
using BetterLyrics.WinUI3.Helper;
using Microsoft.UI.Input; using Microsoft.UI.Input;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
@@ -91,5 +92,22 @@ namespace BetterLyrics.WinUI3.Controls
Shortcut = []; Shortcut = [];
UpdateTextBox(); UpdateTextBox();
} }
private void CheckButton_Click(object sender, RoutedEventArgs e)
{
bool registered = GlobalHotKeyHelper.IsHotKeyRegistered(Shortcut);
if (registered)
{
App.Current.SettingsWindowNotificationPanel?.Notify(
App.ResourceLoader!.GetString("SettingsPageShortcutRegSuccessInfo"),
InfoBarSeverity.Success);
}
else
{
App.Current.SettingsWindowNotificationPanel?.Notify(
App.ResourceLoader!.GetString("SettingsPageShortcutRegFailInfo"),
InfoBarSeverity.Error);
}
}
} }
} }

View File

@@ -13,7 +13,8 @@ namespace BetterLyrics.WinUI3.Helper
{ {
public class GlobalHotKeyHelper public class GlobalHotKeyHelper
{ {
private static Dictionary<int, Action> _hotKeyActions = []; private static Dictionary<int, Action> _actions = [];
private static Dictionary<int, List<string>> _keys = [];
/// <summary> /// <summary>
/// Register a global hotkey for a specific window type /// Register a global hotkey for a specific window type
@@ -22,7 +23,7 @@ namespace BetterLyrics.WinUI3.Helper
/// <param name="id"></param> /// <param name="id"></param>
/// <param name="keys"></param> /// <param name="keys"></param>
/// <param name="action"></param> /// <param name="action"></param>
public static void RegisterHotKey<T>(ShortcutID id, List<string> keys, Action action) private static void RegisterHotKey<T>(ShortcutID id, List<string> keys, Action action)
{ {
if (keys.Count == 0) return; if (keys.Count == 0) return;
@@ -55,18 +56,23 @@ namespace BetterLyrics.WinUI3.Helper
key = (VirtualKey)Enum.Parse(typeof(VirtualKey), item, true); key = (VirtualKey)Enum.Parse(typeof(VirtualKey), item, true);
} }
} }
User32.RegisterHotKey(hwnd, (int)id, modifiers, (uint)key); bool success = User32.RegisterHotKey(hwnd, (int)id, modifiers, (uint)key);
_hotKeyActions[(int)id] = action; if (success)
{
_actions[(int)id] = action;
_keys[(int)id] = keys;
}
} }
public static void UnregisterHotKey<T>(ShortcutID id) private static void UnregisterHotKey<T>(ShortcutID id)
{ {
var window = WindowHelper.GetWindowByWindowType<T>(); var window = WindowHelper.GetWindowByWindowType<T>();
if (window == null) return; if (window == null) return;
HWND hwnd = WindowNative.GetWindowHandle(window); HWND hwnd = WindowNative.GetWindowHandle(window);
User32.UnregisterHotKey(hwnd, (int)id); User32.UnregisterHotKey(hwnd, (int)id);
_hotKeyActions.Remove((int)id); _actions.Remove((int)id);
_keys.Remove((int)id);
} }
public static void UpdateHotKey<T>(ShortcutID id, List<string> keys, Action action) public static void UpdateHotKey<T>(ShortcutID id, List<string> keys, Action action)
@@ -75,6 +81,16 @@ namespace BetterLyrics.WinUI3.Helper
RegisterHotKey<T>(id, keys, action); RegisterHotKey<T>(id, keys, action);
} }
public static bool IsHotKeyRegistered(ShortcutID id)
{
return _actions.ContainsKey((int)id);
}
public static bool IsHotKeyRegistered(List<string> keys)
{
return _keys.ContainsValue(keys);
}
public static bool TryInvokeAction(ShortcutID id) public static bool TryInvokeAction(ShortcutID id)
{ {
return TryInvokeAction((int)id); return TryInvokeAction((int)id);
@@ -82,7 +98,7 @@ namespace BetterLyrics.WinUI3.Helper
public static bool TryInvokeAction(int id) public static bool TryInvokeAction(int id)
{ {
if (_hotKeyActions.TryGetValue(id, out var action)) if (_actions.TryGetValue(id, out var action))
{ {
action?.Invoke(); action?.Invoke();
return true; return true;

View File

@@ -72,9 +72,9 @@ namespace BetterLyrics.WinUI3.Services
code = code switch code = code switch
{ {
"simple" => "en", "simple" => "en",
"zh_classical" => "zh-Hant", "zh_classical" => SimplifiedChineseOrTraditionalChinese(text),
"zh_yue" => "zh-Hant", "zh_yue" => SimplifiedChineseOrTraditionalChinese(text),
"zh" => "zh-Hans", "zh" => SimplifiedChineseOrTraditionalChinese(text),
_ => code _ => code
}; };
return code; return code;

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Graphics;
namespace BetterLyrics.WinUI3.Helper
{
public static class PointHelper
{
public static PointInt32 ToPointInt32(this Point point)
{
return new PointInt32((int)point.X, (int)point.Y);
}
}
}

View File

@@ -1,7 +1,6 @@
// 2025/6/23 by Zhe Fang // 2025/6/23 by Zhe Fang
using System; using System;
using System.Diagnostics;
using BetterLyrics.WinUI3.Enums; using BetterLyrics.WinUI3.Enums;
namespace BetterLyrics.WinUI3.Helper namespace BetterLyrics.WinUI3.Helper
@@ -11,6 +10,8 @@ namespace BetterLyrics.WinUI3.Helper
{ {
private T _currentValue; private T _currentValue;
private double _durationSeconds; private double _durationSeconds;
private double _delaySeconds;
private double _delayRemaining;
private EasingType? _easingType; private EasingType? _easingType;
private Func<T, T, double, T> _interpolator; private Func<T, T, double, T> _interpolator;
private bool _isTransitioning; private bool _isTransitioning;
@@ -19,18 +20,21 @@ namespace BetterLyrics.WinUI3.Helper
private T _targetValue; private T _targetValue;
public double DurationSeconds => _durationSeconds; public double DurationSeconds => _durationSeconds;
public double DelaySeconds => _delaySeconds;
public bool IsTransitioning => _isTransitioning; public bool IsTransitioning => _isTransitioning;
public T Value => _currentValue; public T Value => _currentValue;
public T TargetValue => _targetValue; public T TargetValue => _targetValue;
public EasingType? EasingType => _easingType; public EasingType? EasingType => _easingType;
public ValueTransition(T initialValue, double durationSeconds, Func<T, T, double, T>? interpolator = null, EasingType? easingType = null) public ValueTransition(T initialValue, double durationSeconds, Func<T, T, double, T>? interpolator = null, EasingType? easingType = null, double delaySeconds = 0)
{ {
_currentValue = initialValue; _currentValue = initialValue;
_startValue = initialValue; _startValue = initialValue;
_targetValue = initialValue; _targetValue = initialValue;
_durationSeconds = durationSeconds; _durationSeconds = durationSeconds;
_delaySeconds = delaySeconds;
_delayRemaining = 0;
_progress = 1f; _progress = 1f;
_isTransitioning = false; _isTransitioning = false;
@@ -58,12 +62,18 @@ namespace BetterLyrics.WinUI3.Helper
_durationSeconds = seconds; _durationSeconds = seconds;
} }
public void SetDelay(double seconds)
{
_delaySeconds = seconds;
}
private void JumpTo(T value) private void JumpTo(T value)
{ {
_currentValue = value; _currentValue = value;
_startValue = value; _startValue = value;
_targetValue = value; _targetValue = value;
_progress = 1f; _progress = 1f;
_delayRemaining = 0;
_isTransitioning = false; _isTransitioning = false;
} }
@@ -73,6 +83,7 @@ namespace BetterLyrics.WinUI3.Helper
_startValue = value; _startValue = value;
_targetValue = value; _targetValue = value;
_progress = 0f; _progress = 0f;
_delayRemaining = 0;
_isTransitioning = false; _isTransitioning = false;
} }
@@ -89,6 +100,7 @@ namespace BetterLyrics.WinUI3.Helper
_startValue = _currentValue; _startValue = _currentValue;
_targetValue = targetValue; _targetValue = targetValue;
_progress = 0f; _progress = 0f;
_delayRemaining = _delaySeconds;
_isTransitioning = true; _isTransitioning = true;
} }
} }
@@ -103,7 +115,24 @@ namespace BetterLyrics.WinUI3.Helper
{ {
if (!_isTransitioning) return; if (!_isTransitioning) return;
_progress += (double)(elapsedTime / TimeSpan.FromSeconds(_durationSeconds)); if (_delayRemaining > 0)
{
double consume = Math.Min(_delayRemaining, elapsedTime.TotalSeconds);
_delayRemaining -= consume;
if (_delayRemaining > 0)
return;
elapsedTime = TimeSpan.FromSeconds(elapsedTime.TotalSeconds - consume);
}
if (_durationSeconds <= 0)
{
_progress = 1f;
}
else
{
_progress += elapsedTime.TotalSeconds / _durationSeconds;
}
if (_progress >= 1f) if (_progress >= 1f)
{ {
_progress = 1f; _progress = 1f;
@@ -178,4 +207,4 @@ namespace BetterLyrics.WinUI3.Helper
_interpolator = GetInterpolatorByEasingType(easingType); _interpolator = GetInterpolatorByEasingType(easingType);
} }
} }
} }

View File

@@ -31,6 +31,8 @@ namespace BetterLyrics.WinUI3.Models.Settings
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollDuration { get; set; } [ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollDuration { get; set; }
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollTopDuration { get; set; } [ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollTopDuration { get; set; }
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollBottomDuration { get; set; } [ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollBottomDuration { get; set; }
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollTopDelay { get; set; } = 0;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsScrollBottomDelay { get; set; } = 0;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsVerticalEdgeOpacity { get; set; } = 0; // 0% opacity [ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsVerticalEdgeOpacity { get; set; } = 0; // 0% opacity
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsFanLyricsEnabled { get; set; } = false; [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsFanLyricsEnabled { get; set; } = false;

View File

@@ -4,11 +4,13 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Windows.Foundation;
namespace BetterLyrics.WinUI3.Models.Settings namespace BetterLyrics.WinUI3.Models.Settings
{ {
public partial class PictureInPictureModeSettings : BaseModeSettings public partial class PictureInPictureModeSettings : BaseModeSettings
{ {
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Point WindowPosition { get; set; } = new Point(100, 100);
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> ToggleShortcut { get; set; } = new List<string>() { "Ctrl", "Shift", "P" }; [ObservableProperty][NotifyPropertyChangedRecipients] public partial List<string> ToggleShortcut { get; set; } = new List<string>() { "Ctrl", "Shift", "P" };
public PictureInPictureModeSettings() public PictureInPictureModeSettings()

View File

@@ -13,7 +13,8 @@ namespace BetterLyrics.WinUI3.Models.Settings
public partial class StandardModeSettings : BaseModeSettings public partial class StandardModeSettings : BaseModeSettings
{ {
[ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect WindowBounds { get; set; } = new Rect(100, 100, 1000, 600); [ObservableProperty][NotifyPropertyChangedRecipients] public partial Rect WindowBounds { get; set; } = new Rect(100, 100, 1000, 600);
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsMaximized { get; set; } = false;
public StandardModeSettings() public StandardModeSettings()
{ {
LyricsDisplayType = LyricsDisplayType.SplitView; LyricsDisplayType = LyricsDisplayType.SplitView;

View File

@@ -31,6 +31,11 @@ namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
} }
public async Task<byte[]?> SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null) public async Task<byte[]?> SearchAsync(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null)
{
return await Task.Run(async () => await SearchAsyncCore(mediaSessionId, title, artist, album, bytesFromSMTC));
}
public async Task<byte[]?> SearchAsyncCore(string mediaSessionId, string title, string artist, string album, byte[]? bytesFromSMTC = null)
{ {
byte[]? result = null; byte[]? result = null;

View File

@@ -88,6 +88,11 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
} }
public async Task<(string?, LyricsSearchProvider?)> SearchAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token) public async Task<(string?, LyricsSearchProvider?)> SearchAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
{
return await Task.Run(async () => await SearchAsyncCore(mediaSessionId, title, artist, album, durationMs, token), token);
}
private async Task<(string?, LyricsSearchProvider?)> SearchAsyncCore(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
{ {
_logger.LogInformation("Searching img 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);

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime; using System.Runtime.InteropServices.WindowsRuntime;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Windows.Graphics.Imaging; using Windows.Graphics.Imaging;
using Windows.Storage.Streams; using Windows.Storage.Streams;
@@ -21,46 +22,48 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
private void UpdateAlbumArt() private void UpdateAlbumArt()
{ {
_albumArtRefreshRunner.RunAsync(async (token) => _albumArtRefreshRunner.RunAsync(RefreshArtAlbum);
}
private async Task RefreshArtAlbum(CancellationToken token)
{
if (_cachedSongInfo == null)
{ {
if (_cachedSongInfo == null) _logger.LogWarning("Cached song info is null, cannot update album art.");
{ return;
_logger.LogWarning("Cached song info is null, cannot update album art."); }
return;
}
byte[]? bytes = await _albumArtSearchService.SearchAsync( byte[]? bytes = await _albumArtSearchService.SearchAsync(
SongInfo?.SourceAppUserModelId ?? "", SongInfo?.SourceAppUserModelId ?? "",
_cachedSongInfo.Title, _cachedSongInfo.Title,
_cachedSongInfo.Artist, _cachedSongInfo.Artist,
_cachedSongInfo?.Album ?? string.Empty, _cachedSongInfo?.Album ?? string.Empty,
_SMTCAlbumArtBytes _SMTCAlbumArtBytes
); );
token.ThrowIfCancellationRequested();
if (bytes == null)
{
bytes = await ImageHelper.CreateTextPlaceholderBytesAsync(500, 500);
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
}
if (bytes == null) bytes = ImageHelper.MakeSquareWithThemeColor(bytes);
{
bytes = await ImageHelper.CreateTextPlaceholderBytesAsync(500, 500);
token.ThrowIfCancellationRequested();
}
bytes = ImageHelper.MakeSquareWithThemeColor(bytes); using var stream = new InMemoryRandomAccessStream();
await stream.WriteAsync(bytes.AsBuffer());
token.ThrowIfCancellationRequested();
using var stream = new InMemoryRandomAccessStream(); var decoder = await BitmapDecoder.CreateAsync(stream);
await stream.WriteAsync(bytes.AsBuffer()); token.ThrowIfCancellationRequested();
token.ThrowIfCancellationRequested();
var decoder = await BitmapDecoder.CreateAsync(stream); var albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba16, BitmapAlphaMode.Premultiplied);
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
var albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba16, BitmapAlphaMode.Premultiplied); var albumArtLightAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, false).FirstOrDefault();
token.ThrowIfCancellationRequested(); var albumArtDarkAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, true).FirstOrDefault();
var albumArtLightAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, false).FirstOrDefault(); AlbumArtChanged?.Invoke(this, new AlbumArtChangedEventArgs(null, albumArtSwBitmap, albumArtLightAccentColor, albumArtDarkAccentColor));
var albumArtDarkAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, true).FirstOrDefault();
AlbumArtChanged?.Invoke(this, new AlbumArtChangedEventArgs(null, albumArtSwBitmap, albumArtLightAccentColor, albumArtDarkAccentColor));
});
} }
} }
} }

View File

@@ -10,6 +10,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Vanara.PInvoke;
namespace BetterLyrics.WinUI3.Services.MediaSessionsService namespace BetterLyrics.WinUI3.Services.MediaSessionsService
{ {
@@ -220,10 +221,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
private void UpdateLyrics() private void UpdateLyrics()
{ {
_refreshLyricsRunner.RunAsync(async token => _refreshLyricsRunner.RunAsync(RefreshLyricsAsync);
{
await RefreshLyricsAsync(token);
});
} }
} }
} }

View File

@@ -201,26 +201,29 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
private void MediaManager_OnAnyTimelinePropertyChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionTimelineProperties timelineProperties) private void MediaManager_OnAnyTimelinePropertyChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionTimelineProperties timelineProperties)
{ {
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () => if (!_mediaManager.IsStarted) return;
if (mediaSession == null) return;
var focusedSession = _mediaManager.GetFocusedSession();
if (mediaSession != focusedSession) return;
if (!IsMediaSourceEnabled(mediaSession.Id))
{ {
if (!_mediaManager.IsStarted) return; _cachedPosition = TimeSpan.Zero;
if (mediaSession == null) return; _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
var focusedSession = _mediaManager.GetFocusedSession();
if (mediaSession != focusedSession) return;
if (!IsMediaSourceEnabled(mediaSession.Id))
{ {
_cachedPosition = TimeSpan.Zero;
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, TimeSpan.Zero)); TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, TimeSpan.Zero));
} });
else }
else
{
_cachedPosition = timelineProperties.Position;
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{ {
_cachedPosition = timelineProperties.Position;
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, timelineProperties.EndTime)); TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, timelineProperties.EndTime));
} });
}); }
} }
private void MediaManager_OnAnyPlaybackStateChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo) private void MediaManager_OnAnyPlaybackStateChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo)

View File

@@ -150,9 +150,6 @@
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve"> <data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
<value>Picture-in-picture mode</value> <value>Picture-in-picture mode</value>
</data> </data>
<data name="BaseWindowUnMiniFlyoutItem.Text" xml:space="preserve">
<value>Exit picture-in-picture mode</value>
</data>
<data name="Cancel" xml:space="preserve"> <data name="Cancel" xml:space="preserve">
<value>Cancel</value> <value>Cancel</value>
</data> </data>
@@ -478,6 +475,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve"> <data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
<value>Activate standard mode</value> <value>Activate standard mode</value>
</data> </data>
<data name="SettingsPageAutoStartPIPLyrics.Content" xml:space="preserve">
<value>Start Picture-in-Picture Mode</value>
</data>
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve"> <data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
<value>When starting the app</value> <value>When starting the app</value>
</data> </data>
@@ -934,17 +934,23 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
<data name="SettingsPageScope.Header" xml:space="preserve"> <data name="SettingsPageScope.Header" xml:space="preserve">
<value>Scope</value> <value>Scope</value>
</data> </data>
<data name="SettingsPageScrollBottomDelay.Header" xml:space="preserve">
<value>Tail line delay</value>
</data>
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
<value>Lyrics scrolling animation duration (Last line)</value> <value>Final line duration</value>
</data> </data>
<data name="SettingsPageScrollDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollDuration.Header" xml:space="preserve">
<value>Lyrics scrolling animation duration (Current line)</value> <value>Current line duration</value>
</data> </data>
<data name="SettingsPageScrollEasing.Header" xml:space="preserve"> <data name="SettingsPageScrollEasing.Header" xml:space="preserve">
<value>Lyrics scrolling animation type</value> <value>Lyrics scrolling animation type</value>
</data> </data>
<data name="SettingsPageScrollTopDelay.Header" xml:space="preserve">
<value>First line delay</value>
</data>
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
<value>Lyrics scrolling animation duration (First line)</value> <value>The duration of the first line</value>
</data> </data>
<data name="SettingsPageServerTestButton.Content" xml:space="preserve"> <data name="SettingsPageServerTestButton.Content" xml:space="preserve">
<value>Test server</value> <value>Test server</value>
@@ -958,6 +964,12 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
<data name="SettingsPageSettingsManager.Header" xml:space="preserve"> <data name="SettingsPageSettingsManager.Header" xml:space="preserve">
<value>Settings manager</value> <value>Settings manager</value>
</data> </data>
<data name="SettingsPageShortcutRegFailInfo" xml:space="preserve">
<value>This hotkey was not successfully registered</value>
</data>
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
<value>This hotkey has been successfully registered</value>
</data>
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve"> <data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
<value>Current value: </value> <value>Current value: </value>
</data> </data>

View File

@@ -150,9 +150,6 @@
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve"> <data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
<value>ピクチャーインピクチャーモード</value> <value>ピクチャーインピクチャーモード</value>
</data> </data>
<data name="BaseWindowUnMiniFlyoutItem.Text" xml:space="preserve">
<value>ピクチャーインピクチャーモードを終了します</value>
</data>
<data name="Cancel" xml:space="preserve"> <data name="Cancel" xml:space="preserve">
<value>キャンセル</value> <value>キャンセル</value>
</data> </data>
@@ -478,6 +475,9 @@
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve"> <data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
<value>標準モードをアクティブにします</value> <value>標準モードをアクティブにします</value>
</data> </data>
<data name="SettingsPageAutoStartPIPLyrics.Content" xml:space="preserve">
<value>ピクチャーインピクチャーモードを開始します</value>
</data>
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve"> <data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
<value>アプリを起動するとき</value> <value>アプリを起動するとき</value>
</data> </data>
@@ -934,17 +934,23 @@
<data name="SettingsPageScope.Header" xml:space="preserve"> <data name="SettingsPageScope.Header" xml:space="preserve">
<value>範囲</value> <value>範囲</value>
</data> </data>
<data name="SettingsPageScrollBottomDelay.Header" xml:space="preserve">
<value>テールラインの遅延</value>
</data>
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
<value>歌詞スクロールアニメーション期間(最終行)</value> <value>最終ライン期間</value>
</data> </data>
<data name="SettingsPageScrollDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollDuration.Header" xml:space="preserve">
<value>歌詞スクロールアニメーション期間(現在の行)</value> <value>現在のライン期間</value>
</data> </data>
<data name="SettingsPageScrollEasing.Header" xml:space="preserve"> <data name="SettingsPageScrollEasing.Header" xml:space="preserve">
<value>歌詞スクロールアニメーションタイプ</value> <value>歌詞スクロールアニメーションタイプ</value>
</data> </data>
<data name="SettingsPageScrollTopDelay.Header" xml:space="preserve">
<value>最初の行の遅延</value>
</data>
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
<value>歌詞スクロールアニメーション期間(最初の行</value> <value>最初の行の期間</value>
</data> </data>
<data name="SettingsPageServerTestButton.Content" xml:space="preserve"> <data name="SettingsPageServerTestButton.Content" xml:space="preserve">
<value>テストサーバー</value> <value>テストサーバー</value>
@@ -958,6 +964,12 @@
<data name="SettingsPageSettingsManager.Header" xml:space="preserve"> <data name="SettingsPageSettingsManager.Header" xml:space="preserve">
<value>設定マネージャー</value> <value>設定マネージャー</value>
</data> </data>
<data name="SettingsPageShortcutRegFailInfo" xml:space="preserve">
<value>このホットキーは正常に登録されていません</value>
</data>
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
<value>このホットキーは正常に登録されています</value>
</data>
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve"> <data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
<value>現在の値: </value> <value>現在の値: </value>
</data> </data>

View File

@@ -150,9 +150,6 @@
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve"> <data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
<value>사진 인당 모드</value> <value>사진 인당 모드</value>
</data> </data>
<data name="BaseWindowUnMiniFlyoutItem.Text" xml:space="preserve">
<value>Picture-in-Picture 모드 종료</value>
</data>
<data name="Cancel" xml:space="preserve"> <data name="Cancel" xml:space="preserve">
<value>취소</value> <value>취소</value>
</data> </data>
@@ -478,6 +475,9 @@
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve"> <data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
<value>표준 모드를 ​​활성화합니다</value> <value>표준 모드를 ​​활성화합니다</value>
</data> </data>
<data name="SettingsPageAutoStartPIPLyrics.Content" xml:space="preserve">
<value>Picture-in-Picture 모드를 시작하십시오</value>
</data>
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve"> <data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
<value>앱을 시작할 때</value> <value>앱을 시작할 때</value>
</data> </data>
@@ -934,17 +934,23 @@
<data name="SettingsPageScope.Header" xml:space="preserve"> <data name="SettingsPageScope.Header" xml:space="preserve">
<value>범위</value> <value>범위</value>
</data> </data>
<data name="SettingsPageScrollBottomDelay.Header" xml:space="preserve">
<value>테일 라인 지연</value>
</data>
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
<value>가사 스크롤 애니메이션 지속 시간 (마지막 줄)</value> <value>최종 라인 기간</value>
</data> </data>
<data name="SettingsPageScrollDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollDuration.Header" xml:space="preserve">
<value>가사 스크롤 애니메이션 지속 시간 (현재 줄)</value> <value>현재 라인 기간</value>
</data> </data>
<data name="SettingsPageScrollEasing.Header" xml:space="preserve"> <data name="SettingsPageScrollEasing.Header" xml:space="preserve">
<value>가사 스크롤링 애니메이션 유형</value> <value>가사 스크롤링 애니메이션 유형</value>
</data> </data>
<data name="SettingsPageScrollTopDelay.Header" xml:space="preserve">
<value>첫 번째 줄 지연</value>
</data>
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
<value>가사 스크롤 애니메이션 지속 시간 (첫 번째 줄)</value> <value>첫 번째 줄의 기간</value>
</data> </data>
<data name="SettingsPageServerTestButton.Content" xml:space="preserve"> <data name="SettingsPageServerTestButton.Content" xml:space="preserve">
<value>테스트 서버</value> <value>테스트 서버</value>
@@ -958,6 +964,12 @@
<data name="SettingsPageSettingsManager.Header" xml:space="preserve"> <data name="SettingsPageSettingsManager.Header" xml:space="preserve">
<value>설정 관리자</value> <value>설정 관리자</value>
</data> </data>
<data name="SettingsPageShortcutRegFailInfo" xml:space="preserve">
<value>이 핫키는 성공적으로 등록되지 않았습니다</value>
</data>
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
<value>이 핫키는 성공적으로 등록되었습니다</value>
</data>
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve"> <data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
<value>현재 가치 : </value> <value>현재 가치 : </value>
</data> </data>

View File

@@ -150,9 +150,6 @@
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve"> <data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
<value>画中画模式</value> <value>画中画模式</value>
</data> </data>
<data name="BaseWindowUnMiniFlyoutItem.Text" xml:space="preserve">
<value>退出画中画模式</value>
</data>
<data name="Cancel" xml:space="preserve"> <data name="Cancel" xml:space="preserve">
<value>取消</value> <value>取消</value>
</data> </data>
@@ -478,6 +475,9 @@
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve"> <data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
<value>启动标准模式</value> <value>启动标准模式</value>
</data> </data>
<data name="SettingsPageAutoStartPIPLyrics.Content" xml:space="preserve">
<value>启动画中画模式</value>
</data>
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve"> <data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
<value>启动应用时</value> <value>启动应用时</value>
</data> </data>
@@ -934,17 +934,23 @@
<data name="SettingsPageScope.Header" xml:space="preserve"> <data name="SettingsPageScope.Header" xml:space="preserve">
<value>范围</value> <value>范围</value>
</data> </data>
<data name="SettingsPageScrollBottomDelay.Header" xml:space="preserve">
<value>尾行延时</value>
</data>
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
<value>歌词滚动动画持续时间(最后一行)</value> <value>尾行持续时间</value>
</data> </data>
<data name="SettingsPageScrollDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollDuration.Header" xml:space="preserve">
<value>歌词滚动动画持续时间(当前行)</value> <value>当前行持续时间</value>
</data> </data>
<data name="SettingsPageScrollEasing.Header" xml:space="preserve"> <data name="SettingsPageScrollEasing.Header" xml:space="preserve">
<value>歌词滚动动画类型</value> <value>歌词滚动动画类型</value>
</data> </data>
<data name="SettingsPageScrollTopDelay.Header" xml:space="preserve">
<value>首行延时</value>
</data>
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
<value>歌词滚动动画持续时间(第一行)</value> <value>首行持续时间</value>
</data> </data>
<data name="SettingsPageServerTestButton.Content" xml:space="preserve"> <data name="SettingsPageServerTestButton.Content" xml:space="preserve">
<value>测试服务器</value> <value>测试服务器</value>
@@ -958,6 +964,12 @@
<data name="SettingsPageSettingsManager.Header" xml:space="preserve"> <data name="SettingsPageSettingsManager.Header" xml:space="preserve">
<value>设置管理器</value> <value>设置管理器</value>
</data> </data>
<data name="SettingsPageShortcutRegFailInfo" xml:space="preserve">
<value>该热键未成功注册</value>
</data>
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
<value>该热键已成功注册</value>
</data>
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve"> <data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
<value>当前值: </value> <value>当前值: </value>
</data> </data>

View File

@@ -150,9 +150,6 @@
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve"> <data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
<value>畫中畫模式</value> <value>畫中畫模式</value>
</data> </data>
<data name="BaseWindowUnMiniFlyoutItem.Text" xml:space="preserve">
<value>退出畫中畫模式</value>
</data>
<data name="Cancel" xml:space="preserve"> <data name="Cancel" xml:space="preserve">
<value>取消</value> <value>取消</value>
</data> </data>
@@ -478,6 +475,9 @@
<data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve"> <data name="SettingsPageAutoStartInAppLyrics.Content" xml:space="preserve">
<value>啟動標準模式</value> <value>啟動標準模式</value>
</data> </data>
<data name="SettingsPageAutoStartPIPLyrics.Content" xml:space="preserve">
<value>啟動畫中畫模式</value>
</data>
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve"> <data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
<value>啟動應用程式時</value> <value>啟動應用程式時</value>
</data> </data>
@@ -934,17 +934,23 @@
<data name="SettingsPageScope.Header" xml:space="preserve"> <data name="SettingsPageScope.Header" xml:space="preserve">
<value>範圍</value> <value>範圍</value>
</data> </data>
<data name="SettingsPageScrollBottomDelay.Header" xml:space="preserve">
<value>尾行延時</value>
</data>
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
<value>歌詞滾動動畫持續時間(最後一行)</value> <value>尾行持續時間</value>
</data> </data>
<data name="SettingsPageScrollDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollDuration.Header" xml:space="preserve">
<value>歌詞滾動動畫持續時間(當前行)</value> <value>當前行持續時間</value>
</data> </data>
<data name="SettingsPageScrollEasing.Header" xml:space="preserve"> <data name="SettingsPageScrollEasing.Header" xml:space="preserve">
<value>歌詞滾動動畫類型</value> <value>歌詞滾動動畫類型</value>
</data> </data>
<data name="SettingsPageScrollTopDelay.Header" xml:space="preserve">
<value>首行延時</value>
</data>
<data name="SettingsPageScrollTopDuration.Header" xml:space="preserve"> <data name="SettingsPageScrollTopDuration.Header" xml:space="preserve">
<value>歌詞滾動動畫持續時間(第一行)</value> <value>首行持續時間</value>
</data> </data>
<data name="SettingsPageServerTestButton.Content" xml:space="preserve"> <data name="SettingsPageServerTestButton.Content" xml:space="preserve">
<value>測試服務器</value> <value>測試服務器</value>
@@ -958,6 +964,12 @@
<data name="SettingsPageSettingsManager.Header" xml:space="preserve"> <data name="SettingsPageSettingsManager.Header" xml:space="preserve">
<value>設置管理器</value> <value>設置管理器</value>
</data> </data>
<data name="SettingsPageShortcutRegFailInfo" xml:space="preserve">
<value>該熱鍵未成功註冊</value>
</data>
<data name="SettingsPageShortcutRegSuccessInfo" xml:space="preserve">
<value>該熱鍵已成功註冊</value>
</data>
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve"> <data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
<value>目前值: </value> <value>目前值: </value>
</data> </data>

View File

@@ -167,6 +167,14 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
{ {
_isLayoutChanged = true; _isLayoutChanged = true;
} }
else if (message.PropertyName == nameof(LyricsEffectSettings.LyricsScrollTopDelay))
{
_isLayoutChanged = true;
}
else if (message.PropertyName == nameof(LyricsEffectSettings.LyricsScrollBottomDelay))
{
_isLayoutChanged = true;
}
} }
else if (message.Sender is LyricsStyleSettings) else if (message.Sender is LyricsStyleSettings)
{ {

View File

@@ -589,25 +589,31 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
line.HighlightOpacityTransition.StartTransition(i == _playingLineIndex ? 1f : 0f); line.HighlightOpacityTransition.StartTransition(i == _playingLineIndex ? 1f : 0f);
double yScrollDuration; double yScrollDuration;
double yScrollDelay;
if (lineCountDelta < 0) if (lineCountDelta < 0)
{ {
yScrollDuration = yScrollDuration =
_canvasYScrollTransition.DurationSeconds + _canvasYScrollTransition.DurationSeconds +
distanceFactor * (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollTopDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds); distanceFactor * (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollTopDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds);
yScrollDelay = distanceFactor * _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollTopDelay / 1000.0;
} }
else if (lineCountDelta == 0) else if (lineCountDelta == 0)
{ {
yScrollDuration = _canvasYScrollTransition.DurationSeconds; yScrollDuration = _canvasYScrollTransition.DurationSeconds;
yScrollDelay = 0;
} }
else else
{ {
yScrollDuration = yScrollDuration =
_canvasYScrollTransition.DurationSeconds + _canvasYScrollTransition.DurationSeconds +
distanceFactor * (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollBottomDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds); distanceFactor * (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollBottomDuration / 1000.0 - _canvasYScrollTransition.DurationSeconds);
yScrollDelay = distanceFactor * _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsScrollBottomDelay / 1000.0;
} }
line.YOffsetTransition.SetEasingType(_canvasYScrollTransition.EasingType ?? EasingType.Linear); line.YOffsetTransition.SetEasingType(_canvasYScrollTransition.EasingType ?? EasingType.Linear);
line.YOffsetTransition.SetDuration(yScrollDuration); line.YOffsetTransition.SetDuration(yScrollDuration);
line.YOffsetTransition.SetDelay(yScrollDelay);
line.YOffsetTransition.StartTransition(_canvasTargetYScrollOffset, _isLayoutChanged); line.YOffsetTransition.StartTransition(_canvasTargetYScrollOffset, _isLayoutChanged);
} }

View File

@@ -218,8 +218,7 @@ namespace BetterLyrics.WinUI3
private void UpdateDesktopLockShortcut() private void UpdateDesktopLockShortcut()
{ {
GlobalHotKeyHelper.UnregisterHotKey<LyricsWindow>(ShortcutID.DesktopLock); GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.DesktopLock,
GlobalHotKeyHelper.RegisterHotKey<LyricsWindow>(ShortcutID.DesktopLock,
_settingsService.AppSettings.DesktopModeSettings.LockShortcut, _settingsService.AppSettings.DesktopModeSettings.LockShortcut,
() => () =>
{ {
@@ -233,8 +232,7 @@ namespace BetterLyrics.WinUI3
private void UpdateDesktopToggleShortcut() private void UpdateDesktopToggleShortcut()
{ {
GlobalHotKeyHelper.UnregisterHotKey<LyricsWindow>(ShortcutID.DesktopToggle); GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.DesktopToggle,
GlobalHotKeyHelper.RegisterHotKey<LyricsWindow>(ShortcutID.DesktopToggle,
_settingsService.AppSettings.DesktopModeSettings.ToggleShortcut, _settingsService.AppSettings.DesktopModeSettings.ToggleShortcut,
() => () =>
{ {
@@ -249,8 +247,7 @@ namespace BetterLyrics.WinUI3
private void UpdateDockToggleShortcut() private void UpdateDockToggleShortcut()
{ {
GlobalHotKeyHelper.UnregisterHotKey<LyricsWindow>(ShortcutID.DockToggle); GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.DockToggle,
GlobalHotKeyHelper.RegisterHotKey<LyricsWindow>(ShortcutID.DockToggle,
_settingsService.AppSettings.DockModeSettings.ToggleShortcut, _settingsService.AppSettings.DockModeSettings.ToggleShortcut,
() => () =>
{ {
@@ -265,8 +262,7 @@ namespace BetterLyrics.WinUI3
private void UpdatePictureInPictureToggleShortcut() private void UpdatePictureInPictureToggleShortcut()
{ {
GlobalHotKeyHelper.UnregisterHotKey<LyricsWindow>(ShortcutID.PictureInPictureToggle); GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.PictureInPictureToggle,
GlobalHotKeyHelper.RegisterHotKey<LyricsWindow>(ShortcutID.PictureInPictureToggle,
_settingsService.AppSettings.PictureInPictureModeSettings.ToggleShortcut, _settingsService.AppSettings.PictureInPictureModeSettings.ToggleShortcut,
() => () =>
{ {
@@ -463,6 +459,7 @@ namespace BetterLyrics.WinUI3
if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.PictureInPictureMode) if (LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.PictureInPictureMode)
{ {
window.AppWindow.SetPresenter(AppWindowPresenterKind.CompactOverlay); window.AppWindow.SetPresenter(AppWindowPresenterKind.CompactOverlay);
window.AppWindow.Move(AppSettings.PictureInPictureModeSettings.WindowPosition.ToPointInt32());
SetPIPModeTitleBarControlsStatus(); SetPIPModeTitleBarControlsStatus();
} }
else else

View File

@@ -20,6 +20,7 @@ namespace BetterLyrics.WinUI3.Views
{ {
private readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>(); private readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
private readonly WindowMessageMonitor _wmm; private readonly WindowMessageMonitor _wmm;
private bool _autoSelectLyricsModeOnRunning = true;
public LyricsWindow() public LyricsWindow()
{ {
@@ -75,8 +76,17 @@ namespace BetterLyrics.WinUI3.Views
switch (type!) switch (type!)
{ {
case LyricsWindowMode.StandardMode: case LyricsWindowMode.StandardMode:
AppWindow.MoveAndResize(_settingsService.AppSettings.StandardModeSettings.WindowBounds.ToRectInt32());
ViewModel.SetStandardModeTitleBarControlsStatus(); ViewModel.SetStandardModeTitleBarControlsStatus();
if (_settingsService.AppSettings.StandardModeSettings.IsMaximized)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4>ڴ<EFBFBD>С<EFBFBD>Ա<EFBFBD><D4B1>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>󻯺<EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶ<EFBFBD><DCB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB>ԵӰ<D4B5><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
this.Maximize();
}
else
{
AppWindow.MoveAndResize(_settingsService.AppSettings.StandardModeSettings.WindowBounds.ToRectInt32());
}
break; break;
case LyricsWindowMode.DockMode: case LyricsWindowMode.DockMode:
ViewModel.ToggleDockMode(); ViewModel.ToggleDockMode();
@@ -84,9 +94,13 @@ namespace BetterLyrics.WinUI3.Views
case LyricsWindowMode.DesktopMode: case LyricsWindowMode.DesktopMode:
ViewModel.ToggleDesktopMode(); ViewModel.ToggleDesktopMode();
break; break;
case LyricsWindowMode.PictureInPictureMode:
ViewModel.TogglePictureInPictureMode();
break;
default: default:
break; break;
} }
_autoSelectLyricsModeOnRunning = false;
} }
private void AOTFlyoutItem_Click(object sender, RoutedEventArgs e) private void AOTFlyoutItem_Click(object sender, RoutedEventArgs e)
@@ -96,6 +110,8 @@ namespace BetterLyrics.WinUI3.Views
private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args) private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
{ {
if (_autoSelectLyricsModeOnRunning) return;
if (args.DidPositionChange || args.DidSizeChange) if (args.DidPositionChange || args.DidSizeChange)
{ {
var size = AppWindow.Size; var size = AppWindow.Size;
@@ -107,14 +123,28 @@ namespace BetterLyrics.WinUI3.Views
} }
else else
{ {
if (ViewModel.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DesktopMode) switch (ViewModel.LiveStates.CurrentLyricsWindowMode)
{ {
_settingsService.AppSettings.DesktopModeSettings.WindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height); case LyricsWindowMode.StandardMode:
} if (AppWindow.Presenter is OverlappedPresenter overlappedPresenter)
else if (ViewModel.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode) { } {
else _settingsService.AppSettings.StandardModeSettings.WindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height);
{ _settingsService.AppSettings.StandardModeSettings.IsMaximized = overlappedPresenter.State == OverlappedPresenterState.Maximized;
_settingsService.AppSettings.StandardModeSettings.WindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height); }
break;
case LyricsWindowMode.DockMode:
break;
case LyricsWindowMode.DesktopMode:
_settingsService.AppSettings.DesktopModeSettings.WindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height);
break;
case LyricsWindowMode.PictureInPictureMode:
if (AppWindow.Presenter is CompactOverlayPresenter compactOverlayPresenter)
{
_settingsService.AppSettings.PictureInPictureModeSettings.WindowPosition = new Windows.Foundation.Point(rect.X, rect.Y);
}
break;
default:
break;
} }
} }
} }

View File

@@ -89,7 +89,7 @@
<!-- Lyrics background --> <!-- Lyrics background -->
<controls:Case Value="Background"> <controls:Case Value="Background">
<uc:LyricsBavkgroundSettingsControl /> <uc:LyricsBackgroundSettingsControl />
</controls:Case> </controls:Case>
<!-- Album art area style --> <!-- Album art area style -->