mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-12 19:24:55 +08:00
add: support qq music, kugou music, netease music as lyrics providers
This commit is contained in:
@@ -45,6 +45,7 @@
|
||||
<converter:ColorToBrushConverter x:Key="ColorToBrushConverter" />
|
||||
<converter:MatchedLocalFilesPathToVisibilityConverter x:Key="MatchedLocalFilesPathToVisibilityConverter" />
|
||||
<converter:IntToCornerRadius x:Key="IntToCornerRadius" />
|
||||
<converter:CornerRadiusToDoubleConverter x:Key="CornerRadiusToDoubleConverter" />
|
||||
<converter:LyricsSearchProviderToDisplayNameConverter x:Key="LyricsSearchProviderToDisplayNameConverter" />
|
||||
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
||||
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BetterInAppLyrics.WinUI3.ViewModels;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
@@ -12,9 +15,6 @@ using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.Windows.ApplicationModel.Resources;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
@@ -183,7 +183,7 @@ namespace BetterLyrics.WinUI3
|
||||
UnobservedTaskExceptionEventArgs e
|
||||
)
|
||||
{
|
||||
_logger.LogError(e.Exception, "TaskScheduler_UnobservedTaskException");
|
||||
//_logger.LogError(e.Exception, "TaskScheduler_UnobservedTaskException");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Helpers" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
|
||||
<PackageReference Include="Lyricify.Lyrics.Helper-NativeAot" Version="0.1.4-alpha.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.6" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.6" />
|
||||
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using System;
|
||||
using Windows.UI;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
@@ -10,7 +10,7 @@ namespace BetterLyrics.WinUI3.Converter
|
||||
/// <summary>
|
||||
/// Defines the <see cref="ColorToBrushConverter" />
|
||||
/// </summary>
|
||||
public class ColorToBrushConverter : IValueConverter
|
||||
public partial class ColorToBrushConverter : IValueConverter
|
||||
{
|
||||
#region Methods
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
internal partial class CornerRadiusToDoubleConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is Microsoft.UI.Xaml.CornerRadius cornerRadius)
|
||||
{
|
||||
// Convert CornerRadius to an integer value, e.g., using the top-left radius
|
||||
return (double)cornerRadius.TopLeft;
|
||||
}
|
||||
return .0; // or handle the case where value is not a CornerRadius
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the <see cref="EnumToIntConverter" />
|
||||
/// </summary>
|
||||
internal class EnumToIntConverter : IValueConverter
|
||||
internal partial class EnumToIntConverter : IValueConverter
|
||||
{
|
||||
#region Methods
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the <see cref="IntToCornerRadius" />
|
||||
/// </summary>
|
||||
public class IntToCornerRadius : IValueConverter
|
||||
public partial class IntToCornerRadius : IValueConverter
|
||||
{
|
||||
#region Methods
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace BetterLyrics.WinUI3.Converter
|
||||
/// <summary>
|
||||
/// Defines the <see cref="LyricsSearchProviderToDisplayNameConverter" />
|
||||
/// </summary>
|
||||
public class LyricsSearchProviderToDisplayNameConverter : IValueConverter
|
||||
public partial class LyricsSearchProviderToDisplayNameConverter : IValueConverter
|
||||
{
|
||||
#region Methods
|
||||
|
||||
@@ -30,9 +30,18 @@ namespace BetterLyrics.WinUI3.Converter
|
||||
LyricsSearchProvider.LrcLib => App.ResourceLoader!.GetString(
|
||||
"LyricsSearchProviderLrcLib"
|
||||
),
|
||||
//LyricsSearchProvider.AmllTtmlDb => App.ResourceLoader!.GetString(
|
||||
// "LyricsSearchProviderAmllTtmlDb"
|
||||
//),
|
||||
LyricsSearchProvider.QQ => App.ResourceLoader!.GetString(
|
||||
"LyricsSearchProviderQQ"
|
||||
),
|
||||
LyricsSearchProvider.Netease => App.ResourceLoader!.GetString(
|
||||
"LyricsSearchProviderNetease"
|
||||
),
|
||||
LyricsSearchProvider.Kugou => App.ResourceLoader!.GetString(
|
||||
"LyricsSearchProviderKugou"
|
||||
),
|
||||
LyricsSearchProvider.AmllTtmlDb => App.ResourceLoader!.GetString(
|
||||
"LyricsSearchProviderAmllTtmlDb"
|
||||
),
|
||||
LyricsSearchProvider.LocalLrcFile => App.ResourceLoader!.GetString(
|
||||
"LyricsSearchProviderLocalLrcFile"
|
||||
),
|
||||
@@ -45,7 +54,7 @@ namespace BetterLyrics.WinUI3.Converter
|
||||
LyricsSearchProvider.LocalTtmlFile => App.ResourceLoader!.GetString(
|
||||
"LyricsSearchProviderTtmlFile"
|
||||
),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(provider), provider, null),
|
||||
_ => "",
|
||||
};
|
||||
}
|
||||
return "";
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the <see cref="MatchedLocalFilesPathToVisibilityConverter" />
|
||||
/// </summary>
|
||||
public class MatchedLocalFilesPathToVisibilityConverter : IValueConverter
|
||||
public partial class MatchedLocalFilesPathToVisibilityConverter : IValueConverter
|
||||
{
|
||||
#region Methods
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
/// Defines the Ttml
|
||||
/// </summary>
|
||||
Ttml,
|
||||
Qrc,
|
||||
Krc,
|
||||
NotSpecified,
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -45,7 +48,7 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
/// </summary>
|
||||
/// <param name="content">The content<see cref="string"/></param>
|
||||
/// <returns>The <see cref="LyricsFormat?"/></returns>
|
||||
public static LyricsFormat? Detect(string content)
|
||||
public static LyricsFormat? DetectFormat(this string content)
|
||||
{
|
||||
if (
|
||||
content.StartsWith("<?xml")
|
||||
@@ -81,9 +84,11 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
return format switch
|
||||
{
|
||||
LyricsFormat.Lrc => ".lrc",
|
||||
LyricsFormat.Qrc => ".qrc",
|
||||
LyricsFormat.Krc => ".krc",
|
||||
LyricsFormat.Eslrc => ".eslrc",
|
||||
LyricsFormat.Ttml => ".ttml",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(format), format, null),
|
||||
_ => ".*",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
#region Enums
|
||||
@@ -13,8 +15,11 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
/// Defines the LrcLib
|
||||
/// </summary>
|
||||
LrcLib,
|
||||
QQ,
|
||||
Netease,
|
||||
Kugou,
|
||||
|
||||
//AmllTtmlDb,
|
||||
AmllTtmlDb,
|
||||
|
||||
/// <summary>
|
||||
/// Defines the LocalMusicFile
|
||||
@@ -37,5 +42,56 @@ namespace BetterLyrics.WinUI3.Enums
|
||||
LocalTtmlFile,
|
||||
}
|
||||
|
||||
public static class LyricsSearchProviderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// The IsLocal
|
||||
/// </summary>
|
||||
/// <param name="provider">The provider<see cref="LyricsSearchProvider"/></param>
|
||||
/// <returns>The <see cref="bool"/></returns>
|
||||
public static bool IsLocal(this LyricsSearchProvider provider)
|
||||
{
|
||||
return provider
|
||||
is LyricsSearchProvider.LocalMusicFile
|
||||
or LyricsSearchProvider.LocalLrcFile
|
||||
or LyricsSearchProvider.LocalEslrcFile
|
||||
or LyricsSearchProvider.LocalTtmlFile;
|
||||
}
|
||||
|
||||
public static bool IsRemote(this LyricsSearchProvider provider)
|
||||
{
|
||||
return !provider.IsLocal();
|
||||
}
|
||||
|
||||
public static string GetCacheDirectory(this LyricsSearchProvider provider)
|
||||
{
|
||||
return provider switch
|
||||
{
|
||||
LyricsSearchProvider.LrcLib => AppInfo.LrcLibLyricsCacheDirectory,
|
||||
LyricsSearchProvider.QQ => AppInfo.QQLyricsCacheDirectory,
|
||||
LyricsSearchProvider.Netease => AppInfo.NeteaseLyricsCacheDirectory,
|
||||
LyricsSearchProvider.Kugou => AppInfo.KugouLyricsCacheDirectory,
|
||||
LyricsSearchProvider.AmllTtmlDb => AppInfo.AmllTtmlDbLyricsCacheDirectory,
|
||||
_ => throw new System.ArgumentOutOfRangeException(nameof(provider)),
|
||||
};
|
||||
}
|
||||
|
||||
public static LyricsFormat GetLyricsFormat(this LyricsSearchProvider provider)
|
||||
{
|
||||
return provider switch
|
||||
{
|
||||
LyricsSearchProvider.LrcLib => LyricsFormat.Lrc,
|
||||
LyricsSearchProvider.QQ => LyricsFormat.Qrc,
|
||||
LyricsSearchProvider.Kugou => LyricsFormat.Krc,
|
||||
LyricsSearchProvider.Netease => LyricsFormat.Lrc,
|
||||
LyricsSearchProvider.AmllTtmlDb => LyricsFormat.Ttml,
|
||||
LyricsSearchProvider.LocalLrcFile => LyricsFormat.Lrc,
|
||||
LyricsSearchProvider.LocalEslrcFile => LyricsFormat.Eslrc,
|
||||
LyricsSearchProvider.LocalTtmlFile => LyricsFormat.Ttml,
|
||||
_ => LyricsFormat.NotSpecified,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -199,6 +199,19 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 立即跳转到指定值,无动画
|
||||
/// </summary>
|
||||
/// <param name="value">目标值</param>
|
||||
public void JumpTo(T value)
|
||||
{
|
||||
_currentValue = value;
|
||||
_startValue = value;
|
||||
_targetValue = value;
|
||||
_progress = 1f;
|
||||
_isTransitioning = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Update
|
||||
/// </summary>
|
||||
|
||||
@@ -83,6 +83,10 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public static string AmllTtmlDbLyricsCacheDirectory =>
|
||||
Path.Combine(CacheFolder, "amll-ttml-db-lyrics");
|
||||
public static string QQLyricsCacheDirectory => Path.Combine(CacheFolder, "qq-lyrics");
|
||||
public static string KugouLyricsCacheDirectory => Path.Combine(CacheFolder, "kugou-lyrics");
|
||||
public static string NeteaseLyricsCacheDirectory =>
|
||||
Path.Combine(CacheFolder, "netease-lyrics");
|
||||
|
||||
public static string AmllTtmlDbIndexPath =>
|
||||
Path.Combine(CacheFolder, "amll-ttml-db-index.json");
|
||||
@@ -116,6 +120,9 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
Directory.CreateDirectory(LocalFolder);
|
||||
Directory.CreateDirectory(LogDirectory);
|
||||
Directory.CreateDirectory(LrcLibLyricsCacheDirectory);
|
||||
Directory.CreateDirectory(QQLyricsCacheDirectory);
|
||||
Directory.CreateDirectory(KugouLyricsCacheDirectory);
|
||||
Directory.CreateDirectory(NeteaseLyricsCacheDirectory);
|
||||
Directory.CreateDirectory(AmllTtmlDbLyricsCacheDirectory);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using Lyricify.Lyrics.Models;
|
||||
using Microsoft.UI.Xaml.Shapes;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
@@ -50,6 +52,18 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
case LyricsFormat.Eslrc:
|
||||
ParseLrc(raw, durationMs);
|
||||
break;
|
||||
case LyricsFormat.Qrc:
|
||||
ParseUsingLyricify(
|
||||
Lyricify.Lyrics.Parsers.QrcParser.Parse(raw).Lines,
|
||||
durationMs
|
||||
);
|
||||
break;
|
||||
case LyricsFormat.Krc:
|
||||
ParseUsingLyricify(
|
||||
Lyricify.Lyrics.Parsers.KrcParser.Parse(raw).Lines,
|
||||
durationMs
|
||||
);
|
||||
break;
|
||||
case LyricsFormat.Ttml:
|
||||
ParseTtml(raw, durationMs);
|
||||
break;
|
||||
@@ -204,6 +218,69 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseUsingLyricify(List<ILineInfo>? lines, int durationMs)
|
||||
{
|
||||
List<LyricsLine> lyricsLines = [];
|
||||
|
||||
if (lines != null && lines.Count > 0)
|
||||
{
|
||||
lyricsLines = [];
|
||||
for (int lineIndex = 0; lineIndex < lines.Count; lineIndex++)
|
||||
{
|
||||
var lineRead = lines[lineIndex];
|
||||
var lineWrite = new LyricsLine
|
||||
{
|
||||
StartMs = lineRead.StartTime ?? 0,
|
||||
Text = lineRead.Text,
|
||||
CharTimings = [],
|
||||
};
|
||||
|
||||
if (lineIndex + 1 < lines.Count)
|
||||
{
|
||||
lineWrite.EndMs = lines[lineIndex + 1].StartTime ?? 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lineWrite.EndMs = durationMs;
|
||||
}
|
||||
|
||||
var syllables = (lineRead as SyllableLineInfo)?.Syllables;
|
||||
if (syllables != null)
|
||||
{
|
||||
int startIndex = 0;
|
||||
for (
|
||||
int syllableIndex = 0;
|
||||
syllableIndex < syllables.Count;
|
||||
syllableIndex++
|
||||
)
|
||||
{
|
||||
var syllable = syllables[syllableIndex];
|
||||
var charTiming = new CharTiming
|
||||
{
|
||||
StartMs = syllable.StartTime,
|
||||
Text = syllable.Text,
|
||||
StartIndex = startIndex,
|
||||
};
|
||||
if (syllableIndex + 1 < syllables.Count)
|
||||
{
|
||||
charTiming.EndMs = syllables[syllableIndex + 1].StartTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
charTiming.EndMs = lineWrite.EndMs;
|
||||
}
|
||||
lineWrite.CharTimings.Add(charTiming);
|
||||
startIndex += syllable.Text.Length;
|
||||
}
|
||||
}
|
||||
|
||||
lyricsLines.Add(lineWrite);
|
||||
}
|
||||
}
|
||||
|
||||
_multiLangLyricsLines.Add(lyricsLines);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ParseTtml
|
||||
/// </summary>
|
||||
|
||||
@@ -118,117 +118,108 @@ namespace BetterLyrics.WinUI3.Services
|
||||
}
|
||||
|
||||
string? cachedLyrics;
|
||||
LyricsFormat lyricsFormat = provider.Provider.GetLyricsFormat();
|
||||
|
||||
switch (provider.Provider)
|
||||
// Check cache first
|
||||
if (provider.Provider.IsRemote())
|
||||
{
|
||||
case LyricsSearchProvider.LrcLib:
|
||||
// Check cache first
|
||||
cachedLyrics = ReadCache(
|
||||
title,
|
||||
artist,
|
||||
LyricsFormat.Lrc,
|
||||
AppInfo.LrcLibLyricsCacheDirectory
|
||||
);
|
||||
if (!string.IsNullOrWhiteSpace(cachedLyrics))
|
||||
{
|
||||
return (cachedLyrics, LyricsFormat.Lrc);
|
||||
}
|
||||
break;
|
||||
//case LyricsSearchProvider.AmllTtmlDb:
|
||||
// // Check cache first
|
||||
// cachedLyrics = ReadCache(
|
||||
// title,
|
||||
// artist,
|
||||
// LyricsFormat.Ttml,
|
||||
// AppInfo.AmllTtmlDbLyricsCacheDirectory
|
||||
// );
|
||||
// if (!string.IsNullOrWhiteSpace(cachedLyrics))
|
||||
// {
|
||||
// return (cachedLyrics, LyricsFormat.Ttml);
|
||||
// }
|
||||
// break;
|
||||
default:
|
||||
break;
|
||||
cachedLyrics = ReadCache(
|
||||
title,
|
||||
artist,
|
||||
lyricsFormat,
|
||||
provider.Provider.GetCacheDirectory()
|
||||
);
|
||||
if (!string.IsNullOrWhiteSpace(cachedLyrics))
|
||||
{
|
||||
return (cachedLyrics, lyricsFormat);
|
||||
}
|
||||
}
|
||||
|
||||
string? searchedLyrics = null;
|
||||
|
||||
switch (provider.Provider)
|
||||
if (provider.Provider.IsLocal())
|
||||
{
|
||||
case LyricsSearchProvider.LocalMusicFile:
|
||||
if (provider.Provider == LyricsSearchProvider.LocalMusicFile)
|
||||
{
|
||||
searchedLyrics = LocalLyricsSearchInMusicFiles(title, artist);
|
||||
break;
|
||||
case LyricsSearchProvider.LocalLrcFile:
|
||||
}
|
||||
else
|
||||
{
|
||||
searchedLyrics = await LocalLyricsSearchInLyricsFiles(
|
||||
title,
|
||||
artist,
|
||||
LyricsFormat.Lrc
|
||||
lyricsFormat
|
||||
);
|
||||
break;
|
||||
case LyricsSearchProvider.LocalEslrcFile:
|
||||
searchedLyrics = await LocalLyricsSearchInLyricsFiles(
|
||||
title,
|
||||
artist,
|
||||
LyricsFormat.Eslrc
|
||||
);
|
||||
break;
|
||||
case LyricsSearchProvider.LocalTtmlFile:
|
||||
searchedLyrics = await LocalLyricsSearchInLyricsFiles(
|
||||
title,
|
||||
artist,
|
||||
LyricsFormat.Ttml
|
||||
);
|
||||
break;
|
||||
case LyricsSearchProvider.LrcLib:
|
||||
searchedLyrics = await SearchLrcLibAsync(
|
||||
title,
|
||||
artist,
|
||||
album,
|
||||
(int)(durationMs / 1000),
|
||||
matchMode
|
||||
);
|
||||
break;
|
||||
//case LyricsSearchProvider.AmllTtmlDb:
|
||||
// searchedLyrics = await SearchAmllTtmlDbAsync(title, artist);
|
||||
// break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(searchedLyrics))
|
||||
else
|
||||
{
|
||||
switch (provider.Provider)
|
||||
{
|
||||
case LyricsSearchProvider.LrcLib:
|
||||
WriteCache(
|
||||
searchedLyrics = await SearchLrcLibAsync(
|
||||
title,
|
||||
artist,
|
||||
searchedLyrics,
|
||||
LyricsFormat.Lrc,
|
||||
AppInfo.LrcLibLyricsCacheDirectory
|
||||
album,
|
||||
(int)(durationMs / 1000),
|
||||
matchMode
|
||||
);
|
||||
return (searchedLyrics, LyricsFormat.Lrc);
|
||||
//case LyricsSearchProvider.AmllTtmlDb:
|
||||
// WriteCache(
|
||||
// title,
|
||||
// artist,
|
||||
// searchedLyrics,
|
||||
// LyricsFormat.Ttml,
|
||||
// AppInfo.AmllTtmlDbLyricsCacheDirectory
|
||||
// );
|
||||
// return (searchedLyrics, LyricsFormat.Ttml);
|
||||
case LyricsSearchProvider.LocalMusicFile:
|
||||
return (searchedLyrics, LyricsFormatExtensions.Detect(searchedLyrics));
|
||||
case LyricsSearchProvider.LocalLrcFile:
|
||||
return (searchedLyrics, LyricsFormat.Lrc);
|
||||
case LyricsSearchProvider.LocalEslrcFile:
|
||||
return (searchedLyrics, LyricsFormat.Eslrc);
|
||||
case LyricsSearchProvider.LocalTtmlFile:
|
||||
return (searchedLyrics, LyricsFormat.Ttml);
|
||||
break;
|
||||
case LyricsSearchProvider.QQ:
|
||||
searchedLyrics = await SearchQQAsync(
|
||||
title,
|
||||
artist,
|
||||
album,
|
||||
(int)durationMs,
|
||||
matchMode
|
||||
);
|
||||
break;
|
||||
case LyricsSearchProvider.Kugou:
|
||||
searchedLyrics = await SearchKugouAsync(
|
||||
title,
|
||||
artist,
|
||||
album,
|
||||
(int)durationMs,
|
||||
matchMode
|
||||
);
|
||||
break;
|
||||
case LyricsSearchProvider.Netease:
|
||||
searchedLyrics = await SearchNeteaseAsync(
|
||||
title,
|
||||
artist,
|
||||
album,
|
||||
(int)durationMs,
|
||||
matchMode
|
||||
);
|
||||
break;
|
||||
case LyricsSearchProvider.AmllTtmlDb:
|
||||
searchedLyrics = await SearchAmllTtmlDbAsync(title, artist);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(searchedLyrics))
|
||||
{
|
||||
if (provider.Provider.IsRemote())
|
||||
{
|
||||
WriteCache(
|
||||
title,
|
||||
artist,
|
||||
searchedLyrics,
|
||||
lyricsFormat,
|
||||
provider.Provider.GetCacheDirectory()
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
searchedLyrics,
|
||||
lyricsFormat == LyricsFormat.NotSpecified
|
||||
? searchedLyrics.DetectFormat()
|
||||
: lyricsFormat
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (null, null);
|
||||
@@ -332,7 +323,10 @@ namespace BetterLyrics.WinUI3.Services
|
||||
return plain;
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -422,6 +416,124 @@ namespace BetterLyrics.WinUI3.Services
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<string?> SearchQQAsync(
|
||||
string title,
|
||||
string artist,
|
||||
string album,
|
||||
int durationMs,
|
||||
MusicSearchMatchMode matchMode
|
||||
)
|
||||
{
|
||||
string? queryId = (
|
||||
(
|
||||
await new Lyricify.Lyrics.Searchers.QQMusicSearcher().SearchForResult(
|
||||
new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
|
||||
{
|
||||
DurationMs =
|
||||
matchMode == MusicSearchMatchMode.TitleArtistAlbumAndDuration
|
||||
? durationMs
|
||||
: null,
|
||||
Album =
|
||||
matchMode == MusicSearchMatchMode.TitleArtistAlbumAndDuration
|
||||
? album
|
||||
: null,
|
||||
AlbumArtists = [artist],
|
||||
Artists = [artist],
|
||||
Title = title,
|
||||
}
|
||||
)
|
||||
) as Lyricify.Lyrics.Searchers.QQMusicSearchResult
|
||||
)?.Id;
|
||||
if (queryId is string id)
|
||||
{
|
||||
return (await Lyricify.Lyrics.Decrypter.Qrc.Helper.GetLyricsAsync(id))?.Lyrics;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<string?> SearchKugouAsync(
|
||||
string title,
|
||||
string artist,
|
||||
string album,
|
||||
int durationMs,
|
||||
MusicSearchMatchMode matchMode
|
||||
)
|
||||
{
|
||||
string? queryHash = (
|
||||
(
|
||||
await new Lyricify.Lyrics.Searchers.KugouSearcher().SearchForResult(
|
||||
new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
|
||||
{
|
||||
DurationMs =
|
||||
matchMode == MusicSearchMatchMode.TitleArtistAlbumAndDuration
|
||||
? durationMs
|
||||
: null,
|
||||
Album =
|
||||
matchMode == MusicSearchMatchMode.TitleArtistAlbumAndDuration
|
||||
? album
|
||||
: null,
|
||||
AlbumArtists = [artist],
|
||||
Artists = [artist],
|
||||
Title = title,
|
||||
}
|
||||
)
|
||||
) as Lyricify.Lyrics.Searchers.KugouSearchResult
|
||||
)?.Hash;
|
||||
if (queryHash != null)
|
||||
{
|
||||
var candidate = (
|
||||
await Lyricify.Lyrics.Helpers.ProviderHelper.KugouApi.GetSearchLyrics(
|
||||
hash: queryHash
|
||||
)
|
||||
)?.Candidates.FirstOrDefault();
|
||||
if (candidate != null)
|
||||
{
|
||||
return await Lyricify.Lyrics.Decrypter.Krc.Helper.GetLyricsAsync(
|
||||
candidate.Id,
|
||||
candidate.AccessKey
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<string?> SearchNeteaseAsync(
|
||||
string title,
|
||||
string artist,
|
||||
string album,
|
||||
int durationMs,
|
||||
MusicSearchMatchMode matchMode
|
||||
)
|
||||
{
|
||||
string? queryId = (
|
||||
(
|
||||
await new Lyricify.Lyrics.Searchers.NeteaseSearcher().SearchForResult(
|
||||
new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
|
||||
{
|
||||
DurationMs =
|
||||
matchMode == MusicSearchMatchMode.TitleArtistAlbumAndDuration
|
||||
? durationMs
|
||||
: null,
|
||||
Album =
|
||||
matchMode == MusicSearchMatchMode.TitleArtistAlbumAndDuration
|
||||
? album
|
||||
: null,
|
||||
AlbumArtists = [artist],
|
||||
Artists = [artist],
|
||||
Title = title,
|
||||
}
|
||||
)
|
||||
) as Lyricify.Lyrics.Searchers.NeteaseSearchResult
|
||||
)?.Id;
|
||||
if (queryId != null)
|
||||
{
|
||||
return (await Lyricify.Lyrics.Helpers.ProviderHelper.NeteaseApi.GetLyric(queryId))
|
||||
?.Lrc
|
||||
.Lyric;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 本地检索 amll-ttml-db 索引并下载歌词内容
|
||||
/// </summary>
|
||||
|
||||
@@ -294,6 +294,9 @@
|
||||
<data name="SettingsPageLyricsSearchProvidersConfig.Header" xml:space="preserve">
|
||||
<value>Configure lyrics search providers</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsSearchProvidersConfig.Description" xml:space="preserve">
|
||||
<value>Drag to sort, the lyrics search order will be in the following order</value>
|
||||
</data>
|
||||
<data name="SettingsPageAddFolderButton.Content" xml:space="preserve">
|
||||
<value>Add</value>
|
||||
</data>
|
||||
@@ -315,8 +318,11 @@
|
||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||
<value>Play using system player</value>
|
||||
</data>
|
||||
<data name="SettingsPageLog.Header" xml:space="preserve">
|
||||
<value>Log</value>
|
||||
<data name="SettingsPageCache.Header" xml:space="preserve">
|
||||
<value>Cache</value>
|
||||
</data>
|
||||
<data name="SettingsPageCache.Description" xml:space="preserve">
|
||||
<value>Including log files, network lyrics cache</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColor.Header" xml:space="preserve">
|
||||
<value>Font color</value>
|
||||
@@ -492,4 +498,16 @@
|
||||
<data name="LyricsSearchProviderAmllTtmlDb" xml:space="preserve">
|
||||
<value>amll-ttml-db</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderQQ" xml:space="preserve">
|
||||
<value>QQ</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderNetease" xml:space="preserve">
|
||||
<value>Netease</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderKugou" xml:space="preserve">
|
||||
<value>Kugou</value>
|
||||
</data>
|
||||
<data name="SettingsPageDebugOverlay.Header" xml:space="preserve">
|
||||
<value>Show debug overlay</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -294,6 +294,9 @@
|
||||
<data name="SettingsPageLyricsSearchProvidersConfig.Header" xml:space="preserve">
|
||||
<value>歌詞検索プロバイダーを構成します</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsSearchProvidersConfig.Description" xml:space="preserve">
|
||||
<value>ドラッグしてソートすると、歌詞の検索注文は次の順序で行われます</value>
|
||||
</data>
|
||||
<data name="SettingsPageAddFolderButton.Content" xml:space="preserve">
|
||||
<value>追加</value>
|
||||
</data>
|
||||
@@ -315,8 +318,11 @@
|
||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||
<value>システムプレーヤーを使用して再生します</value>
|
||||
</data>
|
||||
<data name="SettingsPageLog.Header" xml:space="preserve">
|
||||
<value>ログ</value>
|
||||
<data name="SettingsPageCache.Header" xml:space="preserve">
|
||||
<value>キャッシュ</value>
|
||||
</data>
|
||||
<data name="SettingsPageCache.Description" xml:space="preserve">
|
||||
<value>ログファイル、ネットワーク歌詞キャッシュを含む</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColor.Header" xml:space="preserve">
|
||||
<value>フォントカラー</value>
|
||||
@@ -412,7 +418,7 @@
|
||||
<value>ドックモード</value>
|
||||
</data>
|
||||
<data name="HostWindowDesktopFlyoutItem.Text" xml:space="preserve">
|
||||
<value />
|
||||
<value>デスクトップモード</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontWeight.Header" xml:space="preserve">
|
||||
<value>フォント重量</value>
|
||||
@@ -492,4 +498,16 @@
|
||||
<data name="LyricsSearchProviderAmllTtmlDb" xml:space="preserve">
|
||||
<value>amll-ttml-db</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderQQ" xml:space="preserve">
|
||||
<value>QQ</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderNetease" xml:space="preserve">
|
||||
<value>Netease</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderKugou" xml:space="preserve">
|
||||
<value>Kugou</value>
|
||||
</data>
|
||||
<data name="SettingsPageDebugOverlay.Header" xml:space="preserve">
|
||||
<value>デバッグオーバーレイを表示します</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -294,6 +294,9 @@
|
||||
<data name="SettingsPageLyricsSearchProvidersConfig.Header" xml:space="preserve">
|
||||
<value>가사 검색 제공 업체를 구성하십시오</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsSearchProvidersConfig.Description" xml:space="preserve">
|
||||
<value>정렬하기 위해 드래그하면 가사 검색 순서는 다음 순서로됩니다.</value>
|
||||
</data>
|
||||
<data name="SettingsPageAddFolderButton.Content" xml:space="preserve">
|
||||
<value>추가하다</value>
|
||||
</data>
|
||||
@@ -315,8 +318,11 @@
|
||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||
<value>시스템 플레이어를 사용하여 재생하십시오</value>
|
||||
</data>
|
||||
<data name="SettingsPageLog.Header" xml:space="preserve">
|
||||
<value>통나무</value>
|
||||
<data name="SettingsPageCache.Header" xml:space="preserve">
|
||||
<value>은닉처</value>
|
||||
</data>
|
||||
<data name="SettingsPageCache.Description" xml:space="preserve">
|
||||
<value>로그 파일, 네트워크 가사 캐시 포함</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColor.Header" xml:space="preserve">
|
||||
<value>글꼴 색상</value>
|
||||
@@ -412,7 +418,7 @@
|
||||
<value>도크 모드</value>
|
||||
</data>
|
||||
<data name="HostWindowDesktopFlyoutItem.Text" xml:space="preserve">
|
||||
<value />
|
||||
<value>데스크탑 모드</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontWeight.Header" xml:space="preserve">
|
||||
<value>글꼴 무게</value>
|
||||
@@ -492,4 +498,16 @@
|
||||
<data name="LyricsSearchProviderAmllTtmlDb" xml:space="preserve">
|
||||
<value>amll-ttml-db</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderQQ" xml:space="preserve">
|
||||
<value>QQ</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderNetease" xml:space="preserve">
|
||||
<value>Netease</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderKugou" xml:space="preserve">
|
||||
<value>Kugou</value>
|
||||
</data>
|
||||
<data name="SettingsPageDebugOverlay.Header" xml:space="preserve">
|
||||
<value>디버그 오버레이를 표시하십시오</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -294,6 +294,9 @@
|
||||
<data name="SettingsPageLyricsSearchProvidersConfig.Header" xml:space="preserve">
|
||||
<value>配置歌词搜索服务</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsSearchProvidersConfig.Description" xml:space="preserve">
|
||||
<value>拖动排序,歌词搜索顺序将按以下顺序</value>
|
||||
</data>
|
||||
<data name="SettingsPageAddFolderButton.Content" xml:space="preserve">
|
||||
<value>添加</value>
|
||||
</data>
|
||||
@@ -315,8 +318,11 @@
|
||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||
<value>使用系统播放器播放</value>
|
||||
</data>
|
||||
<data name="SettingsPageLog.Header" xml:space="preserve">
|
||||
<value>日志</value>
|
||||
<data name="SettingsPageCache.Header" xml:space="preserve">
|
||||
<value>缓存</value>
|
||||
</data>
|
||||
<data name="SettingsPageCache.Description" xml:space="preserve">
|
||||
<value>包括日志文件,网络歌词缓存</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColor.Header" xml:space="preserve">
|
||||
<value>字体颜色</value>
|
||||
@@ -492,4 +498,16 @@
|
||||
<data name="LyricsSearchProviderAmllTtmlDb" xml:space="preserve">
|
||||
<value>amll-ttml-db</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderQQ" xml:space="preserve">
|
||||
<value>QQ</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderNetease" xml:space="preserve">
|
||||
<value>Netease</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderKugou" xml:space="preserve">
|
||||
<value>Kugou</value>
|
||||
</data>
|
||||
<data name="SettingsPageDebugOverlay.Header" xml:space="preserve">
|
||||
<value>显示调试覆盖层</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -294,6 +294,9 @@
|
||||
<data name="SettingsPageLyricsSearchProvidersConfig.Header" xml:space="preserve">
|
||||
<value>配置歌詞搜尋服務</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsSearchProvidersConfig.Description" xml:space="preserve">
|
||||
<value>拖動排序,歌詞搜索順序將按以下順序</value>
|
||||
</data>
|
||||
<data name="SettingsPageAddFolderButton.Content" xml:space="preserve">
|
||||
<value>添加</value>
|
||||
</data>
|
||||
@@ -315,8 +318,11 @@
|
||||
<data name="SettingsPagePlayingMockMusicButton.Content" xml:space="preserve">
|
||||
<value>使用系統播放器播放</value>
|
||||
</data>
|
||||
<data name="SettingsPageLog.Header" xml:space="preserve">
|
||||
<value>紀錄</value>
|
||||
<data name="SettingsPageCache.Header" xml:space="preserve">
|
||||
<value>快取</value>
|
||||
</data>
|
||||
<data name="SettingsPageCache.Description" xml:space="preserve">
|
||||
<value>包括日誌文件,網絡歌詞緩存</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontColor.Header" xml:space="preserve">
|
||||
<value>字體顏色</value>
|
||||
@@ -412,7 +418,7 @@
|
||||
<value>停靠模式</value>
|
||||
</data>
|
||||
<data name="HostWindowDesktopFlyoutItem.Text" xml:space="preserve">
|
||||
<value />
|
||||
<value>桌面模式</value>
|
||||
</data>
|
||||
<data name="SettingsPageLyricsFontWeight.Header" xml:space="preserve">
|
||||
<value>字體粗細</value>
|
||||
@@ -492,4 +498,16 @@
|
||||
<data name="LyricsSearchProviderAmllTtmlDb" xml:space="preserve">
|
||||
<value>amll-ttml-db</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderQQ" xml:space="preserve">
|
||||
<value>QQ</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderNetease" xml:space="preserve">
|
||||
<value>Netease</value>
|
||||
</data>
|
||||
<data name="LyricsSearchProviderKugou" xml:space="preserve">
|
||||
<value>Kugou</value>
|
||||
</data>
|
||||
<data name="SettingsPageDebugOverlay.Header" xml:space="preserve">
|
||||
<value>顯示調試覆蓋層</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -130,7 +130,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial double LimitedLineWidth { get; set; } = 0.0;
|
||||
public partial double MaxLyricsWidth { get; set; } = 0.0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsFontSize
|
||||
|
||||
@@ -43,9 +43,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_rotateAngle %= MathF.PI * 2;
|
||||
}
|
||||
|
||||
if (_limitedLineWidthTransition.IsTransitioning)
|
||||
if (_maxLyricsWidthTransition.IsTransitioning)
|
||||
{
|
||||
_limitedLineWidthTransition.Update(ElapsedTime);
|
||||
_maxLyricsWidthTransition.Update(ElapsedTime);
|
||||
_isRelayoutNeeded = true;
|
||||
}
|
||||
|
||||
@@ -53,9 +53,13 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
ReLayout(control);
|
||||
_isRelayoutNeeded = false;
|
||||
UpdateCanvasYScrollOffset(control, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateCanvasYScrollOffset(control, true);
|
||||
}
|
||||
|
||||
UpdateCanvasYScrollOffset(control);
|
||||
UpdateLinesProps();
|
||||
}
|
||||
|
||||
@@ -63,7 +67,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// The UpdateCanvasYScrollOffset
|
||||
/// </summary>
|
||||
/// <param name="control">The control<see cref="ICanvasAnimatedControl"/></param>
|
||||
private void UpdateCanvasYScrollOffset(ICanvasAnimatedControl control)
|
||||
private void UpdateCanvasYScrollOffset(ICanvasAnimatedControl control, bool withAnimation)
|
||||
{
|
||||
var currentPlayingLineIndex = GetCurrentPlayingLineIndex();
|
||||
|
||||
@@ -93,10 +97,14 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
- playingTextLayout.LayoutBounds.Height / 2
|
||||
) ?? 0f;
|
||||
|
||||
if (!_canvasYScrollTransition.IsTransitioning)
|
||||
if (withAnimation && !_canvasYScrollTransition.IsTransitioning)
|
||||
{
|
||||
_canvasYScrollTransition.StartTransition(targetYScrollOffset);
|
||||
}
|
||||
else if (!withAnimation)
|
||||
{
|
||||
_canvasYScrollTransition.JumpTo(targetYScrollOffset);
|
||||
}
|
||||
|
||||
if (_canvasYScrollTransition.IsTransitioning)
|
||||
{
|
||||
@@ -298,7 +306,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
control,
|
||||
line.Text,
|
||||
_textFormat,
|
||||
(float)_limitedLineWidthTransition.Value,
|
||||
(float)_maxLyricsWidthTransition.Value,
|
||||
(float)control.Size.Height
|
||||
);
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
partial void OnLyricsFontWeightChanged(LyricsFontWeight value)
|
||||
{
|
||||
_textFormat.FontWeight = value.ToFontWeight();
|
||||
_isRelayoutNeeded = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -128,6 +129,10 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
IsCoverOverlayEnabled = message.NewValue;
|
||||
}
|
||||
else if (message.PropertyName == nameof(SettingsViewModel.IsDebugOverlayEnabled))
|
||||
{
|
||||
_isDebugOverlayEnabled = message.NewValue;
|
||||
}
|
||||
}
|
||||
else if (message.Sender is LyricsSettingsControlViewModel)
|
||||
{
|
||||
@@ -171,9 +176,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
if (message.Sender is LyricsPageViewModel)
|
||||
{
|
||||
if (message.PropertyName == nameof(LyricsPageViewModel.LimitedLineWidth))
|
||||
if (message.PropertyName == nameof(LyricsPageViewModel.MaxLyricsWidth))
|
||||
{
|
||||
_limitedLineWidthTransition.StartTransition((float)message.NewValue);
|
||||
_maxLyricsWidthTransition.StartTransition((float)message.NewValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,14 +101,18 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
out int charLength,
|
||||
out float charProgress
|
||||
);
|
||||
//ds.DrawText(
|
||||
// $"DEBUG: "
|
||||
// + $"播放行 {currentPlayingLineIndex}, 字符 {charStartIndex}, 长度 {charLength}, 进度 {charProgress}\n"
|
||||
// + $"可见行 [{_startVisibleLineIndex}, {_endVisibleLineIndex}]"
|
||||
// + $"当前时刻 {TotalTime}",
|
||||
// new Vector2(10, 10),
|
||||
// Colors.Red
|
||||
//);
|
||||
|
||||
if (_isDebugOverlayEnabled)
|
||||
{
|
||||
ds.DrawText(
|
||||
$"DEBUG: "
|
||||
+ $"播放行 {currentPlayingLineIndex}, 字符 {charStartIndex}, 长度 {charLength}, 进度 {charProgress}\n"
|
||||
+ $"可见行 [{_startVisibleLineIndex}, {_endVisibleLineIndex}]\n"
|
||||
+ $"当前时刻 {TotalTime}",
|
||||
new Vector2(10, 10),
|
||||
Colors.Red
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,18 +322,18 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
break;
|
||||
case LyricsAlignmentType.Center:
|
||||
textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Center;
|
||||
centerX += (float)_limitedLineWidthTransition.Value / 2;
|
||||
centerX += (float)_maxLyricsWidthTransition.Value / 2;
|
||||
break;
|
||||
case LyricsAlignmentType.Right:
|
||||
textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Right;
|
||||
centerX += (float)_limitedLineWidthTransition.Value;
|
||||
centerX += (float)_maxLyricsWidthTransition.Value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
float offsetToLeft =
|
||||
(float)control.Size.Width - _rightMargin - _limitedLineWidthTransition.Value;
|
||||
(float)control.Size.Width - _rightMargin - _maxLyricsWidthTransition.Value;
|
||||
|
||||
// Scale
|
||||
ds.Transform =
|
||||
|
||||
@@ -2,28 +2,16 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using BetterInAppLyrics.WinUI3.ViewModels;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Events;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.Graphics.Canvas.Brushes;
|
||||
using Microsoft.Graphics.Canvas.Effects;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Shapes;
|
||||
using Windows.Foundation;
|
||||
using Windows.Graphics.Imaging;
|
||||
using Windows.UI;
|
||||
|
||||
@@ -78,6 +66,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// </summary>
|
||||
private readonly float _highlightedScale = 1.0f;
|
||||
|
||||
private bool _isDebugOverlayEnabled = false;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the _immersiveBgrTransition
|
||||
/// </summary>
|
||||
@@ -96,7 +86,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// <summary>
|
||||
/// Defines the _limitedLineWidthTransition
|
||||
/// </summary>
|
||||
private readonly ValueTransition<float> _limitedLineWidthTransition = new(
|
||||
private readonly ValueTransition<float> _maxLyricsWidthTransition = new(
|
||||
initialValue: 0f,
|
||||
durationSeconds: 0.8f,
|
||||
interpolator: (from, to, progress) => to
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Messages;
|
||||
@@ -10,13 +17,6 @@ using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.Globalization;
|
||||
using Windows.Media;
|
||||
@@ -102,6 +102,10 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[ObservableProperty]
|
||||
public partial AutoStartWindowType AutoStartWindowType { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial bool IsDebugOverlayEnabled { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the BackdropType
|
||||
/// </summary>
|
||||
@@ -360,9 +364,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// The OpenLogFolder
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void OpenLogFolder()
|
||||
private void OpenCacheFolder()
|
||||
{
|
||||
OpenFolderInFileExplorer(AppInfo.LogDirectory);
|
||||
OpenFolderInFileExplorer(AppInfo.CacheFolder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -93,45 +93,52 @@
|
||||
Grid.Row="1"
|
||||
SizeChanged="CoverArea_SizeChanged">
|
||||
|
||||
<Grid
|
||||
x:Name="CoverImageGrid"
|
||||
CornerRadius="{x:Bind ViewModel.CoverImageGridCornerRadius, Mode=OneWay}"
|
||||
SizeChanged="CoverImageGrid_SizeChanged">
|
||||
<Image
|
||||
x:Name="CoverImage"
|
||||
Source="{x:Bind ViewModel.CoverImage, Mode=OneWay}"
|
||||
Stretch="Uniform">
|
||||
<Image.Resources>
|
||||
<Storyboard x:Key="CoverIamgeFadeInStoryboard">
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="CoverImage" Storyboard.TargetProperty="Opacity">
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<Storyboard x:Key="CoverIamgeFadeOutStoryboard">
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="CoverImage" Storyboard.TargetProperty="Opacity">
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</Image.Resources>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.AboutToUpdateUI, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="True">
|
||||
<interactivity:ControlStoryboardAction Storyboard="{StaticResource CoverIamgeFadeOutStoryboard}" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.AboutToUpdateUI, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="False">
|
||||
<interactivity:ControlStoryboardAction Storyboard="{StaticResource CoverIamgeFadeInStoryboard}" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</Image>
|
||||
<Grid x:Name="CoverImageGrid" SizeChanged="CoverImageGrid_SizeChanged">
|
||||
<Grid CornerRadius="{x:Bind ViewModel.CoverImageGridCornerRadius, Mode=OneWay}">
|
||||
<Image
|
||||
x:Name="CoverImage"
|
||||
Source="{x:Bind ViewModel.CoverImage, Mode=OneWay}"
|
||||
Stretch="Uniform">
|
||||
<Image.Resources>
|
||||
<Storyboard x:Key="CoverIamgeFadeInStoryboard">
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="CoverImage" Storyboard.TargetProperty="Opacity">
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<Storyboard x:Key="CoverIamgeFadeOutStoryboard">
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="CoverImage" Storyboard.TargetProperty="Opacity">
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</Image.Resources>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.AboutToUpdateUI, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="True">
|
||||
<interactivity:ControlStoryboardAction Storyboard="{StaticResource CoverIamgeFadeOutStoryboard}" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.AboutToUpdateUI, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="False">
|
||||
<interactivity:ControlStoryboardAction Storyboard="{StaticResource CoverIamgeFadeInStoryboard}" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</Image>
|
||||
</Grid>
|
||||
<ui:Effects.Shadow>
|
||||
<media:AttachedCardShadow
|
||||
BlurRadius="32"
|
||||
CornerRadius="{x:Bind ViewModel.CoverImageGridCornerRadius, Mode=OneWay, Converter={StaticResource CornerRadiusToDoubleConverter}}"
|
||||
InnerContentClipMode="CompositionMaskBrush"
|
||||
Opacity="0.5" />
|
||||
</ui:Effects.Shadow>
|
||||
</Grid>
|
||||
|
||||
|
||||
</Grid>
|
||||
|
||||
<!-- Title and artist -->
|
||||
@@ -179,7 +186,7 @@
|
||||
x:Name="TitleTextBlock"
|
||||
Behavior="Bouncing"
|
||||
FontSize="{StaticResource TitleTextBlockFontSize}"
|
||||
FontWeight="SemiBold"
|
||||
FontWeight="Bold"
|
||||
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
|
||||
Text="{x:Bind ViewModel.SongInfo.Title, Mode=OneWay}" />
|
||||
</controls:OpacityMaskView>
|
||||
@@ -222,7 +229,6 @@
|
||||
<labs:MarqueeText
|
||||
Behavior="Bouncing"
|
||||
FontSize="{StaticResource SubtitleTextBlockFontSize}"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
|
||||
Opacity="0.5"
|
||||
Text="{x:Bind ViewModel.SongInfo.Artist, Mode=OneWay}" />
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
@@ -102,7 +102,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
/// <param name="e">The e<see cref="SizeChangedEventArgs"/></param>
|
||||
private void LyricsPlaceholderGrid_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
ViewModel.LimitedLineWidth = e.NewSize.Width;
|
||||
ViewModel.MaxLyricsWidth = e.NewSize.Width;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -481,8 +481,11 @@
|
||||
<controls:SettingsCard x:Uid="SettingsPageMockMusicPlaying">
|
||||
<Button x:Uid="SettingsPagePlayingMockMusicButton" Command="{x:Bind ViewModel.PlayTestingMusicTaskCommand}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageLog">
|
||||
<Button x:Uid="SettingsPageOpenLogFolderButton" Command="{x:Bind ViewModel.OpenLogFolderCommand}" />
|
||||
<controls:SettingsCard x:Uid="SettingsPageCache">
|
||||
<Button x:Uid="SettingsPageOpenLogFolderButton" Command="{x:Bind ViewModel.OpenCacheFolderCommand}" />
|
||||
</controls:SettingsCard>
|
||||
<controls:SettingsCard x:Uid="SettingsPageDebugOverlay">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.IsDebugOverlayEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</StackPanel>
|
||||
</controls:Case>
|
||||
|
||||
Reference in New Issue
Block a user