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\AppSettingsControl.xaml" />
<None Remove="Controls\ExtendedSlider.xaml" />
<None Remove="Controls\LyricsBavkgroundSettingsControl.xaml" />
<None Remove="Controls\LyricsSettingsControl.xaml" />
<None Remove="Controls\MediaSettingsControl.xaml" />
<None Remove="Controls\PlaybackSettingsControl.xaml" />
@@ -61,6 +60,7 @@
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" />
<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="Microsoft.Extensions.DependencyInjection" 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="z440.atl.core" Version="7.2.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="Hqub.Lastfm">
<HintPath>..\..\..\Last.fm\src\Hqub.Lastfm\bin\Release\netstandard2.0\Hqub.Lastfm.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Page Update="Rendering\InAppLyricsRenderer.xaml">
<Generator>MSBuild:Compile</Generator>
@@ -222,7 +217,7 @@
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Controls\LyricsBavkgroundSettingsControl.xaml">
<Page Update="Controls\LyricsBackgroundSettingsControl.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>

View File

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

View File

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

View File

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

View File

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

View File

@@ -24,6 +24,14 @@
FontSize=12,
Glyph=&#xE894;}"
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>
</Grid>
</UserControl>

View File

@@ -1,3 +1,4 @@
using BetterLyrics.WinUI3.Helper;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
@@ -91,5 +92,22 @@ namespace BetterLyrics.WinUI3.Controls
Shortcut = [];
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
{
private static Dictionary<int, Action> _hotKeyActions = [];
private static Dictionary<int, Action> _actions = [];
private static Dictionary<int, List<string>> _keys = [];
/// <summary>
/// Register a global hotkey for a specific window type
@@ -22,7 +23,7 @@ namespace BetterLyrics.WinUI3.Helper
/// <param name="id"></param>
/// <param name="keys"></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;
@@ -55,18 +56,23 @@ namespace BetterLyrics.WinUI3.Helper
key = (VirtualKey)Enum.Parse(typeof(VirtualKey), item, true);
}
}
User32.RegisterHotKey(hwnd, (int)id, modifiers, (uint)key);
_hotKeyActions[(int)id] = action;
bool success = User32.RegisterHotKey(hwnd, (int)id, modifiers, (uint)key);
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>();
if (window == null) return;
HWND hwnd = WindowNative.GetWindowHandle(window);
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)
@@ -75,6 +81,16 @@ namespace BetterLyrics.WinUI3.Helper
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)
{
return TryInvokeAction((int)id);
@@ -82,7 +98,7 @@ namespace BetterLyrics.WinUI3.Helper
public static bool TryInvokeAction(int id)
{
if (_hotKeyActions.TryGetValue(id, out var action))
if (_actions.TryGetValue(id, out var action))
{
action?.Invoke();
return true;

View File

@@ -72,9 +72,9 @@ namespace BetterLyrics.WinUI3.Services
code = code switch
{
"simple" => "en",
"zh_classical" => "zh-Hant",
"zh_yue" => "zh-Hant",
"zh" => "zh-Hans",
"zh_classical" => SimplifiedChineseOrTraditionalChinese(text),
"zh_yue" => SimplifiedChineseOrTraditionalChinese(text),
"zh" => SimplifiedChineseOrTraditionalChinese(text),
_ => 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
using System;
using System.Diagnostics;
using BetterLyrics.WinUI3.Enums;
namespace BetterLyrics.WinUI3.Helper
@@ -11,6 +10,8 @@ namespace BetterLyrics.WinUI3.Helper
{
private T _currentValue;
private double _durationSeconds;
private double _delaySeconds;
private double _delayRemaining;
private EasingType? _easingType;
private Func<T, T, double, T> _interpolator;
private bool _isTransitioning;
@@ -19,18 +20,21 @@ namespace BetterLyrics.WinUI3.Helper
private T _targetValue;
public double DurationSeconds => _durationSeconds;
public double DelaySeconds => _delaySeconds;
public bool IsTransitioning => _isTransitioning;
public T Value => _currentValue;
public T TargetValue => _targetValue;
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;
_startValue = initialValue;
_targetValue = initialValue;
_durationSeconds = durationSeconds;
_delaySeconds = delaySeconds;
_delayRemaining = 0;
_progress = 1f;
_isTransitioning = false;
@@ -58,12 +62,18 @@ namespace BetterLyrics.WinUI3.Helper
_durationSeconds = seconds;
}
public void SetDelay(double seconds)
{
_delaySeconds = seconds;
}
private void JumpTo(T value)
{
_currentValue = value;
_startValue = value;
_targetValue = value;
_progress = 1f;
_delayRemaining = 0;
_isTransitioning = false;
}
@@ -73,6 +83,7 @@ namespace BetterLyrics.WinUI3.Helper
_startValue = value;
_targetValue = value;
_progress = 0f;
_delayRemaining = 0;
_isTransitioning = false;
}
@@ -89,6 +100,7 @@ namespace BetterLyrics.WinUI3.Helper
_startValue = _currentValue;
_targetValue = targetValue;
_progress = 0f;
_delayRemaining = _delaySeconds;
_isTransitioning = true;
}
}
@@ -103,7 +115,24 @@ namespace BetterLyrics.WinUI3.Helper
{
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)
{
_progress = 1f;
@@ -178,4 +207,4 @@ namespace BetterLyrics.WinUI3.Helper
_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 LyricsScrollTopDuration { 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 bool IsFanLyricsEnabled { get; set; } = false;

View File

@@ -4,11 +4,13 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
namespace BetterLyrics.WinUI3.Models.Settings
{
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" };
public PictureInPictureModeSettings()

View File

@@ -13,7 +13,8 @@ namespace BetterLyrics.WinUI3.Models.Settings
public partial class StandardModeSettings : BaseModeSettings
{
[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()
{
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)
{
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;

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)
{
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);

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Storage.Streams;
@@ -21,46 +22,48 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
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(
SongInfo?.SourceAppUserModelId ?? "",
_cachedSongInfo.Title,
_cachedSongInfo.Artist,
_cachedSongInfo?.Album ?? string.Empty,
_SMTCAlbumArtBytes
);
byte[]? bytes = await _albumArtSearchService.SearchAsync(
SongInfo?.SourceAppUserModelId ?? "",
_cachedSongInfo.Title,
_cachedSongInfo.Artist,
_cachedSongInfo?.Album ?? string.Empty,
_SMTCAlbumArtBytes
);
token.ThrowIfCancellationRequested();
if (bytes == null)
{
bytes = await ImageHelper.CreateTextPlaceholderBytesAsync(500, 500);
token.ThrowIfCancellationRequested();
}
if (bytes == null)
{
bytes = await ImageHelper.CreateTextPlaceholderBytesAsync(500, 500);
token.ThrowIfCancellationRequested();
}
bytes = ImageHelper.MakeSquareWithThemeColor(bytes);
bytes = ImageHelper.MakeSquareWithThemeColor(bytes);
using var stream = new InMemoryRandomAccessStream();
await stream.WriteAsync(bytes.AsBuffer());
token.ThrowIfCancellationRequested();
using var stream = new InMemoryRandomAccessStream();
await stream.WriteAsync(bytes.AsBuffer());
token.ThrowIfCancellationRequested();
var decoder = await BitmapDecoder.CreateAsync(stream);
token.ThrowIfCancellationRequested();
var decoder = await BitmapDecoder.CreateAsync(stream);
token.ThrowIfCancellationRequested();
var albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba16, BitmapAlphaMode.Premultiplied);
token.ThrowIfCancellationRequested();
var albumArtSwBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Rgba16, BitmapAlphaMode.Premultiplied);
token.ThrowIfCancellationRequested();
var albumArtLightAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, false).FirstOrDefault();
var albumArtDarkAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, true).FirstOrDefault();
var albumArtLightAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, false).FirstOrDefault();
var albumArtDarkAccentColor = ImageHelper.GetAccentColorsFromByte(bytes, 1, true).FirstOrDefault();
AlbumArtChanged?.Invoke(this, new AlbumArtChangedEventArgs(null, albumArtSwBitmap, albumArtLightAccentColor, albumArtDarkAccentColor));
});
AlbumArtChanged?.Invoke(this, new AlbumArtChangedEventArgs(null, albumArtSwBitmap, albumArtLightAccentColor, albumArtDarkAccentColor));
}
}
}

