mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-12 10:54:55 +08:00
chores: Add new rule for locally search lyrics (only compare file name)
This commit is contained in:
@@ -53,8 +53,6 @@
|
||||
<converter:AlbumArtSearchProviderToDisplayNameConverter x:Key="AlbumArtSearchProviderToDisplayNameConverter" />
|
||||
<converter:SecondsToFormattedTimeConverter x:Key="SecondsToFormattedTimeConverter" />
|
||||
<converter:MillisecondsToFormattedTimeConverter x:Key="MillisecondsToFormattedTimeConverter" />
|
||||
<converter:MediaSourceProviderToLogoUriConverter x:Key="MediaSourceProviderToLogoUriConverter" />
|
||||
<converter:MediaSourceProviderToDisplayedNameConverter x:Key="MediaSourceProviderToDisplayedNameConverter" />
|
||||
<converter:FPSToTimeSpanConverter x:Key="FPSToTimeSpanConverter" />
|
||||
<converter:ShortcutToStringConverter x:Key="ShortcutToStringConverter" />
|
||||
<converter:BoolNegationToVisibilityConverter x:Key="BoolNegationToVisibilityConverter" />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Services.AlbumArtSearchService;
|
||||
using BetterLyrics.WinUI3.Services.DiscordService;
|
||||
using BetterLyrics.WinUI3.Services.LastFMService;
|
||||
@@ -68,10 +69,10 @@ namespace BetterLyrics.WinUI3
|
||||
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<LyricsWindow>();
|
||||
WindowHook.OpenOrShowWindow<LyricsWindow>();
|
||||
if (Ioc.Default.GetRequiredService<ISettingsService>().AppSettings.MusicGallerySettings.AutoOpen)
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<MusicGalleryWindow>();
|
||||
WindowHook.OpenOrShowWindow<MusicGalleryWindow>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Helpers" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Triggers" Version="8.2.250402" />
|
||||
<PackageReference Include="ComputeSharp.D2D1.WinUI" Version="3.2.0" />
|
||||
<PackageReference Include="csharp-kana" Version="1.0.2" />
|
||||
<PackageReference Include="csharp-pinyin" Version="1.0.1" />
|
||||
<PackageReference Include="DevWinUI.Controls" Version="9.5.0" />
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
namespace BetterLyrics.WinUI3.Collections
|
||||
{
|
||||
// https://stackoverflow.com/a/32013610/11048731
|
||||
public class FullyObservableCollection<T> : ObservableCollection<T>
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Constants
|
||||
{
|
||||
public class ExtendedGenreFiled
|
||||
{
|
||||
public const string NetEaseCloudMusicTrackID = "NCM-";
|
||||
public const string FileName = "FILENAME-";
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@
|
||||
<Grid
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Background="{ThemeResource AcrylicInAppFillColorDefaultBrush}"
|
||||
CornerRadius="12">
|
||||
<FontIcon
|
||||
Margin="20"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
@@ -34,10 +35,10 @@ namespace BetterLyrics.WinUI3.Controls
|
||||
|
||||
private async Task HideAsync()
|
||||
{
|
||||
var lyricsWindowSwitchWindow = WindowHelper.GetWindowByWindowType<LyricsWindowSwitchWindow>();
|
||||
var lyricsWindowSwitchWindow = WindowHook.GetWindowByWindowType<LyricsWindowSwitchWindow>();
|
||||
lyricsWindowSwitchWindow?.ViewModel.RootGridOpacity = 0;
|
||||
await Task.Delay(300);
|
||||
WindowHelper.HideWindow<LyricsWindowSwitchWindow>();
|
||||
WindowHook.HideWindow<LyricsWindowSwitchWindow>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,10 +68,10 @@
|
||||
FontFamily="Segoe UI Symbol"
|
||||
FontSize="12"
|
||||
Glyph="⠿" />
|
||||
<ImageIcon Height="16" Source="{Binding Provider, Converter={StaticResource MediaSourceProviderToLogoUriConverter}, Mode=OneWay}" />
|
||||
<ImageIcon Height="16" Source="{Binding LogoPath, Mode=OneWay}" />
|
||||
<TextBlock
|
||||
MaxWidth="200"
|
||||
Text="{Binding Provider, Converter={StaticResource MediaSourceProviderToDisplayedNameConverter}, Mode=OneWay}"
|
||||
Text="{Binding DisplayName, Mode=OneWay}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
@@ -242,18 +242,54 @@
|
||||
|
||||
<!-- Provider info -->
|
||||
<TextBlock x:Uid="SettingsPageRealtimeStatus" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<dev:SettingsCard x:Uid="LyricsPageLyricsProviderPrefix">
|
||||
<HyperlinkButton
|
||||
Content="{x:Bind ViewModel.MediaSessionsService.LyricsSearchProvider, Mode=OneWay, Converter={StaticResource LyricsSearchProviderToDisplayNameConverter}}"
|
||||
IsEnabled="False"
|
||||
NavigateUri="{x:Bind ViewModel.OriginalLyricsRef, Mode=OneWay}" />
|
||||
</dev:SettingsCard>
|
||||
<dev:SettingsCard x:Uid="LyricsPageTranslationProviderPrefix">
|
||||
<HyperlinkButton
|
||||
Content="{x:Bind ViewModel.MediaSessionsService.TranslationSearchProvider, Mode=OneWay, Converter={StaticResource TranslationSearchProviderToDisplayNameConverter}}"
|
||||
IsEnabled="False"
|
||||
NavigateUri="{x:Bind ViewModel.TranslatedLyricsRef, Mode=OneWay}" />
|
||||
<dev:SettingsCard ContentAlignment="Left">
|
||||
<StackPanel Spacing="6">
|
||||
<Grid ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
x:Uid="SettingsPagePlaybackSource"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center" />
|
||||
<RichTextBlock
|
||||
Grid.Column="1"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
TextWrapping="Wrap">
|
||||
<Paragraph>
|
||||
<Run Text="{x:Bind ViewModel.MediaSessionsService.CurrentMediaSourceProviderInfo.DisplayName, Mode=OneWay}" />
|
||||
<Run Text="(" />
|
||||
<Run Text="{x:Bind ViewModel.MediaSessionsService.CurrentSongInfo.PlayerId, Mode=OneWay}" />
|
||||
<Run Text=")" />
|
||||
</Paragraph>
|
||||
</RichTextBlock>
|
||||
</Grid>
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<TextBlock VerticalAlignment="Center" Text="NCM ID" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
Text="{x:Bind ViewModel.MediaSessionsService.CurrentSongInfo.SongId, Mode=OneWay, TargetNullValue=N/A}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<TextBlock x:Uid="LyricsPageLyricsProviderPrefix" VerticalAlignment="Center" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
Text="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.ProviderIfFound, Mode=OneWay, Converter={StaticResource LyricsSearchProviderToDisplayNameConverter}}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<TextBlock x:Uid="LyricsPageTranslationProviderPrefix" VerticalAlignment="Center" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
Text="{x:Bind ViewModel.MediaSessionsService.TranslationSearchProvider, Mode=OneWay, Converter={StaticResource TranslationSearchProviderToDisplayNameConverter}}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</dev:SettingsCard>
|
||||
|
||||
<dev:SettingsCard x:Uid="SettingsPageForceWordByWordEffect">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.GeneralSettings.IsForceWordByWordEffect, Mode=TwoWay}" />
|
||||
</dev:SettingsCard>
|
||||
@@ -276,12 +312,7 @@
|
||||
</dev:SettingsCard>
|
||||
<dev:SettingsCard x:Uid="SettingsPageTranslationConfig" IsEnabled="{x:Bind ViewModel.AppSettings.TranslationSettings.IsTranslationEnabled, Mode=OneWay}">
|
||||
<dev:SettingsCard.Description>
|
||||
<HyperlinkButton Margin="0,6,0,0" NavigateUri="https://github.com/LibreTranslate/LibreTranslate">
|
||||
<TextBlock
|
||||
x:Uid="SettingsPageTranslationInfoLink"
|
||||
FontSize="14"
|
||||
TextWrapping="Wrap" />
|
||||
</HyperlinkButton>
|
||||
<HyperlinkButton Content="https://github.com/LibreTranslate/LibreTranslate" NavigateUri="https://github.com/LibreTranslate/LibreTranslate" />
|
||||
</dev:SettingsCard.Description>
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.AppSettings.TranslationSettings.IsLibreTranslateEnabled, Mode=TwoWay}" />
|
||||
</dev:SettingsCard>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Services.ResourceService;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Input;
|
||||
@@ -89,7 +90,7 @@ namespace BetterLyrics.WinUI3.Controls
|
||||
|
||||
private void CheckButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
bool registered = GlobalHotKeyHelper.IsHotKeyRegistered(Shortcut);
|
||||
bool registered = GlobalHotKeyHook.IsHotKeyRegistered(Shortcut);
|
||||
if (registered)
|
||||
{
|
||||
DevWinUI.Growl.Success(_resourceService.GetLocalizedString("SettingsPageShortcutRegSuccessInfo"));
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
using BetterLyrics.WinUI3.Constants;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
public class MediaSourceProviderToDisplayedNameConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is string provider)
|
||||
{
|
||||
return provider switch
|
||||
{
|
||||
PlayerID.Spotify => PlayerName.Spotify,
|
||||
PlayerID.AppleMusic => PlayerName.AppleMusic,
|
||||
PlayerID.iTunes => PlayerName.iTunes,
|
||||
PlayerID.KugouMusic => PlayerName.KugouMusic,
|
||||
PlayerID.NetEaseCloudMusic => PlayerName.NetEaseCloudMusic,
|
||||
PlayerID.QQMusic => PlayerName.QQMusic,
|
||||
PlayerID.LXMusic => PlayerName.LXMusic,
|
||||
PlayerID.LXMusicPortable => PlayerName.LXMusicPortable,
|
||||
PlayerID.MediaPlayerWindows11 => PlayerName.MediaPlayerWindows11,
|
||||
PlayerID.AIMP => PlayerName.AIMP,
|
||||
PlayerID.Foobar2000 => PlayerName.Foobar2000,
|
||||
PlayerID.MusicBee => PlayerName.MusicBee,
|
||||
PlayerID.PotPlayer => PlayerName.PotPlayer,
|
||||
PlayerID.Chrome => PlayerName.Chrome,
|
||||
PlayerID.Edge => PlayerName.Edge,
|
||||
PlayerID.BetterLyrics => PlayerName.BetterLyrics,
|
||||
PlayerID.BetterLyricsDebug => PlayerName.BetterLyricsDebug,
|
||||
PlayerID.SaltPlayerForWindows => PlayerName.SaltPlayerForWindows,
|
||||
PlayerID.MoeKoeMusic => PlayerName.MoeKoeMusic,
|
||||
PlayerID.MoeKoeMusicAlternative => PlayerName.MoeKoeMusic,
|
||||
PlayerID.Listen1 => PlayerName.Listen1,
|
||||
_ => provider,
|
||||
};
|
||||
}
|
||||
return value?.ToString() ?? "";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using BetterLyrics.WinUI3.Constants;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
public class MediaSourceProviderToLogoUriConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is string provider)
|
||||
{
|
||||
return provider switch
|
||||
{
|
||||
PlayerID.Spotify => PathHelper.SpotifyLogoPath,
|
||||
PlayerID.AppleMusic => PathHelper.AppleMusicLogoPath,
|
||||
PlayerID.AppleMusicAlternative => PathHelper.AppleMusicLogoPath,
|
||||
PlayerID.iTunes => PathHelper.iTunesLogoPath,
|
||||
PlayerID.KugouMusic => PathHelper.KugouMusicLogoPath,
|
||||
PlayerID.NetEaseCloudMusic => PathHelper.NetEaseCloudMusicLogoPath,
|
||||
PlayerID.QQMusic => PathHelper.QQMusicLogoPath,
|
||||
PlayerID.LXMusic => PathHelper.LXMusicLogoPath,
|
||||
PlayerID.LXMusicPortable => PathHelper.LXMusicLogoPath,
|
||||
PlayerID.MediaPlayerWindows11 => PathHelper.MediaPlayerWindows11LogoPath,
|
||||
PlayerID.AIMP => PathHelper.AIMPLogoPath,
|
||||
PlayerID.Foobar2000 => PathHelper.Foobar2000LogoPath,
|
||||
PlayerID.MusicBee => PathHelper.MusicBeeLogoPath,
|
||||
PlayerID.PotPlayer => PathHelper.PotPlayerLogoPath,
|
||||
PlayerID.Chrome => PathHelper.ChromeLogoPath,
|
||||
PlayerID.Edge => PathHelper.EdgeLogoPath,
|
||||
PlayerID.BetterLyrics => PathHelper.LogoPath,
|
||||
PlayerID.BetterLyricsDebug => PathHelper.LogoPath,
|
||||
PlayerID.SaltPlayerForWindows => PathHelper.SaltPlayerForWindowsLogoPath,
|
||||
PlayerID.MoeKoeMusic => PathHelper.MoeKoeMusicLogoPath,
|
||||
PlayerID.MoeKoeMusicAlternative => PathHelper.MoeKoeMusicLogoPath,
|
||||
PlayerID.Listen1 => PathHelper.Listen1LogoPath,
|
||||
_ => PathHelper.UnknownPlayerLogoPath,
|
||||
};
|
||||
}
|
||||
return PathHelper.UnknownPlayerLogoPath;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using ATL;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
@@ -11,7 +12,7 @@ namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
if (value is Track track)
|
||||
{
|
||||
return track.GetLyrics();
|
||||
return track.GetRawLyrics();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -1,24 +1,8 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Enums
|
||||
namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
public enum ChineseRomanization
|
||||
{
|
||||
Pinyin,
|
||||
Jyutping,
|
||||
}
|
||||
|
||||
public static class ChineseRomanizationExtensions
|
||||
{
|
||||
public static string ToPhoneticCode(this ChineseRomanization chineseRomanization)
|
||||
{
|
||||
return chineseRomanization switch
|
||||
{
|
||||
ChineseRomanization.Pinyin => PhoneticHelper.PinyinCode,
|
||||
ChineseRomanization.Jyutping => PhoneticHelper.JyutpingCode,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(chineseRomanization))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Events
|
||||
{
|
||||
public class IsPlayingChangedEventArgs(bool isPlaying) : EventArgs
|
||||
{
|
||||
public bool IsPlaying { get; set; } = isPlaying;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Events
|
||||
{
|
||||
public class SongInfoChangedEventArgs(SongInfo? songInfo) : EventArgs
|
||||
{
|
||||
public SongInfo? SongInfo { get; set; } = songInfo;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Events
|
||||
{
|
||||
public class TimelineChangedEventArgs(TimeSpan position, TimeSpan end) : EventArgs()
|
||||
{
|
||||
public TimeSpan Position { get; set; } = position;
|
||||
public TimeSpan End { get; set; } = end;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Microsoft.UI.Windowing;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class AppWindowExtensions
|
||||
{
|
||||
extension(AppWindow appWindow)
|
||||
{
|
||||
public void SetIcons()
|
||||
{
|
||||
appWindow.SetIcon(PathHelper.LogoPath);
|
||||
appWindow.SetTaskbarIcon(PathHelper.LogoPath);
|
||||
appWindow.SetTitleBarIcon(PathHelper.LogoPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class CanvasTextLayoutExtensions
|
||||
{
|
||||
extension(CanvasTextLayout? canvasTextLayout)
|
||||
{
|
||||
public void SetFontFamily(string? text, string cjk, string latin)
|
||||
{
|
||||
if (canvasTextLayout == null) return;
|
||||
if (text == null) return;
|
||||
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
canvasTextLayout.SetFontFamily(i, 1, LanguageHelper.IsCJK(text[i]) ? cjk : latin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class ChineseRomanizationExtensions
|
||||
{
|
||||
extension(ChineseRomanization chineseRomanization)
|
||||
{
|
||||
public string ToPhoneticCode() => chineseRomanization switch
|
||||
{
|
||||
ChineseRomanization.Pinyin => PhoneticHelper.PinyinCode,
|
||||
ChineseRomanization.Jyutping => PhoneticHelper.JyutpingCode,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(chineseRomanization))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Windows.UI;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class ColorExtensions
|
||||
{
|
||||
extension(Color color)
|
||||
{
|
||||
public Color WithAlpha(byte alpha)
|
||||
{
|
||||
return Color.FromArgb(alpha, color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
public Color WithOpacity(float opacity)
|
||||
{
|
||||
return Color.FromArgb((byte)(opacity * 255), color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
public Color WithBrightness(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);
|
||||
}
|
||||
|
||||
public Vector3 ToVector3RGB()
|
||||
{
|
||||
return new Vector3((float)color.R / 0xff, (float)color.G / 0xff, (float)color.B / 0xff);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class DisposableObjectExtension
|
||||
{
|
||||
extension(IDisposable obj)
|
||||
{
|
||||
// Credit/Copyright to https://gist.github.com/tcartwright/dab50ebaff7c59f05013de0fb349cabd
|
||||
public bool IsDisposed()
|
||||
{
|
||||
/*
|
||||
TIM C: This hacky code is because MSFT does not provide a standard way to interrogate if an object is disposed or not.
|
||||
I wrote this based upon streams, but it should work for many other types of MSFT objects (maybe).
|
||||
*/
|
||||
if (obj == null) { return true; }
|
||||
|
||||
var objType = obj.GetType();
|
||||
//var foo = new System.IO.BufferedStream();
|
||||
|
||||
// the _disposed pattern should catch a lot of msft objects.... hopefully
|
||||
var isDisposedField = objType.GetField("_disposed", BindingFlags.NonPublic | BindingFlags.Instance) ??
|
||||
objType.GetField("disposed", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
if (isDisposedField != null) { return Convert.ToBoolean(isDisposedField.GetValue(obj)); }
|
||||
|
||||
isDisposedField = objType.GetField("_isOpen", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
if (isDisposedField != null) { return !Convert.ToBoolean(isDisposedField.GetValue(obj)); }
|
||||
|
||||
// Windows.Graphics.Imaging.SoftwareBitmap
|
||||
isDisposedField = objType.GetField("_objRef_global__System_IDisposable", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (isDisposedField != null) { return !Convert.ToBoolean(isDisposedField.GetValue(obj)); }
|
||||
|
||||
// System.IO.FileStream
|
||||
var strategyField = objType.GetField("_strategy", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (strategyField != null)
|
||||
{
|
||||
var strategy = strategyField.GetValue(obj);
|
||||
var isClosedField = strategy.GetType().GetProperty("IsClosed", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (isClosedField != null) { return Convert.ToBoolean(isClosedField.GetValue(strategy)); }
|
||||
}
|
||||
|
||||
// other streams that use this pattern to determine if they are disposed
|
||||
if (obj is Stream stream) { return !stream.CanRead && !stream.CanWrite; }
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class EnumExtensions
|
||||
{
|
||||
extension<T>(T value) where T : struct, Enum
|
||||
{
|
||||
public T GetNext()
|
||||
{
|
||||
T[] values = Enum.GetValues<T>();
|
||||
int currentIndex = Array.IndexOf(values, value);
|
||||
int nextIndex = (currentIndex + 1) % values.Length;
|
||||
return values[nextIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class EnumerableExtensions
|
||||
{
|
||||
extension<T>(IEnumerable<T> items)
|
||||
{
|
||||
public ObservableCollection<GroupInfoList> GetGroupedBy(Func<T, object> groupKeySelector, Func<object, object>? orderSelector = null)
|
||||
{
|
||||
var query = from item in items
|
||||
group item by groupKeySelector(item) into g
|
||||
orderby g.Key
|
||||
select new GroupInfoList(g.Cast<object>(), orderSelector) { Key = g.Key };
|
||||
|
||||
return new ObservableCollection<GroupInfoList>(query);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class ObservableCollectionExtensions
|
||||
{
|
||||
extension<T>(ObservableCollection<T> list)
|
||||
{
|
||||
public void InsertRange(int index, IEnumerable<T> items)
|
||||
{
|
||||
if (list == null) return;
|
||||
if (items == null) return;
|
||||
if (index < 0 || index > list.Count) return;
|
||||
foreach (var item in items)
|
||||
{
|
||||
list.Insert(index++, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using Windows.Foundation;
|
||||
using Windows.Graphics;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class PointExtensions
|
||||
{
|
||||
extension(Point point)
|
||||
{
|
||||
public PointInt32 ToPointInt32() => new((int)point.X, (int)point.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using Windows.Foundation;
|
||||
using Windows.Graphics;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class RectExtensions
|
||||
{
|
||||
extension(Rect rect)
|
||||
{
|
||||
public RectInt32 ToRectInt32() => new(
|
||||
(int)rect.X,
|
||||
(int)rect.Y,
|
||||
(int)rect.Width,
|
||||
(int)rect.Height
|
||||
);
|
||||
|
||||
public Rect WithHeight(double height) => new(
|
||||
rect.X,
|
||||
rect.Y,
|
||||
rect.Width,
|
||||
height
|
||||
);
|
||||
|
||||
public Rect WithWidth(double width) => new(
|
||||
rect.X,
|
||||
rect.Y,
|
||||
width,
|
||||
rect.Height
|
||||
);
|
||||
|
||||
public Rect WithX(double x) => new(
|
||||
x,
|
||||
rect.Y,
|
||||
rect.Width,
|
||||
rect.Height
|
||||
);
|
||||
|
||||
public Rect WithY(double y) => new(
|
||||
rect.X,
|
||||
y,
|
||||
rect.Width,
|
||||
rect.Height
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class SongInfoExtensions
|
||||
{
|
||||
extension(SongInfo songInfo)
|
||||
{
|
||||
public SongInfo WithTitle(string value)
|
||||
{
|
||||
songInfo.Title = value;
|
||||
return songInfo;
|
||||
}
|
||||
|
||||
public SongInfo WithArtist(string value)
|
||||
{
|
||||
songInfo.Artist = value;
|
||||
return songInfo;
|
||||
}
|
||||
|
||||
public SongInfo WithAlbum(string value)
|
||||
{
|
||||
songInfo.Album = value;
|
||||
return songInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using ATL;
|
||||
using System.IO;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class TrackExtensions
|
||||
{
|
||||
extension(Track track)
|
||||
{
|
||||
public string GetParentFolderName() => Directory.GetParent(track.Path)?.Name ?? "";
|
||||
|
||||
public string GetParentFolderPath() => Directory.GetParent(track.Path)?.FullName ?? "";
|
||||
|
||||
public string GetRawLyrics()
|
||||
{
|
||||
if (track.Path is string path)
|
||||
{
|
||||
return TagLib.File.Create(path).Tag.Lyrics;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class VectorExtensions
|
||||
{
|
||||
extension(Vector2 vector2)
|
||||
{
|
||||
public Vector2 WithX(float x)
|
||||
{
|
||||
return new Vector2(x, vector2.Y);
|
||||
}
|
||||
|
||||
public Vector2 WithY(float y)
|
||||
{
|
||||
return new Vector2(vector2.X, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Services.ResourceService;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Extensions
|
||||
{
|
||||
public static class WindowExtensions
|
||||
{
|
||||
private static readonly IResourceService _resourceService = Ioc.Default.GetRequiredService<IResourceService>();
|
||||
|
||||
extension(Window window)
|
||||
{
|
||||
public void Init(
|
||||
string titleKey,
|
||||
TitleBarHeightOption titleBarHeightOption = TitleBarHeightOption.Standard,
|
||||
BackdropType backdropType = BackdropType.DesktopAcrylic)
|
||||
{
|
||||
window.Title = _resourceService.GetLocalizedString(titleKey);
|
||||
window.AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;
|
||||
window.AppWindow.SetIcons();
|
||||
|
||||
window.ExtendsContentIntoTitleBar = true;
|
||||
window.AppWindow.TitleBar.PreferredHeightOption = titleBarHeightOption;
|
||||
|
||||
window.SystemBackdrop = SystemBackdropHelper.CreateSystemBackdrop(backdropType);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Microsoft.UI.Windowing;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class AppWindowHelper
|
||||
{
|
||||
public static void SetIcons(this AppWindow appWindow)
|
||||
{
|
||||
appWindow.SetIcon(PathHelper.LogoPath);
|
||||
appWindow.SetTaskbarIcon(PathHelper.LogoPath);
|
||||
appWindow.SetTitleBarIcon(PathHelper.LogoPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class CanvasTextLayoutExtensions
|
||||
{
|
||||
public static void SetFontFamily(this CanvasTextLayout? layout, string? text, string cjk, string latin)
|
||||
{
|
||||
if (layout == null) return;
|
||||
if (text == null) return;
|
||||
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
layout.SetFontFamily(i, 1, LanguageHelper.IsCJK(text[i]) ? cjk : latin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class CollectionHelper
|
||||
{
|
||||
public static ObservableCollection<GroupInfoList> GetGroupedBy<T>(
|
||||
this IEnumerable<T> items,
|
||||
Func<T, object> groupKeySelector,
|
||||
Func<object, object>? orderSelector = null)
|
||||
{
|
||||
var query = from item in items
|
||||
group item by groupKeySelector(item) into g
|
||||
orderby g.Key
|
||||
select new GroupInfoList(g.Cast<object>(), orderSelector) { Key = g.Key };
|
||||
|
||||
return new ObservableCollection<GroupInfoList>(query);
|
||||
}
|
||||
|
||||
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
|
||||
{
|
||||
if (collection == null) return;
|
||||
if (items == null) return;
|
||||
foreach (var item in items)
|
||||
{
|
||||
collection.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static void InsertRange<T>(this IList<T> list, int index, IEnumerable<T> items)
|
||||
{
|
||||
if (list == null) return;
|
||||
if (items == null) return;
|
||||
if (index < 0 || index > list.Count) return;
|
||||
foreach (var item in items)
|
||||
{
|
||||
list.Insert(index++, item);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -62,86 +64,28 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
);
|
||||
}
|
||||
|
||||
public static Color ToColor(this int argb)
|
||||
{
|
||||
byte a = (byte)(argb >> 24);
|
||||
byte r = (byte)(argb >> 16);
|
||||
byte g = (byte)(argb >> 8);
|
||||
byte b = (byte)argb;
|
||||
|
||||
// 还原非预乘分量
|
||||
if (a == 0)
|
||||
return Color.FromArgb(0, 0, 0, 0);
|
||||
|
||||
// 预乘解码
|
||||
// 这里 a+1 是编码时的分母
|
||||
int ap1 = a + 1;
|
||||
r = (byte)Math.Min(255, (r * 255 + (ap1 / 2)) / ap1);
|
||||
g = (byte)Math.Min(255, (g * 255 + (ap1 / 2)) / ap1);
|
||||
b = (byte)Math.Min(255, (b * 255 + (ap1 / 2)) / ap1);
|
||||
|
||||
return Color.FromArgb(a, r, g, b);
|
||||
}
|
||||
|
||||
public static Color ToColor(this System.Drawing.Color color)
|
||||
{
|
||||
return Color.FromArgb(color.A, color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
public static Color WithAlpha(this Color color, byte alpha)
|
||||
{
|
||||
return Color.FromArgb(alpha, color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
public static Color WithOpacity(this Color color, float opacity)
|
||||
{
|
||||
return Color.FromArgb((byte)(opacity * 255), 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);
|
||||
}
|
||||
|
||||
public static Vector3 ToVector3RGB(this Color color)
|
||||
{
|
||||
return new Vector3((float)color.R / 0xff, (float)color.G / 0xff, (float)color.B / 0xff);
|
||||
}
|
||||
|
||||
public static Color GetRandomColor()
|
||||
{
|
||||
return Color.FromArgb(255, (byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256));
|
||||
}
|
||||
|
||||
public static System.Drawing.Color GetAccentColor(IntPtr myHwnd, string monitorDeviceName, WindowPixelSampleMode mode)
|
||||
public static Color GetAccentColor(IntPtr myHwnd, string monitorDeviceName, WindowPixelSampleMode mode)
|
||||
{
|
||||
if (!User32.GetWindowRect(myHwnd, out RECT myRect)) return System.Drawing.Color.Transparent;
|
||||
if (!User32.GetWindowRect(myHwnd, out RECT myRect)) return Colors.Transparent;
|
||||
|
||||
var monitorInfo = MonitorHelper.GetMonitorInfoExFromDeviceName(monitorDeviceName);
|
||||
var monitorInfo = MonitorHook.GetMonitorInfoExFromDeviceName(monitorDeviceName);
|
||||
int screenWidth = monitorInfo.rcMonitor.Width;
|
||||
switch (mode)
|
||||
{
|
||||
case WindowPixelSampleMode.BelowWindow:
|
||||
{
|
||||
return GetAverageColorFromScreenRegion(myRect.Left, myRect.Bottom + 2, screenWidth, 1);
|
||||
}
|
||||
return GetAverageColorFromScreenRegion(myRect.Left, myRect.Bottom + 2, screenWidth, 1);
|
||||
case WindowPixelSampleMode.AboveWindow:
|
||||
{
|
||||
return GetAverageColorFromScreenRegion(myRect.Left, myRect.Top - 2, screenWidth, 1);
|
||||
}
|
||||
return GetAverageColorFromScreenRegion(myRect.Left, myRect.Top - 2, screenWidth, 1);
|
||||
case WindowPixelSampleMode.WindowArea:
|
||||
{
|
||||
int width = myRect.Right - myRect.Left;
|
||||
int height = myRect.Bottom - myRect.Top;
|
||||
if (width <= 0 || height <= 0)
|
||||
return System.Drawing.Color.Transparent;
|
||||
if (width <= 0 || height <= 0) return Colors.Transparent;
|
||||
// 采集窗口区域的平均色
|
||||
return GetAverageColorFromScreenRegion(myRect.Left, myRect.Top, width, height);
|
||||
}
|
||||
@@ -150,10 +94,10 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
int width = myRect.Right - myRect.Left;
|
||||
int height = myRect.Bottom - myRect.Top;
|
||||
if (width <= 0 || height <= 0)
|
||||
return System.Drawing.Color.Transparent;
|
||||
return Colors.Transparent;
|
||||
|
||||
var edgeThickness = new Thickness(36, 36, 36, 36);
|
||||
List<System.Drawing.Color> edgeColors = [];
|
||||
List<Color> edgeColors = [];
|
||||
|
||||
// Top edge
|
||||
if (edgeThickness.Top > 0)
|
||||
@@ -169,30 +113,27 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
edgeColors.Add(GetAverageColorFromScreenRegion(myRect.Right, myRect.Top, (int)edgeThickness.Right, height));
|
||||
|
||||
// 合并四边平均色
|
||||
if (edgeColors.Count == 0)
|
||||
return System.Drawing.Color.Transparent;
|
||||
long r = 0,
|
||||
g = 0,
|
||||
b = 0;
|
||||
if (edgeColors.Count == 0) return Colors.Transparent;
|
||||
long r = 0, g = 0, b = 0;
|
||||
foreach (var c in edgeColors)
|
||||
{
|
||||
r += c.R;
|
||||
g += c.G;
|
||||
b += c.B;
|
||||
}
|
||||
return System.Drawing.Color.FromArgb(
|
||||
return Color.FromArgb(
|
||||
255,
|
||||
(int)(r / edgeColors.Count),
|
||||
(int)(g / edgeColors.Count),
|
||||
(int)(b / edgeColors.Count)
|
||||
(byte)(r / edgeColors.Count),
|
||||
(byte)(g / edgeColors.Count),
|
||||
(byte)(b / edgeColors.Count)
|
||||
);
|
||||
}
|
||||
default:
|
||||
return System.Drawing.Color.Transparent;
|
||||
return Colors.Transparent;
|
||||
}
|
||||
}
|
||||
|
||||
private static System.Drawing.Color GetAverageColorFromScreenRegion(int x, int y, int width, int height)
|
||||
private static Color GetAverageColorFromScreenRegion(int x, int y, int width, int height)
|
||||
{
|
||||
using Bitmap bmp = new(width, height, PixelFormat.Format32bppArgb);
|
||||
using Graphics gDest = Graphics.FromImage(bmp);
|
||||
@@ -208,7 +149,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
return ComputeAverageColor(bmp);
|
||||
}
|
||||
|
||||
private static System.Drawing.Color ComputeAverageColor(Bitmap bmp)
|
||||
private static Color ComputeAverageColor(Bitmap bmp)
|
||||
{
|
||||
long r = 0, g = 0, b = 0;
|
||||
int count = 0;
|
||||
@@ -225,8 +166,8 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) return System.Drawing.Color.Transparent;
|
||||
return System.Drawing.Color.FromArgb((int)(r / count), (int)(g / count), (int)(b / count));
|
||||
if (count == 0) return Colors.Transparent;
|
||||
return Color.FromArgb(255, (byte)(r / count), (byte)(g / count), (byte)(b / count));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class EnumExtensions
|
||||
{
|
||||
public static T GetNext<T>(this T value) where T : struct, Enum
|
||||
{
|
||||
T[] values = Enum.GetValues<T>();
|
||||
int currentIndex = Array.IndexOf(values, value);
|
||||
int nextIndex = (currentIndex + 1) % values.Length;
|
||||
return values[nextIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
@@ -55,9 +56,9 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void WriteLyricsCache(string title, string artist, string album, string lyrics, LyricsFormat format, string cacheFolderPath)
|
||||
public static void WriteLyricsCache(SongInfo songInfo, string lyrics, LyricsFormat format, string cacheFolderPath)
|
||||
{
|
||||
var cacheFilePath = Path.Combine(cacheFolderPath, SanitizeFileName($"{artist} - {title} - {album}{format.ToFileExtension()}"));
|
||||
var cacheFilePath = Path.Combine(cacheFolderPath, SanitizeFileName($"{songInfo.Artist} - {songInfo.Title} - {songInfo.Album}{format.ToFileExtension()}"));
|
||||
File.WriteAllText(cacheFilePath, lyrics);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using CommunityToolkit.WinUI.Helpers;
|
||||
using Windows.ApplicationModel;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class MetadataHelper
|
||||
{
|
||||
public static string AppVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
var version = Package.Current.Id.Version;
|
||||
return $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
|
||||
}
|
||||
}
|
||||
public static string AppVersion => Package.Current.Id.Version.ToFormattedString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class ObjectHelper
|
||||
{
|
||||
// Credit/Copyright to https://gist.github.com/tcartwright/dab50ebaff7c59f05013de0fb349cabd
|
||||
public static bool IsDisposed(this IDisposable obj)
|
||||
{
|
||||
/*
|
||||
TIM C: This hacky code is because MSFT does not provide a standard way to interrogate if an object is disposed or not.
|
||||
I wrote this based upon streams, but it should work for many other types of MSFT objects (maybe).
|
||||
*/
|
||||
if (obj == null) { return true; }
|
||||
|
||||
var objType = obj.GetType();
|
||||
//var foo = new System.IO.BufferedStream();
|
||||
|
||||
// the _disposed pattern should catch a lot of msft objects.... hopefully
|
||||
var isDisposedField = objType.GetField("_disposed", BindingFlags.NonPublic | BindingFlags.Instance) ??
|
||||
objType.GetField("disposed", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
if (isDisposedField != null) { return Convert.ToBoolean(isDisposedField.GetValue(obj)); }
|
||||
|
||||
isDisposedField = objType.GetField("_isOpen", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
if (isDisposedField != null) { return !Convert.ToBoolean(isDisposedField.GetValue(obj)); }
|
||||
|
||||
// Windows.Graphics.Imaging.SoftwareBitmap
|
||||
isDisposedField = objType.GetField("_objRef_global__System_IDisposable", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (isDisposedField != null) { return !Convert.ToBoolean(isDisposedField.GetValue(obj)); }
|
||||
|
||||
// System.IO.FileStream
|
||||
var strategyField = objType.GetField("_strategy", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (strategyField != null)
|
||||
{
|
||||
var strategy = strategyField.GetValue(obj);
|
||||
var isClosedField = strategy.GetType().GetProperty("IsClosed", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (isClosedField != null) { return Convert.ToBoolean(isClosedField.GetValue(strategy)); }
|
||||
}
|
||||
|
||||
// other streams that use this pattern to determine if they are disposed
|
||||
if (obj is Stream stream) { return !stream.CanRead && !stream.CanWrite; }
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using DevWinUI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
@@ -10,7 +12,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static async Task<StorageFolder?> PickSingleFolderAsync<T>()
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<T>();
|
||||
var window = WindowHook.GetWindowByWindowType<T>();
|
||||
if (window == null) return null;
|
||||
|
||||
var picker = new Windows.Storage.Pickers.FolderPicker();
|
||||
@@ -26,7 +28,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public static async Task<StorageFile?> PickSingleFileAsync<T>(string[] fileTypeFilter)
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<T>();
|
||||
var window = WindowHook.GetWindowByWindowType<T>();
|
||||
if (window == null) return null;
|
||||
|
||||
var picker = new Windows.Storage.Pickers.FileOpenPicker();
|
||||
@@ -42,7 +44,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public static async Task<StorageFile?> PickSaveFileAsync<T>(IDictionary<string, IList<string>> fileTypeChoices)
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<T>();
|
||||
var window = WindowHook.GetWindowByWindowType<T>();
|
||||
if (window == null) return null;
|
||||
|
||||
var picker = new Windows.Storage.Pickers.FileSavePicker();
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using BetterLyrics.WinUI3.Constants;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class PlayerIdMatcher
|
||||
public static class PlayerIDMatcher
|
||||
{
|
||||
private static readonly List<string> neteaseFamilyRegex =
|
||||
[
|
||||
@@ -12,8 +13,10 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
"^48848aaaaaaccd\\.HyPlayer_" //HyPlayer
|
||||
];
|
||||
|
||||
public static bool IsNeteaseFamily(string id)
|
||||
public static bool IsNeteaseFamily(string? id)
|
||||
{
|
||||
if (id is null) return false;
|
||||
|
||||
foreach (var regex in neteaseFamilyRegex)
|
||||
{
|
||||
var isMatch = Regex.IsMatch(id, regex);
|
||||
@@ -22,9 +25,8 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsLXMusic(string? id)
|
||||
{
|
||||
return id == Constants.PlayerID.LXMusic || id == Constants.PlayerID.LXMusicPortable;
|
||||
}
|
||||
public static bool IsLXMusic(string? id) => id is PlayerID.LXMusic or PlayerID.LXMusicPortable;
|
||||
|
||||
public static bool IsAppleMusic(string? id) => id is PlayerID.AppleMusic or PlayerID.AppleMusicAlternative;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
using Windows.Graphics;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class RectHelper
|
||||
{
|
||||
public static RectInt32 ToRectInt32(this Windows.Foundation.Rect rect)
|
||||
{
|
||||
return new RectInt32(
|
||||
(int)rect.X,
|
||||
(int)rect.Y,
|
||||
(int)rect.Width,
|
||||
(int)rect.Height
|
||||
);
|
||||
}
|
||||
|
||||
public static Windows.Foundation.Rect WithHeight(this Windows.Foundation.Rect rect, double height)
|
||||
{
|
||||
return new Windows.Foundation.Rect(
|
||||
rect.X,
|
||||
rect.Y,
|
||||
rect.Width,
|
||||
height
|
||||
);
|
||||
}
|
||||
|
||||
public static Windows.Foundation.Rect WithWidth(this Windows.Foundation.Rect rect, double width)
|
||||
{
|
||||
return new Windows.Foundation.Rect(
|
||||
rect.X,
|
||||
rect.Y,
|
||||
width,
|
||||
rect.Height
|
||||
);
|
||||
}
|
||||
|
||||
public static Windows.Foundation.Rect WithX(this Windows.Foundation.Rect rect, double x)
|
||||
{
|
||||
return new Windows.Foundation.Rect(
|
||||
x,
|
||||
rect.Y,
|
||||
rect.Width,
|
||||
rect.Height
|
||||
);
|
||||
}
|
||||
|
||||
public static Windows.Foundation.Rect WithY(this Windows.Foundation.Rect rect, double y)
|
||||
{
|
||||
return new Windows.Foundation.Rect(
|
||||
rect.X,
|
||||
y,
|
||||
rect.Width,
|
||||
rect.Height
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class TrackHelper
|
||||
{
|
||||
public static string GetParentFolderName(this ATL.Track track)
|
||||
{
|
||||
return Directory.GetParent(track.Path)?.Name ?? "";
|
||||
}
|
||||
|
||||
public static string GetParentFolderPath(this ATL.Track track)
|
||||
{
|
||||
return Directory.GetParent(track.Path)?.FullName ?? "";
|
||||
}
|
||||
|
||||
public static string GetLyrics(this ATL.Track track)
|
||||
{
|
||||
if (track.Path is string path)
|
||||
{
|
||||
return TagLib.File.Create(path).Tag.Lyrics;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class VectorHelper
|
||||
{
|
||||
public static Vector2 WithX(this Vector2 source, float x)
|
||||
{
|
||||
return new Vector2(x, source.Y);
|
||||
}
|
||||
|
||||
public static Vector2 WithY(this Vector2 source, float y)
|
||||
{
|
||||
return new Vector2(source.X, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,9 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Vanara.PInvoke;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
namespace BetterLyrics.WinUI3.Hooks
|
||||
{
|
||||
public class ForegroundWindowWatcher
|
||||
public class ForegroundWindowHook
|
||||
{
|
||||
private readonly User32.WinEventProc _winEventDelegate;
|
||||
private readonly List<User32.HWINEVENTHOOK> _hooks = new();
|
||||
@@ -17,7 +17,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
private readonly DispatcherTimer _timer;
|
||||
|
||||
public ForegroundWindowWatcher(IntPtr selfHwnd, WindowChangedHandler onWindowChanged)
|
||||
public ForegroundWindowHook(IntPtr selfHwnd, WindowChangedHandler onWindowChanged)
|
||||
{
|
||||
_selfHwnd = selfHwnd;
|
||||
_onWindowChanged = onWindowChanged;
|
||||
@@ -5,9 +5,9 @@ using Vanara.PInvoke;
|
||||
using Windows.System;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
namespace BetterLyrics.WinUI3.Hooks
|
||||
{
|
||||
public class GlobalHotKeyHelper
|
||||
public class GlobalHotKeyHook
|
||||
{
|
||||
private static Dictionary<int, Action> _actions = [];
|
||||
private static Dictionary<int, List<string>> _keys = [];
|
||||
@@ -23,7 +23,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
if (keys.Count == 0) return;
|
||||
|
||||
var window = WindowHelper.GetWindowByWindowType<T>();
|
||||
var window = WindowHook.GetWindowByWindowType<T>();
|
||||
if (window == null) return;
|
||||
|
||||
HWND hwnd = WindowNative.GetWindowHandle(window);
|
||||
@@ -62,7 +62,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
private static void UnregisterHotKey<T>(ShortcutID id)
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<T>();
|
||||
var window = WindowHook.GetWindowByWindowType<T>();
|
||||
if (window == null) return;
|
||||
|
||||
HWND hwnd = WindowNative.GetWindowHandle(window);
|
||||
@@ -5,9 +5,9 @@ using System.Runtime.InteropServices;
|
||||
using Vanara.PInvoke;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
namespace BetterLyrics.WinUI3.Hooks
|
||||
{
|
||||
public static class MonitorHelper
|
||||
public static class MonitorHook
|
||||
{
|
||||
public static IEnumerable<string> GetAllMonitorDeviceNames()
|
||||
{
|
||||
@@ -2,9 +2,9 @@
|
||||
using NAudio.CoreAudioApi;
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
namespace BetterLyrics.WinUI3.Hooks
|
||||
{
|
||||
public static class SystemVolumeHelper
|
||||
public static class SystemVolumeHook
|
||||
{
|
||||
private static MMDeviceEnumerator? _deviceEnumerator;
|
||||
private static MMDevice? _defaultDevice;
|
||||
@@ -15,7 +15,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
/// </summary>
|
||||
public static event EventHandler<int>? VolumeNotification;
|
||||
|
||||
static SystemVolumeHelper()
|
||||
static SystemVolumeHook()
|
||||
{
|
||||
_deviceEnumerator = new MMDeviceEnumerator();
|
||||
_defaultDevice = _deviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
|
||||
@@ -1,6 +1,7 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
@@ -18,9 +19,9 @@ using Windows.Foundation;
|
||||
using WinRT.Interop;
|
||||
using WinUIEx;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
namespace BetterLyrics.WinUI3.Hooks
|
||||
{
|
||||
public static class WindowHelper
|
||||
public static class WindowHook
|
||||
{
|
||||
private static List<object> _activeWindows = [];
|
||||
private static List<object> _workAreas = [];
|
||||
@@ -1,6 +1,7 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Microsoft.Graphics.Canvas.Geometry;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public class LyricsSearchResult
|
||||
{
|
||||
public bool IsFound => !string.IsNullOrEmpty(Raw);
|
||||
public LyricsSearchProvider? Provider { get; set; }
|
||||
|
||||
public string? Raw { get; set; }
|
||||
@@ -12,5 +11,16 @@ namespace BetterLyrics.WinUI3.Models
|
||||
public string? Title { get; set; }
|
||||
public string? Artist { get; set; }
|
||||
public string? Album { get; set; }
|
||||
|
||||
public bool IsFound => !string.IsNullOrEmpty(Raw);
|
||||
|
||||
public LyricsSearchProvider? ProviderIfFound => IsFound ? Provider : null;
|
||||
|
||||
public void CopyFromSongInfo(SongInfo songInfo)
|
||||
{
|
||||
Title = songInfo.Title;
|
||||
Artist = songInfo.Artist;
|
||||
Album = songInfo.Album;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.ResourceService;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
@@ -104,10 +105,10 @@ namespace BetterLyrics.WinUI3.Models
|
||||
|
||||
public void UpdateMonitorNameAndBounds()
|
||||
{
|
||||
var lyricsWindow = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
var lyricsWindow = WindowHook.GetWindowByWindowType<LyricsWindow>();
|
||||
if (lyricsWindow == null) return;
|
||||
|
||||
var mointor = MonitorHelper.GetMonitorInfoExFromWindow(lyricsWindow);
|
||||
var mointor = MonitorHook.GetMonitorInfoExFromWindow(lyricsWindow);
|
||||
MonitorDeviceName = mointor.szDevice;
|
||||
MonitorBounds = new Rect(
|
||||
mointor.rcMonitor.Left,
|
||||
@@ -119,7 +120,7 @@ namespace BetterLyrics.WinUI3.Models
|
||||
|
||||
public void UpdateMonitorBounds()
|
||||
{
|
||||
var mointor = MonitorHelper.GetMonitorInfoExFromDeviceName(MonitorDeviceName);
|
||||
var mointor = MonitorHook.GetMonitorInfoExFromDeviceName(MonitorDeviceName);
|
||||
MonitorBounds = new Rect(
|
||||
mointor.rcMonitor.Left,
|
||||
mointor.rcMonitor.Top,
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Collections;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using BetterLyrics.WinUI3.Constants;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
@@ -32,7 +33,60 @@ namespace BetterLyrics.WinUI3.Models
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection<AlbumArtSearchProviderInfo> AlbumArtSearchProvidersInfo { get; set; } = [.. Enum.GetValues<AlbumArtSearchProvider>().Select(p => new AlbumArtSearchProviderInfo(p, true))];
|
||||
|
||||
public bool IsLXMusic => PlayerIdMatcher.IsLXMusic(Provider);
|
||||
public bool IsLXMusic => PlayerIDMatcher.IsLXMusic(Provider);
|
||||
|
||||
public string DisplayName => Provider switch
|
||||
{
|
||||
PlayerID.Spotify => PlayerName.Spotify,
|
||||
PlayerID.AppleMusic => PlayerName.AppleMusic,
|
||||
PlayerID.iTunes => PlayerName.iTunes,
|
||||
PlayerID.KugouMusic => PlayerName.KugouMusic,
|
||||
PlayerID.NetEaseCloudMusic => PlayerName.NetEaseCloudMusic,
|
||||
PlayerID.QQMusic => PlayerName.QQMusic,
|
||||
PlayerID.LXMusic => PlayerName.LXMusic,
|
||||
PlayerID.LXMusicPortable => PlayerName.LXMusicPortable,
|
||||
PlayerID.MediaPlayerWindows11 => PlayerName.MediaPlayerWindows11,
|
||||
PlayerID.AIMP => PlayerName.AIMP,
|
||||
PlayerID.Foobar2000 => PlayerName.Foobar2000,
|
||||
PlayerID.MusicBee => PlayerName.MusicBee,
|
||||
PlayerID.PotPlayer => PlayerName.PotPlayer,
|
||||
PlayerID.Chrome => PlayerName.Chrome,
|
||||
PlayerID.Edge => PlayerName.Edge,
|
||||
PlayerID.BetterLyrics => PlayerName.BetterLyrics,
|
||||
PlayerID.BetterLyricsDebug => PlayerName.BetterLyricsDebug,
|
||||
PlayerID.SaltPlayerForWindows => PlayerName.SaltPlayerForWindows,
|
||||
PlayerID.MoeKoeMusic => PlayerName.MoeKoeMusic,
|
||||
PlayerID.MoeKoeMusicAlternative => PlayerName.MoeKoeMusic,
|
||||
PlayerID.Listen1 => PlayerName.Listen1,
|
||||
_ => Provider,
|
||||
};
|
||||
|
||||
public string LogoPath => Provider switch
|
||||
{
|
||||
PlayerID.Spotify => PathHelper.SpotifyLogoPath,
|
||||
PlayerID.AppleMusic => PathHelper.AppleMusicLogoPath,
|
||||
PlayerID.AppleMusicAlternative => PathHelper.AppleMusicLogoPath,
|
||||
PlayerID.iTunes => PathHelper.iTunesLogoPath,
|
||||
PlayerID.KugouMusic => PathHelper.KugouMusicLogoPath,
|
||||
PlayerID.NetEaseCloudMusic => PathHelper.NetEaseCloudMusicLogoPath,
|
||||
PlayerID.QQMusic => PathHelper.QQMusicLogoPath,
|
||||
PlayerID.LXMusic => PathHelper.LXMusicLogoPath,
|
||||
PlayerID.LXMusicPortable => PathHelper.LXMusicLogoPath,
|
||||
PlayerID.MediaPlayerWindows11 => PathHelper.MediaPlayerWindows11LogoPath,
|
||||
PlayerID.AIMP => PathHelper.AIMPLogoPath,
|
||||
PlayerID.Foobar2000 => PathHelper.Foobar2000LogoPath,
|
||||
PlayerID.MusicBee => PathHelper.MusicBeeLogoPath,
|
||||
PlayerID.PotPlayer => PathHelper.PotPlayerLogoPath,
|
||||
PlayerID.Chrome => PathHelper.ChromeLogoPath,
|
||||
PlayerID.Edge => PathHelper.EdgeLogoPath,
|
||||
PlayerID.BetterLyrics => PathHelper.LogoPath,
|
||||
PlayerID.BetterLyricsDebug => PathHelper.LogoPath,
|
||||
PlayerID.SaltPlayerForWindows => PathHelper.SaltPlayerForWindowsLogoPath,
|
||||
PlayerID.MoeKoeMusic => PathHelper.MoeKoeMusicLogoPath,
|
||||
PlayerID.MoeKoeMusicAlternative => PathHelper.MoeKoeMusicLogoPath,
|
||||
PlayerID.Listen1 => PathHelper.Listen1LogoPath,
|
||||
_ => PathHelper.UnknownPlayerLogoPath,
|
||||
};
|
||||
|
||||
public MediaSourceProviderInfo()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Collections;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models.Settings
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
public partial class SongInfo : ObservableObject
|
||||
public partial class SongInfo : ObservableObject, ICloneable
|
||||
{
|
||||
[ObservableProperty]
|
||||
public partial string Album { get; set; }
|
||||
@@ -24,9 +25,37 @@ namespace BetterLyrics.WinUI3.Models
|
||||
[ObservableProperty]
|
||||
public partial string? SongId { get; set; } = null;
|
||||
|
||||
public string? LinkedFileName { get; set; } = null;
|
||||
|
||||
public double Duration => DurationMs / 1000;
|
||||
|
||||
public SongInfo() { }
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return new SongInfo()
|
||||
{
|
||||
Title = this.Title,
|
||||
Artist = this.Artist,
|
||||
Album = this.Album,
|
||||
DurationMs = this.DurationMs,
|
||||
PlayerId = this.PlayerId,
|
||||
SongId = this.SongId,
|
||||
LinkedFileName = this.LinkedFileName,
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return
|
||||
$"Title: {Title}\n" +
|
||||
$"Artist: {Artist}\n" +
|
||||
$"Album: {Album}\n" +
|
||||
$"Duration: {Duration} sec\n" +
|
||||
$"Plauer ID: {PlayerId}\n" +
|
||||
$"Song ID: {SongId}\n" +
|
||||
$"Linked file name: {LinkedFileName}";
|
||||
}
|
||||
}
|
||||
|
||||
public static class SongInfoExtensions
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using System;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
namespace BetterLyrics.WinUI3.Providers
|
||||
{
|
||||
public class AppleMusic
|
||||
{
|
||||
@@ -1,5 +1,6 @@
|
||||
using BetterLyrics.WinUI3.Events;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services.ResourceService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
@@ -59,7 +60,7 @@ namespace BetterLyrics.WinUI3.Services.LastFMService
|
||||
|
||||
public async Task AuthAsync()
|
||||
{
|
||||
var dialogXamlRoot = WindowHelper.GetWindowByWindowType<SettingsWindow>()?.Content.XamlRoot;
|
||||
var dialogXamlRoot = WindowHook.GetWindowByWindowType<SettingsWindow>()?.Content.XamlRoot;
|
||||
if (dialogXamlRoot == null)
|
||||
{
|
||||
return;
|
||||
@@ -86,7 +87,7 @@ namespace BetterLyrics.WinUI3.Services.LastFMService
|
||||
|
||||
public async Task UnAuthAsync()
|
||||
{
|
||||
var dialogXamlRoot = WindowHelper.GetWindowByWindowType<SettingsWindow>()?.Content.XamlRoot;
|
||||
var dialogXamlRoot = WindowHook.GetWindowByWindowType<SettingsWindow>()?.Content.XamlRoot;
|
||||
if (dialogXamlRoot == null)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace BetterLyrics.WinUI3.Services.LibWatcherService
|
||||
UpdateWatchers();
|
||||
}
|
||||
|
||||
private void LocalMediaFolders_ItemPropertyChanged(object? sender, Extensions.ItemPropertyChangedEventArgs e)
|
||||
private void LocalMediaFolders_ItemPropertyChanged(object? sender, Collections.ItemPropertyChangedEventArgs e)
|
||||
{
|
||||
UpdateWatchers();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
@@ -44,21 +46,21 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
|
||||
LiveStates.LyricsWindowStatus.UpdateMonitorBounds();
|
||||
|
||||
WindowHelper.SetIsWorkArea<LyricsWindow>(LiveStates.LyricsWindowStatus.IsWorkArea);
|
||||
WindowHook.SetIsWorkArea<LyricsWindow>(LiveStates.LyricsWindowStatus.IsWorkArea);
|
||||
if (LiveStates.LyricsWindowStatus.IsWorkArea)
|
||||
{
|
||||
WindowHelper.UpdateWorkArea<LyricsWindow>();
|
||||
WindowHook.UpdateWorkArea<LyricsWindow>();
|
||||
}
|
||||
await Task.Delay(300);
|
||||
|
||||
WindowHelper.SetIsShowInSwitchers<LyricsWindow>(LiveStates.LyricsWindowStatus.IsShownInSwitchers);
|
||||
WindowHelper.SetIsAlwaysOnTop<LyricsWindow>(LiveStates.LyricsWindowStatus.IsAlwaysOnTop);
|
||||
WindowHook.SetIsShowInSwitchers<LyricsWindow>(LiveStates.LyricsWindowStatus.IsShownInSwitchers);
|
||||
WindowHook.SetIsAlwaysOnTop<LyricsWindow>(LiveStates.LyricsWindowStatus.IsAlwaysOnTop);
|
||||
|
||||
WindowHelper.SetIsClickThrough<LyricsWindow>(LiveStates.LyricsWindowStatus.IsClickThrough);
|
||||
WindowHelper.SetIsBorderless<LyricsWindow>(LiveStates.LyricsWindowStatus.IsBorderless);
|
||||
WindowHook.SetIsClickThrough<LyricsWindow>(LiveStates.LyricsWindowStatus.IsClickThrough);
|
||||
WindowHook.SetIsBorderless<LyricsWindow>(LiveStates.LyricsWindowStatus.IsBorderless);
|
||||
|
||||
WindowHelper.SetLyricsWindowVisibilityByPlayingStatus(_dispatcherQueue);
|
||||
WindowHelper.SetTitleBarArea<LyricsWindow>(LiveStates.LyricsWindowStatus.TitleBarArea);
|
||||
WindowHook.SetLyricsWindowVisibilityByPlayingStatus(_dispatcherQueue);
|
||||
WindowHook.SetTitleBarArea<LyricsWindow>(LiveStates.LyricsWindowStatus.TitleBarArea);
|
||||
|
||||
// 下述代码可以删除,但是为了避免给用户造成操作上的疑虑,暂时保留
|
||||
if (LiveStates.LyricsWindowStatus.IsWorkArea)
|
||||
@@ -66,7 +68,7 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
LiveStates.LyricsWindowStatus.WindowBounds = LiveStates.LyricsWindowStatus.GetWindowBoundsWhenWorkArea();
|
||||
}
|
||||
|
||||
WindowHelper.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.WindowBounds);
|
||||
WindowHook.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.WindowBounds);
|
||||
LiveStates.LyricsWindowStatus.WindowX = LiveStates.LyricsWindowStatus.WindowBounds.X;
|
||||
LiveStates.LyricsWindowStatus.WindowY = LiveStates.LyricsWindowStatus.WindowBounds.Y;
|
||||
LiveStates.LyricsWindowStatus.WindowWidth = LiveStates.LyricsWindowStatus.WindowBounds.Width;
|
||||
@@ -83,11 +85,11 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
{
|
||||
case nameof(LyricsWindowStatus.IsWorkArea):
|
||||
LiveStates.IsLyricsWindowStatusRefreshing = true;
|
||||
WindowHelper.SetIsWorkArea<LyricsWindow>(LiveStates.LyricsWindowStatus.IsWorkArea);
|
||||
WindowHook.SetIsWorkArea<LyricsWindow>(LiveStates.LyricsWindowStatus.IsWorkArea);
|
||||
LiveStates.IsLyricsWindowStatusRefreshing = false;
|
||||
if (LiveStates.LyricsWindowStatus.IsWorkArea)
|
||||
{
|
||||
WindowHelper.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.GetWindowBoundsWhenWorkArea());
|
||||
WindowHook.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.GetWindowBoundsWhenWorkArea());
|
||||
}
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.DockHeight):
|
||||
@@ -97,40 +99,40 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
if (LiveStates.LyricsWindowStatus.IsWorkArea)
|
||||
{
|
||||
LiveStates.IsLyricsWindowStatusRefreshing = true;
|
||||
WindowHelper.UpdateWorkArea<LyricsWindow>();
|
||||
WindowHook.UpdateWorkArea<LyricsWindow>();
|
||||
LiveStates.IsLyricsWindowStatusRefreshing = false;
|
||||
WindowHelper.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.GetWindowBoundsWhenWorkArea());
|
||||
WindowHook.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.GetWindowBoundsWhenWorkArea());
|
||||
}
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.IsShownInSwitchers):
|
||||
WindowHelper.SetIsShowInSwitchers<LyricsWindow>(LiveStates.LyricsWindowStatus.IsShownInSwitchers);
|
||||
WindowHook.SetIsShowInSwitchers<LyricsWindow>(LiveStates.LyricsWindowStatus.IsShownInSwitchers);
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.IsAlwaysOnTop):
|
||||
WindowHelper.SetIsAlwaysOnTop<LyricsWindow>(LiveStates.LyricsWindowStatus.IsAlwaysOnTop);
|
||||
WindowHook.SetIsAlwaysOnTop<LyricsWindow>(LiveStates.LyricsWindowStatus.IsAlwaysOnTop);
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.IsClickThrough):
|
||||
WindowHelper.SetIsClickThrough<LyricsWindow>(LiveStates.LyricsWindowStatus.IsClickThrough);
|
||||
WindowHook.SetIsClickThrough<LyricsWindow>(LiveStates.LyricsWindowStatus.IsClickThrough);
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.IsBorderless):
|
||||
WindowHelper.SetIsBorderless<LyricsWindow>(LiveStates.LyricsWindowStatus.IsBorderless);
|
||||
WindowHook.SetIsBorderless<LyricsWindow>(LiveStates.LyricsWindowStatus.IsBorderless);
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.WindowX):
|
||||
WindowHelper.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.WindowBounds.WithX(LiveStates.LyricsWindowStatus.WindowX));
|
||||
WindowHook.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.WindowBounds.WithX(LiveStates.LyricsWindowStatus.WindowX));
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.WindowY):
|
||||
WindowHelper.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.WindowBounds.WithY(LiveStates.LyricsWindowStatus.WindowY));
|
||||
WindowHook.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.WindowBounds.WithY(LiveStates.LyricsWindowStatus.WindowY));
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.WindowWidth):
|
||||
WindowHelper.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.WindowBounds.WithWidth(LiveStates.LyricsWindowStatus.WindowWidth));
|
||||
WindowHook.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.WindowBounds.WithWidth(LiveStates.LyricsWindowStatus.WindowWidth));
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.WindowHeight):
|
||||
WindowHelper.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.WindowBounds.WithHeight(LiveStates.LyricsWindowStatus.WindowHeight));
|
||||
WindowHook.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.WindowBounds.WithHeight(LiveStates.LyricsWindowStatus.WindowHeight));
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.TitleBarArea):
|
||||
WindowHelper.SetTitleBarArea<LyricsWindow>(LiveStates.LyricsWindowStatus.TitleBarArea);
|
||||
WindowHook.SetTitleBarArea<LyricsWindow>(LiveStates.LyricsWindowStatus.TitleBarArea);
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.AutoShowOrHideWindow):
|
||||
WindowHelper.SetLyricsWindowVisibilityByPlayingStatus(_dispatcherQueue);
|
||||
WindowHook.SetLyricsWindowVisibilityByPlayingStatus(_dispatcherQueue);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -9,8 +9,8 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
{
|
||||
public interface ILyricsSearchService
|
||||
{
|
||||
Task<LyricsSearchResult> SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, string? songId, CancellationToken token);
|
||||
Task<LyricsSearchResult> SearchSmartlyAsync(SongInfo songInfo, CancellationToken token);
|
||||
|
||||
Task<List<LyricsSearchResult>> SearchAllAsync(string title, string artist, string album, double durationMs, CancellationToken token);
|
||||
Task<List<LyricsSearchResult>> SearchAllAsync(SongInfo songInfo, CancellationToken token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
using ATL;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Providers;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Lyricify.Lyrics.Helpers;
|
||||
@@ -89,15 +91,16 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<LyricsSearchResult> SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, string? songId, CancellationToken token)
|
||||
public async Task<LyricsSearchResult> SearchSmartlyAsync(SongInfo songInfo, CancellationToken token)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult();
|
||||
|
||||
string overridenTitle = title;
|
||||
string overridenArtist = artist;
|
||||
string overridenAlbum = album;
|
||||
string overridenTitle = songInfo.Title;
|
||||
string overridenArtist = songInfo.Artist;
|
||||
string overridenAlbum = songInfo.Album;
|
||||
|
||||
_logger.LogInformation("Searching img for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
|
||||
_logger.LogInformation("Searching lyrics for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)",
|
||||
overridenTitle, overridenArtist, overridenAlbum, songInfo.DurationMs);
|
||||
|
||||
var found = _settingsService.AppSettings.MappedSongSearchQueries
|
||||
.Where(x => x.OriginalTitle == overridenTitle && x.OriginalArtist == overridenArtist && x.OriginalAlbum == overridenAlbum)
|
||||
@@ -124,18 +127,27 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
var targetProvider = found.LyricsSearchProvider;
|
||||
if (targetProvider != null)
|
||||
{
|
||||
return await SearchSingleAsync(targetProvider.Value, overridenTitle, overridenArtist, overridenAlbum, durationMs, songId, token);
|
||||
return await SearchSingleAsync(
|
||||
((SongInfo)songInfo.Clone())
|
||||
.WithTitle(overridenTitle)
|
||||
.WithArtist(overridenArtist)
|
||||
.WithAlbum(overridenAlbum),
|
||||
targetProvider.Value, token);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var provider in _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == mediaSessionId).FirstOrDefault()?.LyricsSearchProvidersInfo ?? [])
|
||||
foreach (var provider in _settingsService.AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == songInfo.PlayerId).FirstOrDefault()?.LyricsSearchProvidersInfo ?? [])
|
||||
{
|
||||
if (!provider.IsEnabled)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lyricsSearchResult = await SearchSingleAsync(provider.Provider, overridenTitle, overridenArtist, overridenAlbum, durationMs, null, token);
|
||||
lyricsSearchResult = await SearchSingleAsync(
|
||||
((SongInfo)songInfo.Clone())
|
||||
.WithTitle(overridenTitle)
|
||||
.WithArtist(overridenArtist)
|
||||
.WithAlbum(overridenAlbum),
|
||||
provider.Provider, token);
|
||||
|
||||
if (lyricsSearchResult.IsFound)
|
||||
{
|
||||
@@ -146,19 +158,19 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
public async Task<List<LyricsSearchResult>> SearchAllAsync(string title, string artist, string album, double durationMs, CancellationToken token)
|
||||
public async Task<List<LyricsSearchResult>> SearchAllAsync(SongInfo songInfo, CancellationToken token)
|
||||
{
|
||||
_logger.LogInformation("Searching all lyrics for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
|
||||
_logger.LogInformation("Searching all lyrics for: {SongInfo}", songInfo);
|
||||
var results = new List<LyricsSearchResult>();
|
||||
foreach (var provider in Enum.GetValues<LyricsSearchProvider>())
|
||||
{
|
||||
var searchResult = await SearchSingleAsync(provider, title, artist, album, durationMs, null, token);
|
||||
var searchResult = await SearchSingleAsync(songInfo, provider, token);
|
||||
results.Add(searchResult);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private async Task<LyricsSearchResult> SearchSingleAsync(LyricsSearchProvider provider, string title, string artist, string album, double durationMs, string? songId, CancellationToken token)
|
||||
private async Task<LyricsSearchResult> SearchSingleAsync(SongInfo songInfo, LyricsSearchProvider provider, CancellationToken token)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
@@ -172,13 +184,11 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
// Check cache first
|
||||
if (provider.IsRemote())
|
||||
{
|
||||
var cachedLyrics = FileHelper.ReadLyricsCache(title, artist, album, lyricsFormat, provider.GetCacheDirectory());
|
||||
var cachedLyrics = FileHelper.ReadLyricsCache(songInfo.Title, songInfo.Artist, songInfo.Album, lyricsFormat, provider.GetCacheDirectory());
|
||||
if (!string.IsNullOrWhiteSpace(cachedLyrics))
|
||||
{
|
||||
lyricsSearchResult.Raw = cachedLyrics;
|
||||
lyricsSearchResult.Title = title;
|
||||
lyricsSearchResult.Artist = artist;
|
||||
lyricsSearchResult.Album = album;
|
||||
lyricsSearchResult.CopyFromSongInfo(songInfo);
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
}
|
||||
@@ -187,11 +197,11 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
{
|
||||
if (provider == LyricsSearchProvider.LocalMusicFile)
|
||||
{
|
||||
lyricsSearchResult = SearchEmbedded(title, artist, album);
|
||||
lyricsSearchResult = SearchEmbedded(songInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
lyricsSearchResult = await SearchFile(title, artist, album, lyricsFormat);
|
||||
lyricsSearchResult = await SearchFile(songInfo, lyricsFormat);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -199,22 +209,22 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
switch (provider)
|
||||
{
|
||||
case LyricsSearchProvider.LrcLib:
|
||||
lyricsSearchResult = await SearchLrcLibAsync(title, artist, album, (int)(durationMs / 1000));
|
||||
lyricsSearchResult = await SearchLrcLibAsync(songInfo);
|
||||
break;
|
||||
case LyricsSearchProvider.QQ:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.QQMusic);
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(songInfo, Searchers.QQMusic);
|
||||
break;
|
||||
case LyricsSearchProvider.Kugou:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.Kugou);
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(songInfo, Searchers.Kugou);
|
||||
break;
|
||||
case LyricsSearchProvider.Netease:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.Netease);
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(songInfo, Searchers.Netease);
|
||||
break;
|
||||
case LyricsSearchProvider.AmllTtmlDb:
|
||||
lyricsSearchResult = await SearchAmllTtmlDbAsync(title, artist, album);
|
||||
lyricsSearchResult = await SearchAmllTtmlDbAsync(songInfo);
|
||||
break;
|
||||
case LyricsSearchProvider.AppleMusic:
|
||||
lyricsSearchResult = await SearchAppleMusicAsync(title, artist, album, (int)durationMs);
|
||||
lyricsSearchResult = await SearchAppleMusicAsync(songInfo);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -230,7 +240,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
{
|
||||
if (provider.IsRemote())
|
||||
{
|
||||
FileHelper.WriteLyricsCache(title, artist, album, lyricsSearchResult.Raw!, lyricsFormat, provider.GetCacheDirectory());
|
||||
FileHelper.WriteLyricsCache(songInfo, lyricsSearchResult.Raw!, lyricsFormat, provider.GetCacheDirectory());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,7 +251,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private async Task<LyricsSearchResult> SearchFile(string title, string artist, string album, LyricsFormat format)
|
||||
private async Task<LyricsSearchResult> SearchFile(SongInfo songInfo, LyricsFormat format)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
@@ -256,15 +266,14 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
{
|
||||
foreach (var file in DirectoryHelper.GetAllFiles(folder.Path, $"*{format.ToFileExtension()}"))
|
||||
{
|
||||
if (FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), title, artist))
|
||||
var fileName = Path.GetFileNameWithoutExtension(file);
|
||||
if (FileHelper.IsSwitchableNormalizedMatch(fileName, songInfo.Title, songInfo.Artist) || songInfo.LinkedFileName == fileName)
|
||||
{
|
||||
string? raw = await File.ReadAllTextAsync(file, FileHelper.GetEncoding(file));
|
||||
if (raw != null)
|
||||
{
|
||||
lyricsSearchResult.Raw = raw;
|
||||
lyricsSearchResult.Title = title;
|
||||
lyricsSearchResult.Artist = artist;
|
||||
lyricsSearchResult.Album = album;
|
||||
lyricsSearchResult.CopyFromSongInfo(songInfo);
|
||||
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
@@ -279,7 +288,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private LyricsSearchResult SearchEmbedded(string title, string artist, string album)
|
||||
private LyricsSearchResult SearchEmbedded(SongInfo songInfo)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
@@ -295,17 +304,15 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
if (FileHelper.MusicExtensions.Contains(Path.GetExtension(file)))
|
||||
{
|
||||
var track = new Track(file);
|
||||
if ((album != "" && track.Title == title && track.Artist == artist && track.Album == album)
|
||||
|| (album == "" && track.Title == title && track.Artist == artist)
|
||||
|| (album == "" && FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), title, artist)))
|
||||
if ((songInfo.Album != "" && track.Title == songInfo.Title && track.Artist == songInfo.Artist && track.Album == songInfo.Album)
|
||||
|| (songInfo.Album == "" && track.Title == songInfo.Title && track.Artist == songInfo.Artist)
|
||||
|| (songInfo.Album == "" && FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), songInfo.Title, songInfo.Artist)))
|
||||
{
|
||||
var plain = track.GetLyrics();
|
||||
var plain = track.GetRawLyrics();
|
||||
if (!plain.IsNullOrEmpty())
|
||||
{
|
||||
lyricsSearchResult.Raw = plain;
|
||||
lyricsSearchResult.Title = track.Title;
|
||||
lyricsSearchResult.Artist = track.Artist;
|
||||
lyricsSearchResult.Album = track.Album;
|
||||
lyricsSearchResult.CopyFromSongInfo(songInfo);
|
||||
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
@@ -317,7 +324,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private async Task<LyricsSearchResult> SearchAmllTtmlDbAsync(string title, string artist, string album)
|
||||
private async Task<LyricsSearchResult> SearchAmllTtmlDbAsync(SongInfo songInfo)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
@@ -360,7 +367,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
if (musicName == null || artists == null)
|
||||
continue;
|
||||
|
||||
if (FileHelper.IsSwitchableNormalizedMatch($"{artists} - {musicName}", title, artist))
|
||||
if (FileHelper.IsSwitchableNormalizedMatch($"{artists} - {musicName}", songInfo.Title, songInfo.Artist))
|
||||
{
|
||||
if (root.TryGetProperty("rawLyricFile", out var rawLyricFileProp))
|
||||
{
|
||||
@@ -389,9 +396,9 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
string lyrics = await response.Content.ReadAsStringAsync();
|
||||
|
||||
lyricsSearchResult.Raw = lyrics;
|
||||
lyricsSearchResult.Title = title;
|
||||
lyricsSearchResult.Artist = artist;
|
||||
lyricsSearchResult.Album = album;
|
||||
lyricsSearchResult.Title = songInfo.Title;
|
||||
lyricsSearchResult.Artist = songInfo.Artist;
|
||||
lyricsSearchResult.Album = songInfo.Album;
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -400,7 +407,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private async Task<LyricsSearchResult> SearchLrcLibAsync(string title, string artist, string album, int duration)
|
||||
private async Task<LyricsSearchResult> SearchLrcLibAsync(SongInfo songInfo)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
@@ -410,10 +417,10 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
// Build API query URL
|
||||
var url =
|
||||
$"https://lrclib.net/api/search?" +
|
||||
$"track_name={Uri.EscapeDataString(title)}&" +
|
||||
$"artist_name={Uri.EscapeDataString(artist)}&" +
|
||||
$"&album_name={Uri.EscapeDataString(album)}" +
|
||||
$"&durationMs={Uri.EscapeDataString(duration.ToString())}";
|
||||
$"track_name={Uri.EscapeDataString(songInfo.Title)}&" +
|
||||
$"artist_name={Uri.EscapeDataString(songInfo.Artist)}&" +
|
||||
$"&album_name={Uri.EscapeDataString(songInfo.Album)}" +
|
||||
$"&durationMs={Uri.EscapeDataString(songInfo.DurationMs.ToString())}";
|
||||
|
||||
using var response = await _lrcLibHttpClient.GetAsync(url);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
@@ -450,7 +457,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private static async Task<LyricsSearchResult> SearchQQNeteaseKugouAsync(string title, string artist, string album, int durationMs, string? songId, Searchers searcher)
|
||||
private static async Task<LyricsSearchResult> SearchQQNeteaseKugouAsync(SongInfo songInfo, Searchers searcher)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult();
|
||||
|
||||
@@ -472,19 +479,19 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
}
|
||||
|
||||
ISearchResult? result;
|
||||
if (searcher == Searchers.Netease && songId != null)
|
||||
if (searcher == Searchers.Netease && songInfo.SongId != null)
|
||||
{
|
||||
result = new NeteaseSearchResult(title, [artist], album, null, durationMs, songId);
|
||||
result = new NeteaseSearchResult(songInfo.Title, [songInfo.Artist], songInfo.Album, null, (int)songInfo.DurationMs, songInfo.SongId);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await SearchHelper.Search(new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
|
||||
{
|
||||
DurationMs = durationMs,
|
||||
Album = album,
|
||||
AlbumArtists = [artist],
|
||||
Artists = [artist],
|
||||
Title = title,
|
||||
DurationMs = (int)songInfo.DurationMs,
|
||||
Album = songInfo.Album,
|
||||
AlbumArtists = [songInfo.Artist],
|
||||
Artists = [songInfo.Artist],
|
||||
Title = songInfo.Title,
|
||||
}, searcher);
|
||||
}
|
||||
|
||||
@@ -498,9 +505,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
if (!string.IsNullOrEmpty(translated))
|
||||
{
|
||||
FileHelper.WriteLyricsCache(
|
||||
title,
|
||||
artist,
|
||||
album,
|
||||
songInfo,
|
||||
translated,
|
||||
LyricsFormat.Lrc,
|
||||
PathHelper.QQTranslationCacheDirectory
|
||||
@@ -517,9 +522,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
if (!string.IsNullOrEmpty(translated))
|
||||
{
|
||||
FileHelper.WriteLyricsCache(
|
||||
title,
|
||||
artist,
|
||||
album,
|
||||
songInfo,
|
||||
translated,
|
||||
LyricsFormat.Lrc,
|
||||
PathHelper.NeteaseTranslationCacheDirectory
|
||||
@@ -555,9 +558,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
if (!string.IsNullOrEmpty(translated))
|
||||
{
|
||||
FileHelper.WriteLyricsCache(
|
||||
title,
|
||||
artist,
|
||||
album,
|
||||
songInfo,
|
||||
translated,
|
||||
LyricsFormat.Lrc,
|
||||
PathHelper.KugouTranslationCacheDirectory
|
||||
@@ -578,7 +579,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private async Task<LyricsSearchResult> SearchAppleMusicAsync(string title, string artist, string album, int durationMs)
|
||||
private async Task<LyricsSearchResult> SearchAppleMusicAsync(SongInfo songInfo)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
@@ -587,11 +588,11 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
|
||||
if (await _appleMusic.InitAsync())
|
||||
{
|
||||
var raw = await _appleMusic.GetLyricsAsync(title, artist);
|
||||
_logger.LogInformation("Apple Music lyrics search result for {Title} - {Artist}: {Raw}", title, artist, raw ?? "null");
|
||||
var raw = await _appleMusic.GetLyricsAsync(songInfo.Title, songInfo.Artist);
|
||||
_logger.LogInformation("Apple Music lyrics search result for {SongInfo}: {Raw}", songInfo, raw);
|
||||
lyricsSearchResult.Raw = raw;
|
||||
lyricsSearchResult.Title = title;
|
||||
lyricsSearchResult.Artist = artist;
|
||||
lyricsSearchResult.Title = songInfo.Title;
|
||||
lyricsSearchResult.Artist = songInfo.Artist;
|
||||
lyricsSearchResult.Album = "";
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
TimeSpan CurrentPosition { get; }
|
||||
LyricsData? CurrentLyricsData { get; }
|
||||
|
||||
LyricsSearchProvider? LyricsSearchProvider { get; }
|
||||
TranslationSearchProvider? TranslationSearchProvider { get; }
|
||||
LyricsSearchResult? CurrentLyricsSearchResult { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Events;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
@@ -26,7 +27,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
public event EventHandler<LyricsChangedEventArgs>? LyricsChanged;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsSearchProvider? LyricsSearchProvider { get; private set; }
|
||||
[ObservableProperty] public partial LyricsSearchResult? CurrentLyricsSearchResult { get; private set; }
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TranslationSearchProvider? TranslationSearchProvider { get; private set; }
|
||||
|
||||
@@ -84,7 +85,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
_logger.LogInformation("Found translated text in lyrics data at index {FoundIndex}", found);
|
||||
|
||||
_lyricsDataArr[0].SetTranslatedText(_lyricsDataArr[found], _liveStatesService.LiveStates.LyricsWindowStatus.LyricsStyleSettings.LyricsTranslationSeparator, 50);
|
||||
TranslationSearchProvider = LyricsSearchProvider.ToTranslationSearchProvider();
|
||||
TranslationSearchProvider = CurrentLyricsSearchResult?.Provider.ToTranslationSearchProvider();
|
||||
}
|
||||
else if (_settingsService.AppSettings.TranslationSettings.IsLibreTranslateEnabled)
|
||||
{
|
||||
@@ -147,7 +148,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
_logger.LogInformation("Refreshing lyrics...");
|
||||
|
||||
LyricsSearchProvider = null;
|
||||
CurrentLyricsSearchResult = null;
|
||||
_lyricsDataArr = [LyricsData.GetLoadingPlaceholder()];
|
||||
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
@@ -160,24 +161,15 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
_logger.LogInformation("Searching lyrics for: Title={Title}, Artist={Artist}, Album={Album}, DurationMs={DurationMs}",
|
||||
CurrentSongInfo.Title, CurrentSongInfo.Artist, CurrentSongInfo.Album, CurrentSongInfo.DurationMs);
|
||||
|
||||
var lyricsSearchResult = await Task.Run(async () => await _lyrcsSearchService.SearchSmartlyAsync(
|
||||
CurrentSongInfo.PlayerId ?? "",
|
||||
CurrentSongInfo.Title,
|
||||
CurrentSongInfo.Artist,
|
||||
CurrentSongInfo.Album,
|
||||
CurrentSongInfo.DurationMs,
|
||||
CurrentSongInfo.SongId,
|
||||
token
|
||||
), token);
|
||||
CurrentLyricsSearchResult = await Task.Run(async () => await _lyrcsSearchService.SearchSmartlyAsync(CurrentSongInfo, token), token);
|
||||
if (token.IsCancellationRequested) return;
|
||||
LyricsSearchProvider = lyricsSearchResult?.Provider;
|
||||
|
||||
_logger.LogInformation("Lyrics was found? {Found}, Provider: {LyricsSearchProvider}", lyricsSearchResult?.IsFound, LyricsSearchProvider);
|
||||
_logger.LogInformation("Lyrics was found? {Found}, Provider: {LyricsSearchProvider}", CurrentLyricsSearchResult?.IsFound, CurrentLyricsSearchResult?.Provider);
|
||||
|
||||
var lyricsParser = new LyricsParser();
|
||||
lyricsParser.Parse(
|
||||
_settingsService.AppSettings.MappedSongSearchQueries.ToList(),
|
||||
CurrentSongInfo.Title, CurrentSongInfo.Artist, CurrentSongInfo.Album, lyricsSearchResult?.Raw, (int?)CurrentSongInfo?.DurationMs, LyricsSearchProvider);
|
||||
CurrentSongInfo.Title, CurrentSongInfo.Artist, CurrentSongInfo.Album, CurrentLyricsSearchResult?.Raw, (int?)CurrentSongInfo?.DurationMs, CurrentLyricsSearchResult?.Provider);
|
||||
_lyricsDataArr = lyricsParser.LyricsDataArr;
|
||||
ApplyChinesePreference();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Events;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Collections;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
@@ -32,6 +32,8 @@ using System.Threading.Tasks;
|
||||
using Windows.Media.Control;
|
||||
using Windows.Storage.Streams;
|
||||
using WindowsMediaController;
|
||||
using BetterLyrics.WinUI3.Constants;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
@@ -64,7 +66,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TimeSpan CurrentPosition { get; private set; } = TimeSpan.Zero;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial SongInfo? CurrentSongInfo { get; private set; }
|
||||
|
||||
public MediaSourceProviderInfo? CurrentMediaSourceProviderInfo { get; set; }
|
||||
[ObservableProperty] public partial MediaSourceProviderInfo? CurrentMediaSourceProviderInfo { get; set; }
|
||||
|
||||
public MediaSessionsService(
|
||||
ISettingsService settingsService,
|
||||
@@ -119,7 +121,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private void UpdatePlayOrPauseSongShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.PlayOrPauseSong, _settingsService.AppSettings.GeneralSettings.PlayOrPauseShortcut, (() =>
|
||||
GlobalHotKeyHook.UpdateHotKey<LyricsWindow>(ShortcutID.PlayOrPauseSong, _settingsService.AppSettings.GeneralSettings.PlayOrPauseShortcut, (() =>
|
||||
{
|
||||
if (CurrentIsPlaying)
|
||||
{
|
||||
@@ -134,7 +136,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private void UpdatePreviousSongShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.PreviousSong, _settingsService.AppSettings.GeneralSettings.PreviousSongShortcut, () =>
|
||||
GlobalHotKeyHook.UpdateHotKey<LyricsWindow>(ShortcutID.PreviousSong, _settingsService.AppSettings.GeneralSettings.PreviousSongShortcut, () =>
|
||||
{
|
||||
_ = PreviousAsync();
|
||||
});
|
||||
@@ -142,7 +144,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private void UpdateNextSongShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.NextSong, _settingsService.AppSettings.GeneralSettings.NextSongShortcut, () =>
|
||||
GlobalHotKeyHook.UpdateHotKey<LyricsWindow>(ShortcutID.NextSong, _settingsService.AppSettings.GeneralSettings.NextSongShortcut, () =>
|
||||
{
|
||||
_ = NextAsync();
|
||||
});
|
||||
@@ -291,7 +293,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||
mediaProperties?.Title, mediaProperties?.Artist, mediaProperties?.AlbumTitle);
|
||||
|
||||
if (PlayerIdMatcher.IsLXMusic(sessionId))
|
||||
if (PlayerIDMatcher.IsLXMusic(sessionId))
|
||||
{
|
||||
StopSSE();
|
||||
}
|
||||
@@ -310,16 +312,22 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
string fixedAlbum = mediaProperties?.AlbumTitle ?? "N/A";
|
||||
string? songId = null;
|
||||
|
||||
if (sessionId == Constants.PlayerID.AppleMusic || sessionId == Constants.PlayerID.AppleMusicAlternative)
|
||||
if (PlayerIDMatcher.IsAppleMusic(sessionId))
|
||||
{
|
||||
fixedArtist = mediaProperties?.Artist.Split(" — ").FirstOrDefault() ?? (mediaProperties?.Artist ?? "N/A");
|
||||
fixedAlbum = mediaProperties?.Artist.Split(" — ").LastOrDefault() ?? (mediaProperties?.AlbumTitle ?? "N/A");
|
||||
}
|
||||
else if (PlayerIdMatcher.IsNeteaseFamily(sessionId ?? ""))
|
||||
else if (PlayerIDMatcher.IsNeteaseFamily(sessionId))
|
||||
{
|
||||
songId = mediaProperties?.Genres.FirstOrDefault()?.Replace("NCM-", "");
|
||||
songId = mediaProperties?.Genres
|
||||
.Where(x => x.StartsWith(ExtendedGenreFiled.NetEaseCloudMusicTrackID))?.FirstOrDefault()?
|
||||
.Replace(ExtendedGenreFiled.NetEaseCloudMusicTrackID, "");
|
||||
}
|
||||
|
||||
var linkedFileName = mediaProperties?.Genres
|
||||
.Where(x => x.StartsWith(ExtendedGenreFiled.FileName))?.FirstOrDefault()?
|
||||
.Replace(ExtendedGenreFiled.FileName, "");
|
||||
|
||||
CurrentSongInfo = new SongInfo
|
||||
{
|
||||
Title = mediaProperties?.Title ?? "N/A",
|
||||
@@ -327,13 +335,14 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
Album = fixedAlbum,
|
||||
DurationMs = mediaSession?.ControlSession?.GetTimelineProperties().EndTime.TotalMilliseconds ?? 0,
|
||||
PlayerId = sessionId,
|
||||
SongId = songId
|
||||
SongId = songId,
|
||||
LinkedFileName = linkedFileName
|
||||
};
|
||||
|
||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||
mediaProperties?.Title, mediaProperties?.Artist, mediaProperties?.AlbumTitle);
|
||||
|
||||
if (PlayerIdMatcher.IsLXMusic(sessionId))
|
||||
if (PlayerIDMatcher.IsLXMusic(sessionId))
|
||||
{
|
||||
StartSSE();
|
||||
}
|
||||
@@ -342,7 +351,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
StopSSE();
|
||||
}
|
||||
|
||||
if (PlayerIdMatcher.IsLXMusic(sessionId) && _lxMusicAlbumArtBytes != null)
|
||||
if (PlayerIDMatcher.IsLXMusic(sessionId) && _lxMusicAlbumArtBytes != null)
|
||||
{
|
||||
_SMTCAlbumArtBuffer = _lxMusicAlbumArtBytes.AsBuffer();
|
||||
}
|
||||
@@ -532,7 +541,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, async () =>
|
||||
{
|
||||
if (PlayerIdMatcher.IsLXMusic(CurrentSongInfo?.PlayerId))
|
||||
if (PlayerIDMatcher.IsLXMusic(CurrentSongInfo?.PlayerId))
|
||||
{
|
||||
var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement);
|
||||
if (data.ValueKind == JsonValueKind.Number)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Collections;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
using ComputeSharp;
|
||||
using ComputeSharp.D2D1;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Shaders
|
||||
{
|
||||
[D2DInputCount(0)]
|
||||
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
|
||||
[D2DGeneratedPixelShaderDescriptor]
|
||||
[D2DRequiresScenePosition]
|
||||
public readonly partial struct SnowEffect(float time, Float2 resolution) : ID2D1PixelShader
|
||||
{
|
||||
public Float4 Execute()
|
||||
{
|
||||
Float2 fragCoord = D2D.GetScenePosition().XY;
|
||||
|
||||
float snow = 0.0f;
|
||||
|
||||
for (int k = 0; k < 6; k++)
|
||||
{
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
float cellSize = 2.0f + ((float)i * 3.0f);
|
||||
float downSpeed = 0.3f + (Hlsl.Sin(time * 0.4f + (float)(k + i * 20)) + 1.0f) * 0.00008f;
|
||||
downSpeed /= 10;
|
||||
downSpeed *= -1;
|
||||
|
||||
Float2 uv = (fragCoord / resolution.X) +
|
||||
new Float2(
|
||||
0.01f * Hlsl.Sin((time + (float)(k * 6185)) * 0.6f + (float)i) * (5.0f * i),
|
||||
downSpeed * (time + (float)(k * 1352)) * i
|
||||
);
|
||||
|
||||
Float2 uvStep = (Hlsl.Ceil(uv * cellSize - new Float2(0.5f, 0.5f)) / cellSize);
|
||||
|
||||
float x = Hlsl.Frac(Hlsl.Sin(Hlsl.Dot(uvStep, new Float2(12.9898f + (float)k * 12.0f, 78.233f + (float)k * 315.156f))) * 43758.5453f + (float)k * 12.0f) - 0.5f;
|
||||
float y = Hlsl.Frac(Hlsl.Sin(Hlsl.Dot(uvStep, new Float2(62.2364f + (float)k * 23.0f, 94.674f + (float)k * 95.0f))) * 62159.8432f + (float)k * 12.0f) - 0.5f;
|
||||
|
||||
float randomMagnitude1 = Hlsl.Sin(time * 2.5f) * 0.7f / cellSize;
|
||||
float randomMagnitude2 = Hlsl.Cos(time * 2.5f) * 0.7f / cellSize;
|
||||
|
||||
float d = 5.0f * Hlsl.Distance((uvStep + new Float2(x * Hlsl.Sin(y), y) * randomMagnitude1 + new Float2(y, x) * randomMagnitude2), uv);
|
||||
|
||||
float omiVal = Hlsl.Frac(Hlsl.Sin(Hlsl.Dot(uvStep, new Float2(32.4691f, 94.615f))) * 31572.1684f);
|
||||
|
||||
if (omiVal < 0.08f)
|
||||
{
|
||||
float newd = (x + 1.0f) * 0.4f * Hlsl.Clamp(1.9f - d * (15.0f + (x * 6.3f)) * (cellSize / 1.4f), 0.0f, 1.0f);
|
||||
snow += newd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (Float4)snow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,7 +225,7 @@
|
||||
<data name="LyricsNotFound" xml:space="preserve">
|
||||
<value>Lyrics not found</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||
<data name="LyricsPageLyricsProviderPrefix.Text" xml:space="preserve">
|
||||
<value>Lyrics provider</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSearchButtonToolTip.Content" xml:space="preserve">
|
||||
@@ -258,7 +258,7 @@
|
||||
<data name="LyricsPageTranslationOnly.Header" xml:space="preserve">
|
||||
<value>Show translation only</value>
|
||||
</data>
|
||||
<data name="LyricsPageTranslationProviderPrefix.Header" xml:space="preserve">
|
||||
<data name="LyricsPageTranslationProviderPrefix.Text" xml:space="preserve">
|
||||
<value>Translation provider</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlAlbum.Text" xml:space="preserve">
|
||||
@@ -333,6 +333,9 @@
|
||||
<data name="LyricsWindowSwitchWindowHelp.Text" xml:space="preserve">
|
||||
<value>Go to Settings to add more modes</value>
|
||||
</data>
|
||||
<data name="LyricsWindowSwitchWindowTitle" xml:space="preserve">
|
||||
<value>Lyrics window switcher</value>
|
||||
</data>
|
||||
<data name="MainPageAlbumArtOnly.Content" xml:space="preserve">
|
||||
<value>Album art area only</value>
|
||||
</data>
|
||||
@@ -1150,6 +1153,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPagePlaybackShortcut.Text" xml:space="preserve">
|
||||
<value>Play</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlaybackSource.Text" xml:space="preserve">
|
||||
<value>Playback source</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||
<value>Play "Cut To The Feeling" on "soundcloud.com"</value>
|
||||
</data>
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
<data name="LyricsNotFound" xml:space="preserve">
|
||||
<value>歌詞が見つかりません</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||
<data name="LyricsPageLyricsProviderPrefix.Text" xml:space="preserve">
|
||||
<value>歌詞プロバイダー</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSearchButtonToolTip.Content" xml:space="preserve">
|
||||
@@ -258,7 +258,7 @@
|
||||
<data name="LyricsPageTranslationOnly.Header" xml:space="preserve">
|
||||
<value>翻訳のみを表示します</value>
|
||||
</data>
|
||||
<data name="LyricsPageTranslationProviderPrefix.Header" xml:space="preserve">
|
||||
<data name="LyricsPageTranslationProviderPrefix.Text" xml:space="preserve">
|
||||
<value>翻訳プロバイダー</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlAlbum.Text" xml:space="preserve">
|
||||
@@ -333,6 +333,9 @@
|
||||
<data name="LyricsWindowSwitchWindowHelp.Text" xml:space="preserve">
|
||||
<value>設定に移動して、さらにモードを追加してください</value>
|
||||
</data>
|
||||
<data name="LyricsWindowSwitchWindowTitle" xml:space="preserve">
|
||||
<value>歌詞ウィンドウスイッチャー</value>
|
||||
</data>
|
||||
<data name="MainPageAlbumArtOnly.Content" xml:space="preserve">
|
||||
<value>アルバムアートエリアのみ</value>
|
||||
</data>
|
||||
@@ -1150,6 +1153,9 @@
|
||||
<data name="SettingsPagePlaybackShortcut.Text" xml:space="preserve">
|
||||
<value>遊ぶ</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlaybackSource.Text" xml:space="preserve">
|
||||
<value>再生ソース</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||
<value>「SoundCloud.com」で「Cut to the Feeling」を再生する</value>
|
||||
</data>
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
<data name="LyricsNotFound" xml:space="preserve">
|
||||
<value>가사를 찾을 수 없습니다</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||
<data name="LyricsPageLyricsProviderPrefix.Text" xml:space="preserve">
|
||||
<value>가사 제공자</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSearchButtonToolTip.Content" xml:space="preserve">
|
||||
@@ -258,7 +258,7 @@
|
||||
<data name="LyricsPageTranslationOnly.Header" xml:space="preserve">
|
||||
<value>번역 만 표시하십시오</value>
|
||||
</data>
|
||||
<data name="LyricsPageTranslationProviderPrefix.Header" xml:space="preserve">
|
||||
<data name="LyricsPageTranslationProviderPrefix.Text" xml:space="preserve">
|
||||
<value>번역 제공자</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlAlbum.Text" xml:space="preserve">
|
||||
@@ -333,6 +333,9 @@
|
||||
<data name="LyricsWindowSwitchWindowHelp.Text" xml:space="preserve">
|
||||
<value>설정으로 이동하여 모드를 더 추가하세요</value>
|
||||
</data>
|
||||
<data name="LyricsWindowSwitchWindowTitle" xml:space="preserve">
|
||||
<value>가사 창 전환기</value>
|
||||
</data>
|
||||
<data name="MainPageAlbumArtOnly.Content" xml:space="preserve">
|
||||
<value>앨범 아트 영역만</value>
|
||||
</data>
|
||||
@@ -1150,6 +1153,9 @@
|
||||
<data name="SettingsPagePlaybackShortcut.Text" xml:space="preserve">
|
||||
<value>놀다</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlaybackSource.Text" xml:space="preserve">
|
||||
<value>재생 소스</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||
<value>"soundcloud.com"에서 "Fut to the Feeling"을 재생하십시오.</value>
|
||||
</data>
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
<data name="LyricsNotFound" xml:space="preserve">
|
||||
<value>未找到歌词</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||
<data name="LyricsPageLyricsProviderPrefix.Text" xml:space="preserve">
|
||||
<value>歌词来源</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSearchButtonToolTip.Content" xml:space="preserve">
|
||||
@@ -258,7 +258,7 @@
|
||||
<data name="LyricsPageTranslationOnly.Header" xml:space="preserve">
|
||||
<value>仅显示翻译</value>
|
||||
</data>
|
||||
<data name="LyricsPageTranslationProviderPrefix.Header" xml:space="preserve">
|
||||
<data name="LyricsPageTranslationProviderPrefix.Text" xml:space="preserve">
|
||||
<value>翻译来源</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlAlbum.Text" xml:space="preserve">
|
||||
@@ -333,6 +333,9 @@
|
||||
<data name="LyricsWindowSwitchWindowHelp.Text" xml:space="preserve">
|
||||
<value>转到“设置”以添加更多模式</value>
|
||||
</data>
|
||||
<data name="LyricsWindowSwitchWindowTitle" xml:space="preserve">
|
||||
<value>歌词窗口切换器</value>
|
||||
</data>
|
||||
<data name="MainPageAlbumArtOnly.Content" xml:space="preserve">
|
||||
<value>仅显示专辑区域</value>
|
||||
</data>
|
||||
@@ -1150,6 +1153,9 @@
|
||||
<data name="SettingsPagePlaybackShortcut.Text" xml:space="preserve">
|
||||
<value>播放</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlaybackSource.Text" xml:space="preserve">
|
||||
<value>播放源</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||
<value>在 “soundcloud.com” 上播放 “Cut to the Feeling”</value>
|
||||
</data>
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
<data name="LyricsNotFound" xml:space="preserve">
|
||||
<value>找不到歌詞</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsProviderPrefix.Header" xml:space="preserve">
|
||||
<data name="LyricsPageLyricsProviderPrefix.Text" xml:space="preserve">
|
||||
<value>歌詞來源</value>
|
||||
</data>
|
||||
<data name="LyricsPageLyricsSearchButtonToolTip.Content" xml:space="preserve">
|
||||
@@ -258,7 +258,7 @@
|
||||
<data name="LyricsPageTranslationOnly.Header" xml:space="preserve">
|
||||
<value>僅顯示翻譯</value>
|
||||
</data>
|
||||
<data name="LyricsPageTranslationProviderPrefix.Header" xml:space="preserve">
|
||||
<data name="LyricsPageTranslationProviderPrefix.Text" xml:space="preserve">
|
||||
<value>翻譯來源</value>
|
||||
</data>
|
||||
<data name="LyricsSearchControlAlbum.Text" xml:space="preserve">
|
||||
@@ -333,6 +333,9 @@
|
||||
<data name="LyricsWindowSwitchWindowHelp.Text" xml:space="preserve">
|
||||
<value>前往設定以新增更多模式</value>
|
||||
</data>
|
||||
<data name="LyricsWindowSwitchWindowTitle" xml:space="preserve">
|
||||
<value>歌詞視窗切換器</value>
|
||||
</data>
|
||||
<data name="MainPageAlbumArtOnly.Content" xml:space="preserve">
|
||||
<value>僅限相簿藝術區域</value>
|
||||
</data>
|
||||
@@ -1150,6 +1153,9 @@
|
||||
<data name="SettingsPagePlaybackShortcut.Text" xml:space="preserve">
|
||||
<value>播放</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlaybackSource.Text" xml:space="preserve">
|
||||
<value>播放源</value>
|
||||
</data>
|
||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||
<value>在 “soundcloud.com” 上播放 “Cut to the Feeling”</value>
|
||||
</data>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.ResourceService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
@@ -59,7 +60,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
var succeed = _settingsService.ImportSettings(file.Path);
|
||||
if (succeed)
|
||||
{
|
||||
WindowHelper.RestartApp();
|
||||
WindowHook.RestartApp();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
@@ -25,7 +26,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[RelayCommand]
|
||||
private static void RestartApp()
|
||||
{
|
||||
WindowHelper.RestartApp();
|
||||
WindowHook.RestartApp();
|
||||
}
|
||||
|
||||
public async Task<bool> ToggleAutoStartupAsync(bool target)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||
@@ -31,8 +32,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
LiveStates = _liveStatesService.LiveStates;
|
||||
|
||||
Volume = SystemVolumeHelper.MasterVolume;
|
||||
SystemVolumeHelper.VolumeNotification += SystemVolumeHelper_VolumeNotification;
|
||||
Volume = SystemVolumeHook.MasterVolume;
|
||||
SystemVolumeHook.VolumeNotification += SystemVolumeHelper_VolumeNotification;
|
||||
}
|
||||
|
||||
private void SystemVolumeHelper_VolumeNotification(object? sender, int e)
|
||||
@@ -68,7 +69,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[RelayCommand]
|
||||
private static void OpenSettingsWindow()
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<SettingsWindow>();
|
||||
WindowHook.OpenOrShowWindow<SettingsWindow>();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Shaders;
|
||||
using CommunityToolkit.WinUI;
|
||||
using ComputeSharp.D2D1.WinUI;
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.Graphics.Canvas.Brushes;
|
||||
using Microsoft.Graphics.Canvas.Effects;
|
||||
@@ -68,6 +71,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
DrawAlbumArt(control, ds);
|
||||
DrawSongInfo(control, ds);
|
||||
|
||||
DrawSnowEffect(control, ds);
|
||||
|
||||
if (_isDebugOverlayEnabled)
|
||||
{
|
||||
_drawFrameCount++;
|
||||
@@ -400,6 +405,20 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSnowEffect(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
||||
{
|
||||
if (_liveStatesService.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.IsSnowFlakeOverlayEnabled)
|
||||
{
|
||||
_snowEffect ??= new PixelShaderEffect<SnowEffect>();
|
||||
|
||||
var width = (float)control.ConvertDipsToPixels((float)control.Size.Width, CanvasDpiRounding.Round);
|
||||
var height = (float)control.ConvertDipsToPixels((float)control.Size.Height, CanvasDpiRounding.Round);
|
||||
_snowEffect?.ConstantBuffer = new SnowEffect((float)TotalTime.TotalSeconds, new(width, height));
|
||||
|
||||
ds.DrawImage(_snowEffect);
|
||||
}
|
||||
}
|
||||
|
||||
private void FillBackground(ICanvasAnimatedControl control, CanvasDrawingSession ds, Color color, double radius, double opacity)
|
||||
{
|
||||
ds.FillRoundedRectangle(
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Shaders;
|
||||
using ComputeSharp.D2D1.WinUI;
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.Graphics.Canvas.Effects;
|
||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||
@@ -17,6 +20,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
private OpacityEffect? _albumArtBgEffect;
|
||||
private CanvasCommandList? _albumArtEffect;
|
||||
private PixelShaderEffect? _fluidEffect;
|
||||
private PixelShaderEffect<SnowEffect>? _snowEffect;
|
||||
|
||||
private OpacityEffect CreateBgImageEffect(CanvasBitmap canvasBitmap, double opacity)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
|
||||
namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
{
|
||||
@@ -117,9 +118,12 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
if (_fluidEffect != null)
|
||||
{
|
||||
var effectTime = Convert.ToSingle(_fluidEffect.Properties["iTime"]);
|
||||
effectTime += Convert.ToSingle(_elapsedTime.TotalSeconds);
|
||||
_fluidEffect.Properties["iTime"] = effectTime;
|
||||
if (_mediaSessionsService.CurrentIsPlaying)
|
||||
{
|
||||
var effectTime = Convert.ToSingle(_fluidEffect.Properties["iTime"]);
|
||||
effectTime += Convert.ToSingle(_elapsedTime.TotalSeconds);
|
||||
_fluidEffect.Properties["iTime"] = effectTime;
|
||||
}
|
||||
|
||||
if (_albumArtAccentColor1Transition.IsTransitioning)
|
||||
{
|
||||
@@ -168,7 +172,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
_isDebugOverlayEnabledChanged = false;
|
||||
}
|
||||
|
||||
if (_liveStatesService.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.CoverOverlaySpeed > 0)
|
||||
if (_mediaSessionsService.CurrentIsPlaying && _liveStatesService.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.CoverOverlaySpeed > 0)
|
||||
{
|
||||
_rotateAngle += _coverRotateBaseSpeed * _liveStatesService.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.CoverOverlaySpeed / 100.0;
|
||||
_rotateAngle %= Math.PI * 2;
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
[ObservableProperty]
|
||||
public partial AppSettings AppSettings { get; set; }
|
||||
|
||||
private bool _isLastFMTrackEnabled = false;
|
||||
private bool _isLastFMTracked = false;
|
||||
|
||||
/// <summary>
|
||||
@@ -46,10 +45,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
/// </summary>
|
||||
private TimeSpan _elapsedTime = TimeSpan.Zero;
|
||||
|
||||
//public TimeSpan ScrollDeltaTime { get; set; } = TimeSpan.Zero;
|
||||
//private TimeSpan _scrollTime = TimeSpan.Zero;
|
||||
//public bool IsScrolling { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Get or set the current time position of the song.
|
||||
/// </summary>
|
||||
|
||||
@@ -111,10 +111,12 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
LyricsSearchResults = [..await Task.Run(async () =>
|
||||
{
|
||||
return await _lyricsSearchService.SearchAllAsync(
|
||||
MappedSongSearchQuery.MappedTitle,
|
||||
MappedSongSearchQuery.MappedArtist,
|
||||
MappedSongSearchQuery.MappedAlbum,
|
||||
_mediaSessionsService.CurrentSongInfo?.DurationMs ?? 0, token);
|
||||
new SongInfo {
|
||||
Title = MappedSongSearchQuery.MappedTitle,
|
||||
Artist = MappedSongSearchQuery.MappedArtist,
|
||||
Album = MappedSongSearchQuery.MappedAlbum,
|
||||
DurationMs = _mediaSessionsService.CurrentSongInfo?.DurationMs ?? 0
|
||||
}, token);
|
||||
}, token)];
|
||||
IsSearching = false;
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||
@@ -37,13 +38,13 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
LiveStates = _liveStatesService.LiveStates;
|
||||
MonitorDeviceNames = [.. MonitorHelper.GetAllMonitorDeviceNames()];
|
||||
MonitorDeviceNames = [.. MonitorHook.GetAllMonitorDeviceNames()];
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void RefreshMonitorDeviceNames()
|
||||
{
|
||||
MonitorDeviceNames = [.. MonitorHelper.GetAllMonitorDeviceNames()];
|
||||
MonitorDeviceNames = [.. MonitorHook.GetAllMonitorDeviceNames()];
|
||||
LiveStates.LyricsWindowStatus?.MonitorDeviceName = MonitorDeviceNames.FirstOrDefault() ?? "";
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||
@@ -33,7 +34,7 @@ namespace BetterLyrics.WinUI3
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ILiveStatesService _liveStatesService;
|
||||
|
||||
private ForegroundWindowWatcher? _fgWindowWatcher = null;
|
||||
private ForegroundWindowHook? _fgWindowWatcher = null;
|
||||
private DispatcherQueueTimer? _fgWindowWatcherTimer = null;
|
||||
|
||||
public LyricsWindowViewModel(ISettingsService settingsService, ILiveStatesService liveStatesService)
|
||||
@@ -72,11 +73,11 @@ namespace BetterLyrics.WinUI3
|
||||
|
||||
private void UpdateLyricsWindowShowHideShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.LyricsWindowShowOrHide,
|
||||
GlobalHotKeyHook.UpdateHotKey<LyricsWindow>(ShortcutID.LyricsWindowShowOrHide,
|
||||
_settingsService.AppSettings.GeneralSettings.ShowOrHideLyricsWindowShortcut,
|
||||
() =>
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
var window = WindowHook.GetWindowByWindowType<LyricsWindow>();
|
||||
if (window == null) return;
|
||||
|
||||
if (window.Visible)
|
||||
@@ -85,7 +86,7 @@ namespace BetterLyrics.WinUI3
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<LyricsWindow>();
|
||||
WindowHook.OpenOrShowWindow<LyricsWindow>();
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -93,7 +94,7 @@ namespace BetterLyrics.WinUI3
|
||||
|
||||
private void UpdateLyricsWindowBorderlessShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.Borderless,
|
||||
GlobalHotKeyHook.UpdateHotKey<LyricsWindow>(ShortcutID.Borderless,
|
||||
_settingsService.AppSettings.GeneralSettings.BorderlessShortcut,
|
||||
() =>
|
||||
{
|
||||
@@ -104,7 +105,7 @@ namespace BetterLyrics.WinUI3
|
||||
|
||||
private void UpdateLyricsWindowClickThroughShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.ClickThrough,
|
||||
GlobalHotKeyHook.UpdateHotKey<LyricsWindow>(ShortcutID.ClickThrough,
|
||||
_settingsService.AppSettings.GeneralSettings.ClickThroughShortcut,
|
||||
() =>
|
||||
{
|
||||
@@ -115,24 +116,24 @@ namespace BetterLyrics.WinUI3
|
||||
|
||||
private void UpdateLyricsWindowSwitchShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.LyricsWindowSwitch,
|
||||
GlobalHotKeyHook.UpdateHotKey<LyricsWindow>(ShortcutID.LyricsWindowSwitch,
|
||||
_settingsService.AppSettings.GeneralSettings.LyricsWindowSwitchShortcut,
|
||||
() =>
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<LyricsWindowSwitchWindow>();
|
||||
WindowHook.OpenOrShowWindow<LyricsWindowSwitchWindow>();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public void InitFgWindowWatcher()
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
var window = WindowHook.GetWindowByWindowType<LyricsWindow>();
|
||||
if (window == null) return;
|
||||
|
||||
var hwnd = WindowNative.GetWindowHandle(window);
|
||||
|
||||
_fgWindowWatcherTimer = _dispatcherQueue.CreateTimer();
|
||||
_fgWindowWatcher = new ForegroundWindowWatcher(
|
||||
_fgWindowWatcher = new ForegroundWindowHook(
|
||||
hwnd,
|
||||
fgHwnd =>
|
||||
{
|
||||
@@ -160,18 +161,18 @@ namespace BetterLyrics.WinUI3
|
||||
BackdropAccentColor = ColorHelper.GetAccentColor(
|
||||
hwnd,
|
||||
_liveStatesService.LiveStates.LyricsWindowStatus.MonitorDeviceName,
|
||||
_liveStatesService.LiveStates.LyricsWindowStatus.EnvironmentSampleMode).ToColor();
|
||||
_liveStatesService.LiveStates.LyricsWindowStatus.EnvironmentSampleMode);
|
||||
}
|
||||
|
||||
public void ExitOrClose()
|
||||
{
|
||||
if (_settingsService.AppSettings.GeneralSettings.ExitOnLyricsWindowClosed)
|
||||
{
|
||||
WindowHelper.ExitApp();
|
||||
WindowHook.ExitApp();
|
||||
}
|
||||
else
|
||||
{
|
||||
var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
var window = WindowHook.GetWindowByWindowType<LyricsWindow>();
|
||||
window?.Hide();
|
||||
}
|
||||
}
|
||||
@@ -225,7 +226,7 @@ namespace BetterLyrics.WinUI3
|
||||
{
|
||||
if (message.PropertyName == nameof(IMediaSessionsService.CurrentIsPlaying))
|
||||
{
|
||||
WindowHelper.SetLyricsWindowVisibilityByPlayingStatus(_dispatcherQueue);
|
||||
WindowHook.SetLyricsWindowVisibilityByPlayingStatus(_dispatcherQueue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using ATL;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Collections;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
@@ -24,6 +24,7 @@ using Windows.Media;
|
||||
using Windows.Media.Core;
|
||||
using Windows.Media.Playback;
|
||||
using Windows.Storage;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
|
||||
namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
@@ -446,6 +447,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
var storageFile = await StorageFile.GetFileFromPathAsync(track.Path);
|
||||
await updater.CopyFromFileAsync(MediaPlaybackType.Music, storageFile);
|
||||
updater.MusicProperties.AlbumTitle = track.Album;
|
||||
updater.MusicProperties.Genres.Add($"FILENAME-{Path.GetFileNameWithoutExtension(track.Path)}");
|
||||
updater.Update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,12 +45,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[ObservableProperty]
|
||||
public partial bool IsLXMusicServerTesting { get; set; } = false;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string OriginalLyricsRef { get; set; } = "about:blank";
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string TranslatedLyricsRef { get; set; } = "about:blank";
|
||||
|
||||
[ObservableProperty]
|
||||
public partial int SelectedTargetLanguageIndex { get; set; }
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
@@ -15,50 +16,50 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[RelayCommand]
|
||||
private static void ExitApp()
|
||||
{
|
||||
WindowHelper.ExitApp();
|
||||
WindowHook.ExitApp();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void RestartApp()
|
||||
{
|
||||
WindowHelper.RestartApp();
|
||||
WindowHook.RestartApp();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void ResetWindowPosition()
|
||||
{
|
||||
var lyricsWindow = WindowHelper.GetWindowByWindowType<LyricsWindow>();
|
||||
var lyricsWindow = WindowHook.GetWindowByWindowType<LyricsWindow>();
|
||||
lyricsWindow?.MoveAndResize(100, 100, 800, 500);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void OpenSettings()
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<SettingsWindow>();
|
||||
WindowHook.OpenOrShowWindow<SettingsWindow>();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void OpenMusicGallery()
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<MusicGalleryWindow>();
|
||||
WindowHook.OpenOrShowWindow<MusicGalleryWindow>();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void OpenLyrics()
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<LyricsWindow>();
|
||||
WindowHook.OpenOrShowWindow<LyricsWindow>();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void OpenLyricsWindowSwitch()
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<LyricsWindowSwitchWindow>();
|
||||
WindowHook.OpenOrShowWindow<LyricsWindowSwitchWindow>();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void OpenLyricsSearchWindow()
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<LyricsSearchWindow>();
|
||||
WindowHook.OpenOrShowWindow<LyricsSearchWindow>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
<!-- Lyrics area -->
|
||||
<renderer:LyricsRenderer />
|
||||
|
||||
<dev:SnowFlakeEffect FlakeCount="{x:Bind ViewModel.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.SnowFlakeOverlayAmount, Mode=OneWay}" Visibility="{x:Bind ViewModel.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.IsSnowFlakeOverlayEnabled, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
|
||||
<ScrollViewer HorizontalAlignment="Center" VerticalScrollBarVisibility="Hidden">
|
||||
<StackPanel
|
||||
Margin="40"
|
||||
@@ -36,8 +34,6 @@
|
||||
dev:Growl.GrowlParent="True" />
|
||||
</ScrollViewer>
|
||||
|
||||
<!--<Grid x:Name="ScrollGrid" PointerWheelChanged="ScrollGrid_PointerWheelChanged" Background="{ThemeResource AccentAcrylicBackgroundFillColorDefaultBrush}" Opacity="0.3"/>-->
|
||||
|
||||
<!-- Bottom command area -->
|
||||
<Grid
|
||||
x:Name="BottomCommandGrid"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using BetterLyrics.WinUI3.Controls;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
@@ -131,7 +132,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
|
||||
private void LyricsSearchShortcutButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<LyricsSearchWindow>();
|
||||
WindowHook.OpenOrShowWindow<LyricsSearchWindow>();
|
||||
}
|
||||
|
||||
private void TimelineSliderOverlay_PointerPressed(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
|
||||
@@ -180,7 +181,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
|
||||
private void ExtendedSlider_ValueChangedByUser(object sender, Events.ExtendedSliderValueChangedByUserEventArgs e)
|
||||
{
|
||||
SystemVolumeHelper.MasterVolume = ViewModel.Volume;
|
||||
SystemVolumeHook.MasterVolume = ViewModel.Volume;
|
||||
}
|
||||
|
||||
//private void ScrollGrid_PointerWheelChanged(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services.ResourceService;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Windowing;
|
||||
@@ -14,26 +18,18 @@ namespace BetterLyrics.WinUI3.Views
|
||||
/// </summary>
|
||||
public sealed partial class LyricsSearchWindow : Window
|
||||
{
|
||||
private readonly IResourceService _resourceService = Ioc.Default.GetRequiredService<IResourceService>();
|
||||
|
||||
public LyricsSearchWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Title = _resourceService.GetLocalizedString("LyricsSearchPageTitle");
|
||||
AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;
|
||||
AppWindow.SetIcons();
|
||||
|
||||
ExtendsContentIntoTitleBar = true;
|
||||
this.Init("LyricsSearchPageTitle", backdropType: BackdropType.Transparent);
|
||||
|
||||
AppWindow.Closing += AppWindow_Closing;
|
||||
|
||||
SystemBackdrop = SystemBackdropHelper.CreateSystemBackdrop(Enums.BackdropType.Transparent);
|
||||
}
|
||||
|
||||
private void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args)
|
||||
{
|
||||
WindowHelper.CloseWindow<LyricsSearchWindow>();
|
||||
WindowHook.CloseWindow<LyricsSearchWindow>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Services.LiveStatesService;
|
||||
using BetterLyrics.WinUI3.Services.ResourceService;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
@@ -16,7 +18,6 @@ namespace BetterLyrics.WinUI3.Views
|
||||
public sealed partial class LyricsWindow : Window
|
||||
{
|
||||
private readonly ILiveStatesService _liveStatesService = Ioc.Default.GetRequiredService<ILiveStatesService>();
|
||||
private readonly IResourceService _resourceService = Ioc.Default.GetRequiredService<IResourceService>();
|
||||
|
||||
private readonly WindowMessageMonitor _wmm;
|
||||
|
||||
@@ -26,18 +27,12 @@ namespace BetterLyrics.WinUI3.Views
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
AppWindow.SetIcons();
|
||||
|
||||
AppWindow.Changed += AppWindow_Changed;
|
||||
|
||||
ExtendsContentIntoTitleBar = true;
|
||||
AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Collapsed;
|
||||
|
||||
Title = _resourceService.GetLocalizedString("LyricsPageTitle");
|
||||
|
||||
_wmm = new WindowMessageMonitor(this);
|
||||
_wmm.WindowMessageReceived += Wmm_WindowMessageReceived;
|
||||
|
||||
this.Init("LyricsPageTitle", TitleBarHeightOption.Collapsed, BackdropType.Transparent);
|
||||
|
||||
AppWindow.Changed += AppWindow_Changed;
|
||||
AppWindow.Closing += AppWindow_Closing;
|
||||
}
|
||||
|
||||
@@ -70,7 +65,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
if (e.Message.MessageId == (uint)User32.WindowMessage.WM_HOTKEY)
|
||||
{
|
||||
int id = (int)e.Message.WParam;
|
||||
GlobalHotKeyHelper.TryInvokeAction(id);
|
||||
GlobalHotKeyHook.TryInvokeAction(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +104,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
|
||||
private void MusicGalleryButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<MusicGalleryWindow>();
|
||||
WindowHook.OpenOrShowWindow<MusicGalleryWindow>();
|
||||
}
|
||||
|
||||
private void CloseButton_Click(object sender, RoutedEventArgs e)
|
||||
@@ -119,12 +114,12 @@ namespace BetterLyrics.WinUI3.Views
|
||||
|
||||
private void LyricsWindowSwitchButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<LyricsWindowSwitchWindow>();
|
||||
WindowHook.OpenOrShowWindow<LyricsWindowSwitchWindow>();
|
||||
}
|
||||
|
||||
private void SettingsWindowButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<SettingsWindow>();
|
||||
WindowHook.OpenOrShowWindow<SettingsWindow>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using WinUIEx;
|
||||
|
||||
@@ -20,10 +24,9 @@ namespace BetterLyrics.WinUI3.Views
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
AppWindow.TitleBar.ExtendsContentIntoTitleBar = true;
|
||||
AppWindow.TitleBar.PreferredHeightOption = Microsoft.UI.Windowing.TitleBarHeightOption.Collapsed;
|
||||
this.Init("LyricsWindowSwitchWindowTitle", TitleBarHeightOption.Collapsed, BackdropType.Transparent);
|
||||
|
||||
this.CenterOnScreen();
|
||||
this.SystemBackdrop = SystemBackdropHelper.CreateSystemBackdrop(Enums.BackdropType.Transparent);
|
||||
this.SetWindowStyle(WindowStyle.Popup | WindowStyle.Visible);
|
||||
AppWindow.IsShownInSwitchers = false;
|
||||
this.SetIsAlwaysOnTop(true);
|
||||
@@ -32,7 +35,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
AppWindow.Changed += AppWindow_Changed;
|
||||
}
|
||||
|
||||
private void AppWindow_Changed(Microsoft.UI.Windowing.AppWindow sender, Microsoft.UI.Windowing.AppWindowChangedEventArgs args)
|
||||
private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
|
||||
{
|
||||
if (args.DidVisibilityChange)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:dev="using:DevWinUI"
|
||||
xmlns:ext="using:BetterLyrics.WinUI3.Extensions"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Views"
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
using ATL;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.ResourceService;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using DevWinUI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Window.SystemBackdrop>
|
||||
<DesktopAcrylicBackdrop />
|
||||
</Window.SystemBackdrop>
|
||||
|
||||
<Grid>
|
||||
|
||||
<local:MusicGalleryPage Margin="0,40,0,0" />
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Services.ResourceService;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Windowing;
|
||||
@@ -14,34 +16,28 @@ namespace BetterLyrics.WinUI3.Views
|
||||
/// </summary>
|
||||
public sealed partial class MusicGalleryWindow : Window
|
||||
{
|
||||
private readonly IResourceService _resourceService = Ioc.Default.GetRequiredService<IResourceService>();
|
||||
|
||||
public MusicGalleryWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Title = _resourceService.GetLocalizedString("MusicGalleryPageTitle");
|
||||
AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;
|
||||
AppWindow.SetIcons();
|
||||
|
||||
ExtendsContentIntoTitleBar = true;
|
||||
this.Init("MusicGalleryPageTitle");
|
||||
|
||||
AppWindow.Closing += AppWindow_Closing;
|
||||
}
|
||||
|
||||
private void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args)
|
||||
{
|
||||
WindowHelper.CloseWindow<MusicGalleryWindow>();
|
||||
WindowHook.CloseWindow<MusicGalleryWindow>();
|
||||
}
|
||||
|
||||
private void LyricsWindowButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<LyricsWindow>();
|
||||
WindowHook.OpenOrShowWindow<LyricsWindow>();
|
||||
}
|
||||
|
||||
private void SettingsWindowButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<SettingsWindow>();
|
||||
WindowHook.OpenOrShowWindow<SettingsWindow>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Window.SystemBackdrop>
|
||||
<DesktopAcrylicBackdrop />
|
||||
</Window.SystemBackdrop>
|
||||
|
||||
<Grid x:Name="RootGrid">
|
||||
<Frame x:Name="RootFrame" Margin="0,40,0,0" />
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using BetterLyrics.WinUI3.Extensions;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Hooks;
|
||||
using BetterLyrics.WinUI3.Services.ResourceService;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
@@ -16,11 +18,8 @@ namespace BetterLyrics.WinUI3.Views
|
||||
public SettingsWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
Title = _resourceService.GetLocalizedString("SettingsPageTitle");
|
||||
AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;
|
||||
AppWindow.SetIcons();
|
||||
|
||||
ExtendsContentIntoTitleBar = true;
|
||||
this.Init("SettingsPageTitle");
|
||||
|
||||
AppWindow.Closing += AppWindow_Closing;
|
||||
|
||||
@@ -29,17 +28,17 @@ namespace BetterLyrics.WinUI3.Views
|
||||
|
||||
private void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args)
|
||||
{
|
||||
WindowHelper.CloseWindow<SettingsWindow>();
|
||||
WindowHook.CloseWindow<SettingsWindow>();
|
||||
}
|
||||
|
||||
private void LyricsWindowButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<LyricsWindow>();
|
||||
WindowHook.OpenOrShowWindow<LyricsWindow>();
|
||||
}
|
||||
|
||||
private void MusicGalleryButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowHelper.OpenOrShowWindow<MusicGalleryWindow>();
|
||||
WindowHook.OpenOrShowWindow<MusicGalleryWindow>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user