View File

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

View File

@@ -201,26 +201,29 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
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;
if (mediaSession == null) return;
var focusedSession = _mediaManager.GetFocusedSession();
if (mediaSession != focusedSession) return;
if (!IsMediaSourceEnabled(mediaSession.Id))
_cachedPosition = TimeSpan.Zero;
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
_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));
}
});
});
}
}
private void MediaManager_OnAnyPlaybackStateChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo)

View File

@@ -150,9 +150,6 @@
<data name="BaseWindowMiniFlyoutItem.Text" xml:space="preserve">
<value>Picture-in-picture mode</value>
</data>
<data name="BaseWindowUnMiniFlyoutItem.Text" xml:space="preserve">
<value>Exit picture-in-picture mode</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancel</value>
</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">
<value>Activate standard mode</value>
</data>
<data name="SettingsPageAutoStartPIPLyrics.Content" xml:space="preserve">
<value>Start Picture-in-Picture Mode</value>
</data>
<data name="SettingsPageAutoStartWindow.Header" xml:space="preserve">
<value>When starting the app</value>
</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">
<value>Scope</value>
</data>
<data name="SettingsPageScrollBottomDelay.Header" xml:space="preserve">
<value>Tail line delay</value>
</data>
<data name="SettingsPageScrollBottomDuration.Header" xml:space="preserve">
<value>Lyrics scrolling animation duration (Last line)</value>
<value>Final line duration</value>
</data>
<data name="SettingsPageScrollDuration.Header" xml:space="preserve">
<value>Lyrics scrolling animation duration (Current line)</value>
<value>Current line duration</value>
</data>
<data name="SettingsPageScrollEasing.Header" xml:space="preserve">
<value>Lyrics scrolling animation type</value>
</data>
<data name="SettingsPageScrollTopDelay.Header" xml:space="preserve">
<value>First line delay</value>
</data>
<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 name="SettingsPageServerTestButton.Content" xml:space="preserve">
<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">
<value>Settings manager</value>
</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">
<value>Current value: </value>
</data>

View File

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

View File

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

View File

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

View File

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

View File

@@ -167,6 +167,14 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
{
_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)
{

View File

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

View File

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

View File

@@ -20,6 +20,7 @@ namespace BetterLyrics.WinUI3.Views
{
private readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService<ISettingsService>();
private readonly WindowMessageMonitor _wmm;
private bool _autoSelectLyricsModeOnRunning = true;
public LyricsWindow()
{
@@ -75,8 +76,17 @@ namespace BetterLyrics.WinUI3.Views
switch (type!)
{
case LyricsWindowMode.StandardMode:
AppWindow.MoveAndResize(_settingsService.AppSettings.StandardModeSettings.WindowBounds.ToRectInt32());
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;
case LyricsWindowMode.DockMode:
ViewModel.ToggleDockMode();
@@ -84,9 +94,13 @@ namespace BetterLyrics.WinUI3.Views
case LyricsWindowMode.DesktopMode:
ViewModel.ToggleDesktopMode();
break;
case LyricsWindowMode.PictureInPictureMode:
ViewModel.TogglePictureInPictureMode();
break;
default:
break;
}
_autoSelectLyricsModeOnRunning = false;
}
private void AOTFlyoutItem_Click(object sender, RoutedEventArgs e)
@@ -96,6 +110,8 @@ namespace BetterLyrics.WinUI3.Views
private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
{
if (_autoSelectLyricsModeOnRunning) return;
if (args.DidPositionChange || args.DidSizeChange)
{
var size = AppWindow.Size;
@@ -107,14 +123,28 @@ namespace BetterLyrics.WinUI3.Views
}
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);
}
else if (ViewModel.LiveStates.CurrentLyricsWindowMode == LyricsWindowMode.DockMode) { }
else
{
_settingsService.AppSettings.StandardModeSettings.WindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height);
case LyricsWindowMode.StandardMode:
if (AppWindow.Presenter is OverlappedPresenter overlappedPresenter)
{
_settingsService.AppSettings.StandardModeSettings.WindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height);
_settingsService.AppSettings.StandardModeSettings.IsMaximized = overlappedPresenter.State == OverlappedPresenterState.Maximized;
}
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 -->
<controls:Case Value="Background">
<uc:LyricsBavkgroundSettingsControl />
<uc:LyricsBackgroundSettingsControl />
</controls:Case>
<!-- Album art area style -->