diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
index 15b0eb3..2d896a4 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
@@ -12,7 +12,7 @@
+ Version="0.0.12.0" />
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
index 1f411d7..68a3aa4 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
@@ -82,7 +82,7 @@
-
+
+
@@ -100,7 +106,7 @@
- Segoe Fluent Icons, Segoe MDL2 Assets
+ ms-appx:///Assets/Segoe Fluent Icons.ttf#Segoe Fluent Icons
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Segoe Fluent Icons.ttf b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Segoe Fluent Icons.ttf
new file mode 100644
index 0000000..8f05a4b
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Segoe Fluent Icons.ttf differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj
index af27b0e..f3c1d0a 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj
@@ -20,6 +20,7 @@
+
@@ -30,6 +31,7 @@
+
@@ -80,6 +82,11 @@
+
+
+ Always
+
+
MSBuild:Compile
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs
index 2a22ccc..f7994ea 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs
@@ -1,5 +1,14 @@
// 2025/6/23 by Zhe Fang
+using CommunityToolkit.WinUI.Helpers;
+using Microsoft.Graphics.Canvas;
+using Microsoft.Graphics.Canvas.Text;
+using Microsoft.UI;
+using Microsoft.UI.Xaml.Media.Imaging;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.Formats.Png;
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.IO;
@@ -7,10 +16,6 @@ using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
-using Microsoft.Graphics.Canvas;
-using Microsoft.Graphics.Canvas.Text;
-using Microsoft.UI;
-using Microsoft.UI.Xaml.Media.Imaging;
using Windows.Graphics.Imaging;
using Windows.Storage.Streams;
using Windows.UI;
@@ -30,62 +35,33 @@ namespace BetterLyrics.WinUI3.Helper
return stream;
}
- public static async Task CreateTextPlaceholderBytesAsync(string text, int width, int height)
+ public static async Task CreateTextPlaceholderBytesAsync(int width, int height)
{
var device = CanvasDevice.GetSharedDevice();
var renderTarget = new CanvasRenderTarget(device, width, height, 96);
- // 居中绘制文字
+ // 随机生成渐变色
+ Windows.UI.Color RandomColor()
+ {
+ var rand = new Random(Guid.NewGuid().GetHashCode());
+ double h = rand.NextDouble() * 360;
+ double s = 0.35 + rand.NextDouble() * 0.3; // 0.35~0.65,适中饱和度
+ double l = 0.5 + rand.NextDouble() * 0.3; // 0.5~0.8,明亮
+ return HslToColor(h, s, l);
+ }
+
+ Windows.UI.Color color1 = RandomColor();
+ Windows.UI.Color color2 = RandomColor();
+
using (var ds = renderTarget.CreateDrawingSession())
{
- // 背景色
- ds.Clear(Colors.LightGray);
-
- // 文字格式
- var format = new CanvasTextFormat
+ // 绘制线性渐变背景
+ var gradientBrush = new Microsoft.Graphics.Canvas.Brushes.CanvasLinearGradientBrush(ds, color1, color2)
{
- FontSize = Math.Min(width, height) / 6f,
- FontWeight = Microsoft.UI.Text.FontWeights.SemiBold,
- HorizontalAlignment = CanvasHorizontalAlignment.Center,
- VerticalAlignment = CanvasVerticalAlignment.Center,
- WordWrapping = CanvasWordWrapping.Wrap,
- TrimmingGranularity = CanvasTextTrimmingGranularity.Character,
- Options = CanvasDrawTextOptions.Default,
+ StartPoint = new System.Numerics.Vector2(0, 0),
+ EndPoint = new System.Numerics.Vector2(width, height)
};
-
- // 设定边距
- float margin = Math.Min(width, height) / 12f;
- float availableWidth = width - 2 * margin;
- float availableHeight = height - 2 * margin;
-
- // 计算合适的字体大小以适应内容区域
- float fontSize = format.FontSize;
- float minFontSize = 8f;
- float maxFontSize = format.FontSize;
- CanvasTextLayout layout;
- do
- {
- format.FontSize = fontSize;
- layout = new CanvasTextLayout(
- ds,
- text,
- format,
- availableWidth,
- availableHeight
- );
- if (
- layout.LayoutBounds.Width <= availableWidth
- && layout.LayoutBounds.Height <= availableHeight
- )
- break;
- fontSize -= 1f;
- } while (fontSize >= minFontSize);
-
- // 居中绘制文字(在内容区域内居中)
- var bounds = layout.LayoutBounds;
- var x = margin + (availableWidth - (float)bounds.Width) / 2f - (float)bounds.X;
- var y = margin + (availableHeight - (float)bounds.Height) / 2f - (float)bounds.Y;
- ds.DrawTextLayout(layout, new Vector2(x, y), Colors.DarkGray);
+ ds.FillRectangle(0, 0, width, height, gradientBrush);
}
// 保存为 PNG 并转为 byte[]
@@ -100,9 +76,34 @@ namespace BetterLyrics.WinUI3.Helper
}
return buffer;
}
+
+ // HSL转Color
+ static Windows.UI.Color HslToColor(double h, double s, double l)
+ {
+ h = h / 360.0;
+ double r = l, g = l, b = l;
+ if (s != 0)
+ {
+ double q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ double p = 2 * l - q;
+ r = HueToRgb(p, q, h + 1.0 / 3.0);
+ g = HueToRgb(p, q, h);
+ b = HueToRgb(p, q, h - 1.0 / 3.0);
+ }
+ return Windows.UI.Color.FromArgb(255, (byte)(r * 255), (byte)(g * 255), (byte)(b * 255));
+ }
+ static double HueToRgb(double p, double q, double t)
+ {
+ if (t < 0) t += 1;
+ if (t > 1) t -= 1;
+ if (t < 1.0 / 6.0) return p + (q - p) * 6 * t;
+ if (t < 1.0 / 2.0) return q;
+ if (t < 2.0 / 3.0) return p + (q - p) * (2.0 / 3.0 - t) * 6;
+ return p;
+ }
}
- public static List GetAccentColorsFromByte(byte[] bytes)
+ public static List GetAccentColorsFromByte(byte[] bytes)
{
// 使用 ImageSharp 读取图片
using var image = SixLabors.ImageSharp.Image.Load(bytes);
@@ -137,7 +138,6 @@ namespace BetterLyrics.WinUI3.Helper
.ToList();
}
-
//public static async Task GetBitmapImageFromBytesAsync(byte[] imageBytes)
//{
// var stream = new InMemoryRandomAccessStream();
@@ -188,5 +188,35 @@ namespace BetterLyrics.WinUI3.Helper
}
return (float)(sum / (pixels.Length / 4));
}
+
+ public static byte[] MakeSquareWithThemeColor(byte[] imageBytes)
+ {
+ using var image = Image.Load(imageBytes);
+
+ if (image.Width == image.Height)
+ {
+ // 已经是正方形,直接返回
+ return imageBytes;
+ }
+
+ int size = Math.Max(image.Width, image.Height);
+
+ var themeColor = Rgba32.ParseHex(GetAccentColorsFromByte(imageBytes).FirstOrDefault().ToHex());
+
+ // 新建正方形画布
+ using var square = new Image(size, size, themeColor);
+
+ // 计算居中位置
+ int offsetX = (size - image.Width) / 2;
+ int offsetY = (size - image.Height) / 2;
+
+ // 绘制原图到正方形画布
+ square.Mutate(ctx => ctx.DrawImage(image, new Point(offsetX, offsetY), 1f));
+
+ // 保存为 PNG 字节流
+ using var ms = new MemoryStream();
+ square.Save(ms, new PngEncoder());
+ return ms.ToArray();
+ }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs
index 11c0a7c..5ea75d8 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs
@@ -98,16 +98,19 @@ namespace BetterLyrics.WinUI3.Services
};
}
- public static string DetectCountryCode(string? text)
+ public static string ConvertToCountryCode(string? languageCode)
{
- if (text == null) return "en";
- var code = DetectLanguageCode(text);
- if (code == null) return "en";
- // 处理中文简体和繁体
- if (code == "zh-Hans") return "cn";
- if (code == "zh-Hant") return "cn";
- // 其他语言直接返回两字母代码
- return code;
+ if (languageCode == null) return "us";
+
+ return languageCode switch
+ {
+ "zh" => "cn",
+ "zh-Hans" => "cn",
+ "zh-Hant" => "tw",
+ "ja" => "jp",
+ "ko" => "kr",
+ _ => "us"
+ };
}
public static string GetUserTargetLanguageCode()
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/NetHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/NetHelper.cs
new file mode 100644
index 0000000..8a68874
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/NetHelper.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Helper
+{
+ public class NetHelper
+ {
+ public static async Task CheckConnectivity(string url)
+ {
+ try
+ {
+ using var client = new System.Net.Http.HttpClient();
+ // Try to reach a reliable endpoint
+ var res = await client.GetAsync(url);
+ return res.IsSuccessStatusCode;
+ }
+ catch
+ {
+ return false; // If any exception occurs, assume no connectivity
+ }
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService.cs
index 2b26dbb..9aedf97 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService.cs
@@ -7,8 +7,10 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net;
using System.Net.Http;
using System.Text;
+using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks;
@@ -48,7 +50,11 @@ namespace BetterLyrics.WinUI3.Services
result = bytesFromSMTC;
break;
case AlbumArtSearchProvider.iTunes:
- result = await SearchiTunesAsync(artist, album);
+ foreach (string countryCode in new List() { "us", "cn", "jp", "kr" })
+ {
+ result = await SearchiTunesAsync(artist, album, title, countryCode);
+ if (result != null) break;
+ }
break;
default:
break;
@@ -82,7 +88,7 @@ namespace BetterLyrics.WinUI3.Services
return null;
}
- private async Task SearchiTunesAsync(string artist, string album)
+ private async Task SearchiTunesAsync(string artist, string album, string title, string countryCode)
{
// Source: https://gist.github.com/mcworkaholic/82fbf203e3f1043bbe534b5b2974c0ce
try
@@ -96,10 +102,9 @@ namespace BetterLyrics.WinUI3.Services
}
// Build the iTunes API URL
- string url = $"https://itunes.apple.com/search?term=" + artist + "+" + album + "&country=" + LanguageHelper.DetectCountryCode(album + artist) + "&entity=album";
- url.Replace(" ", "-");
- // Make a request to the API
+ string url = $"https://itunes.apple.com/search?term=" + WebUtility.UrlEncode($"{artist} {album}").Replace("%20", "+") + "&country=" + countryCode + "&entity=album&media=music&limit=1";
+ // Make a request to the API
HttpResponseMessage response = await _iTunesHttpClinet.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
@@ -118,6 +123,7 @@ namespace BetterLyrics.WinUI3.Services
if (fetched != null && fetched.Length > 0)
{
+ fetched = ImageHelper.MakeSquareWithThemeColor(fetched);
// Write to cache
FileHelper.WriteAlbumArtCache(artist, album, fetched, format, PathHelper.iTunesAlbumArtCacheDirectory);
return fetched;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ISettingsService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ISettingsService.cs
index c61230d..4f9ba23 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ISettingsService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ISettingsService.cs
@@ -3,10 +3,8 @@
using System.Collections.Generic;
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Models;
-using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Windows.UI;
-using Windows.UI.Text;
namespace BetterLyrics.WinUI3.Services
{
@@ -92,5 +90,7 @@ namespace BetterLyrics.WinUI3.Services
int TimelineSyncThreshold { get; set; }
int LockHotKeyIndex { get; set; }
+ bool IsImmersiveMode { get; set; }
+ string LXMusicServer { get; set; }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs
index 2ef4bff..5c5b604 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs
@@ -7,6 +7,7 @@ using BetterLyrics.WinUI3.ViewModels;
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
+using EvtSource;
using Microsoft.Extensions.Logging;
using Microsoft.UI.Dispatching;
using System;
@@ -14,6 +15,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
+using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
@@ -29,14 +31,20 @@ namespace BetterLyrics.WinUI3.Services
{
private readonly IAlbumArtSearchService _albumArtSearchService;
private readonly ILogger _logger;
+
+ private readonly string _lxMusicId = "cn.toside.music.desktop";
+
+ private EventSourceReader? _sse = null;
+
private readonly MediaManager _mediaManager = new();
+
private readonly LatestOnlyTaskRunner _AlbumArtRefreshRunner = new();
private readonly LatestOnlyTaskRunner _OnAnyMediaPropertyChangedRunner = new();
private SongInfo? _cachedSongInfo;
private List _mediaSourceProvidersInfo;
private byte[]? _SMTCAlbumArtBytes = null;
- private AlbumArtChangedEventArgs _albumArtChangedEventArgs = new AlbumArtChangedEventArgs();
+ private AlbumArtChangedEventArgs _albumArtChangedEventArgs = new();
public event EventHandler? IsPlayingChanged;
public event EventHandler? PositionChanged;
@@ -140,6 +148,15 @@ namespace BetterLyrics.WinUI3.Services
token.ThrowIfCancellationRequested();
+ if (id == _lxMusicId)
+ {
+ StartSSE();
+ }
+ else
+ {
+ StopSSE();
+ }
+
_cachedSongInfo = new SongInfo
{
Title = mediaProperties.Title,
@@ -232,7 +249,7 @@ namespace BetterLyrics.WinUI3.Services
if (bytes == null)
{
- bytes = await ImageHelper.CreateTextPlaceholderBytesAsync($"{_cachedSongInfo!.Artist} - {_cachedSongInfo.Title}", 400, 400);
+ bytes = await ImageHelper.CreateTextPlaceholderBytesAsync(400, 400);
token.ThrowIfCancellationRequested();
}
@@ -255,6 +272,46 @@ namespace BetterLyrics.WinUI3.Services
});
}
+ private void StartSSE()
+ {
+ _sse = new EventSourceReader(new Uri($"{_settingsService.LXMusicServer}/subscribe-player-status?filter=progress")).Start();
+ _sse.MessageReceived += Sse_MessageReceived;
+ _sse.Disconnected += Sse_Disconnected;
+ }
+
+ private void StopSSE()
+ {
+ if (_sse != null)
+ {
+ _sse.MessageReceived -= Sse_MessageReceived;
+ _sse.Disconnected -= Sse_Disconnected;
+ _sse.Dispose();
+ _sse = null;
+ }
+ }
+
+ private void Sse_Disconnected(object sender, DisconnectEventArgs e)
+ {
+ Task.Run(async () =>
+ {
+ await Task.Delay(e.ReconnectDelay);
+ if (_sse != null && !_sse.IsDisposed) _sse.Start();
+ });
+ }
+
+ private void Sse_MessageReceived(object sender, EventSourceMessageEventArgs e)
+ {
+ var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement);
+
+ if (data.TryGetDouble(out double positionSeconds))
+ {
+ if (_cachedSongInfo?.SourceAppUserModelId == _lxMusicId)
+ {
+ PositionChanged?.Invoke(this, new PositionChangedEventArgs(TimeSpan.FromSeconds(positionSeconds)));
+ }
+ }
+ }
+
public async Task PlayAsync()
{
var focusedSession = _mediaManager.GetFocusedSession();
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService.cs
index 0ebb81a..7e5bd2e 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService.cs
@@ -41,6 +41,7 @@ namespace BetterLyrics.WinUI3.Services
private const string StandardWindowHeightKey = "StandardWindowHeight";
private const string AutoLockOnDesktopModeKey = "AutoLockOnDesktopMode";
+ private const string IsImmersiveModeKey = "IsImmersiveMode";
private const string IsDynamicCoverOverlayEnabledKey = "IsDynamicCoverOverlayEnabled";
private const string IsFanLyricsEnabledKey = "IsFanLyricsEnabled";
@@ -74,6 +75,8 @@ namespace BetterLyrics.WinUI3.Services
private const string LibreTranslateServerKey = "LibreTranslateServer";
private const string SelectedTargetLanguageIndexKey = "SelectedTargetLanguageIndex";
+ private const string LXMusicServerKey = "LXMusicServer";
+
private const string LyricsBackgroundThemeKey = "LyricsBackgroundTheme";
private const string IgnoreFullscreenWindowKey = "IgnoreFullscreenWindow";
private const string PreferredDisplayTypeKey = "PreferredDisplayTypeKey";
@@ -160,6 +163,7 @@ namespace BetterLyrics.WinUI3.Services
SetDefault(StandardWindowWidthKey, 1600);
SetDefault(AutoLockOnDesktopModeKey, false);
+ SetDefault(IsImmersiveModeKey, false);
// App behavior
SetDefault(AutoStartWindowTypeKey, (int)AutoStartWindowType.StandardMode);
// Album art
@@ -196,6 +200,8 @@ namespace BetterLyrics.WinUI3.Services
SetDefault(IsTranslationEnabledKey, false);
SetDefault(SelectedTargetLanguageIndexKey, LanguageHelper.GetDefaultTargetLanguageIndex());
+ SetDefault(LXMusicServerKey, "");
+
SetDefault(LyricsFontStrokeWidthKey, 3);
SetDefault(IgnoreFullscreenWindowKey, false);
SetDefault(PreferredDisplayTypeKey, (int)LyricsDisplayType.SplitView);
@@ -531,6 +537,12 @@ namespace BetterLyrics.WinUI3.Services
set => SetValue(SelectedTargetLanguageIndexKey, value);
}
+ public string LXMusicServer
+ {
+ get => GetValue(LXMusicServerKey)!;
+ set => SetValue(LXMusicServerKey, value);
+ }
+
public bool IgnoreFullscreenWindow
{
get => GetValue(IgnoreFullscreenWindowKey);
@@ -561,6 +573,12 @@ namespace BetterLyrics.WinUI3.Services
set => SetValue(PositionOffsetKey, value);
}
+ public bool IsImmersiveMode
+ {
+ get => GetValue(IsImmersiveModeKey);
+ set => SetValue(IsImmersiveModeKey, value);
+ }
+
private T? GetValue(string key)
{
if (_localSettings.Values.TryGetValue(key, out object? value))
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw
index b9c1365..13d8a36 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw
@@ -603,10 +603,10 @@
Visit https://github.com/LibreTranslate/LibreTranslate for installation instructions and more information (this software is not affiliated with this translation service in any way)
-
+
Server test successful
-
+
Server test failed
@@ -741,4 +741,7 @@
Unlock and lock shortcut keys
+
+ LX Music Server
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
index c2c7208..d266f11 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
@@ -603,10 +603,10 @@
https://github.com/LibreTranslate/LibreTranslate にアクセスしてください。
-
+
サーバーテストが成功しました
-
+
サーバーテストに失敗しました
@@ -741,4 +741,7 @@
ショートカットキーのロックを解除およびロックします
+
+ LX Music Server
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
index 6815c92..6b6b07f 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
@@ -603,10 +603,10 @@
설치 지침 및 자세한 정보는 https://github.com/LibreTranslate/LibreTranslate 를 방문하십시오 (이 소프트웨어는이 번역 서비스와 제휴하지 않습니다).
-
+
서버 테스트 성공
-
+
서버 테스트가 실패했습니다
@@ -741,4 +741,7 @@
바로 가기 키를 잠금 해제하고 잠그십시오
+
+ LX 음악 서버
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
index 594253d..ec57613 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
@@ -603,10 +603,10 @@
访问 https://github.com/LibreTranslate/LibreTranslate 获取安装教程及更多信息(本软件与该翻译服务无任何联系)
-
+
服务器测试成功
-
+
服务器测试失败
@@ -741,4 +741,7 @@
解锁和锁定快捷键
+
+ LX 音乐服务器
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
index 09312e3..c755f78 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
@@ -603,10 +603,10 @@
造訪 https://github.com/LibreTranslate/LibreTranslate 以取得安裝教學及更多資訊(本軟體與此翻譯服務無任何關聯)
-
+
服務器測試成功
-
+
服務器測試失敗
@@ -741,4 +741,7 @@
解鎖和鎖定快捷鍵
+
+ LX 音樂服務器
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs
index 07ad440..722e745 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs
@@ -26,6 +26,8 @@ namespace BetterLyrics.WinUI3.ViewModels
PreferredDisplayType = _settingsService.PreferredDisplayType;
ResetPositionOffsetOnSongChanged = _settingsService.ResetPositionOffsetOnSongChanged;
PositionOffset = _settingsService.PositionOffset;
+ IsImmersiveMode = _settingsService.IsImmersiveMode;
+ OnIsImmersiveModeChanged(IsImmersiveMode);
//Volume = SystemVolumeHelper.GetMasterVolume();
//SystemVolumeHelper.VolumeChanged += SystemVolumeHelper_VolumeChanged;
@@ -58,6 +60,12 @@ namespace BetterLyrics.WinUI3.ViewModels
//[ObservableProperty]
//public partial int Volume { get; set; }
+ [ObservableProperty]
+ public partial bool IsImmersiveMode { get; set; }
+
+ [ObservableProperty]
+ public partial float BottomCommandGridOpacity { get; set; }
+
[ObservableProperty]
[NotifyPropertyChangedRecipients]
public partial LyricsDisplayType DisplayType { get; set; } = LyricsDisplayType.PlaceholderOnly;
@@ -103,6 +111,10 @@ namespace BetterLyrics.WinUI3.ViewModels
SetNonStandardModePreferredDisplayType(message.NewValue);
TrySwitchToPreferredDisplayType(SongInfo);
}
+ else if (message.PropertyName == nameof(LyricsWindowViewModel.IsImmersiveMode))
+ {
+ IsImmersiveMode = message.NewValue;
+ }
}
}
@@ -191,6 +203,18 @@ namespace BetterLyrics.WinUI3.ViewModels
_settingsService.PositionOffset = value;
}
+ partial void OnIsImmersiveModeChanged(bool value)
+ {
+ if (value)
+ {
+ BottomCommandGridOpacity = 0f;
+ }
+ else
+ {
+ BottomCommandGridOpacity = .5f;
+ }
+ }
+
//partial void OnVolumeChanged(int value)
//{
// SystemVolumeHelper.SetMasterVolume(value);
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Draw.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Draw.cs
index 054ea4d..e8af5ec 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Draw.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Draw.cs
@@ -45,7 +45,7 @@ namespace BetterLyrics.WinUI3.ViewModels
}
else if (_isDesktopMode)
{
- DrawImmersiveBackground(control, combinedDs, 12f);
+ DrawImmersiveBackground(control, combinedDs, 0f);
}
else
{
@@ -196,7 +196,7 @@ namespace BetterLyrics.WinUI3.ViewModels
BlurAmount = _albumArtBgBlurAmount,
Source = overlappedCovers,
BorderMode = EffectBorderMode.Soft,
- Optimization = EffectOptimization.Quality,
+ Optimization = EffectOptimization.Speed,
},
};
ds.DrawImage(coverOverlayEffect);
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs
index 8ff92d7..769ce38 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs
@@ -35,6 +35,8 @@ namespace BetterLyrics.WinUI3
public LyricsWindowViewModel(ISettingsService settingsService) : base(settingsService)
{
_ignoreFullscreenWindow = _settingsService.IgnoreFullscreenWindow;
+ IsImmersiveMode = _settingsService.IsImmersiveMode;
+ OnIsImmersiveModeChanged(_settingsService.IsImmersiveMode);
}
[ObservableProperty]
@@ -53,6 +55,13 @@ namespace BetterLyrics.WinUI3
[NotifyPropertyChangedRecipients]
public partial bool IsLyricsWindowLocked { get; set; } = false;
+ [ObservableProperty]
+ [NotifyPropertyChangedRecipients]
+ public partial bool IsImmersiveMode { get; set; }
+
+ [ObservableProperty]
+ public partial float TopCommandGridOpacity { get; set; }
+
[ObservableProperty]
public partial ElementTheme ThemeType { get; set; } = ElementTheme.Default;
@@ -64,7 +73,19 @@ namespace BetterLyrics.WinUI3
public partial bool IsMouseWithinWindow { get; set; } = false;
[ObservableProperty]
- public partial string LockHotKey { get; set; }
+ public partial string LockHotKey { get; set; } = "";
+
+ partial void OnIsImmersiveModeChanged(bool value)
+ {
+ if (value)
+ {
+ TopCommandGridOpacity = 0f;
+ }
+ else
+ {
+ TopCommandGridOpacity = 0.5f;
+ }
+ }
public void Receive(PropertyChangedMessage message)
{
@@ -190,11 +211,13 @@ namespace BetterLyrics.WinUI3
{
DesktopModeHelper.SetClickThrough(window, false);
IsLyricsWindowLocked = false;
+ IsImmersiveMode = _settingsService.IsImmersiveMode;
}
else
{
DesktopModeHelper.SetClickThrough(window, true);
IsLyricsWindowLocked = true;
+ IsImmersiveMode = true;
}
}
@@ -237,5 +260,11 @@ namespace BetterLyrics.WinUI3
DockModeHelper.Disable(window);
}
}
+
+ [RelayCommand]
+ private void OnImmersiveToggleButtonEnabledChanged()
+ {
+ _settingsService.IsImmersiveMode = IsImmersiveMode;
+ }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs
index c52c937..5e87d4d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs
@@ -9,6 +9,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
using ShadowViewer.Controls;
using System;
using System.Collections.Generic;
@@ -93,6 +94,8 @@ namespace BetterLyrics.WinUI3.ViewModels
ResetPositionOffsetOnSongChanged = _settingsService.ResetPositionOffsetOnSongChanged;
LockHotKeyIndex = _settingsService.LockHotKeyIndex;
+ LXMusicServer = _settingsService.LXMusicServer;
+
_playbackService.MediaSourceProvidersInfoChanged += PlaybackService_SessionIdsChanged;
Task.Run(async () =>
@@ -274,6 +277,13 @@ namespace BetterLyrics.WinUI3.ViewModels
[NotifyPropertyChangedRecipients]
public partial int TimelineSyncThreshold { get; set; }
+ [ObservableProperty]
+ public partial bool IsLXMusicServerTesting { get; set; } = false;
+
+ [ObservableProperty]
+ [NotifyPropertyChangedRecipients]
+ public partial string LXMusicServer { get; set; }
+
public void OnLyricsSearchProvidersReordered()
{
_settingsService.LyricsSearchProvidersInfo = [.. LyricsSearchProvidersInfo];
@@ -415,7 +425,7 @@ namespace BetterLyrics.WinUI3.ViewModels
string result = await _libreTranslateService.TranslateTextAsync("Hello, world!", targetLangCode, null);
_dispatcherQueue.TryEnqueue(() =>
{
- App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageLibreTranslateTestSuccessInfo"), Microsoft.UI.Xaml.Controls.InfoBarSeverity.Success);
+ App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageServerTestSuccessInfo"), Microsoft.UI.Xaml.Controls.InfoBarSeverity.Success);
IsLibreTranslateServerTesting = false;
});
}
@@ -423,13 +433,30 @@ namespace BetterLyrics.WinUI3.ViewModels
{
_dispatcherQueue.TryEnqueue(() =>
{
- App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageLibreTranslateTestFailedInfo"), Microsoft.UI.Xaml.Controls.InfoBarSeverity.Error);
+ App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader!.GetString("SettingsPageServerTestFailedInfo"), Microsoft.UI.Xaml.Controls.InfoBarSeverity.Error);
IsLibreTranslateServerTesting = false;
});
}
});
}
+ [RelayCommand]
+ private void LXMusicServerTest()
+ {
+ IsLXMusicServerTesting = true;
+ Task.Run(async () =>
+ {
+ bool testResult = await NetHelper.CheckConnectivity($"{LXMusicServer}/status");
+ _dispatcherQueue.TryEnqueue(() =>
+ {
+ App.Current.SettingsWindowNotificationPanel?.Notify(
+ App.ResourceLoader!.GetString($"SettingsPageServerTest{(testResult ? "Success" : "Failed")}Info"),
+ testResult ? InfoBarSeverity.Success : InfoBarSeverity.Error);
+ IsLXMusicServerTesting = false;
+ });
+ });
+ }
+
public async Task ToggleAutoStartupAsync(bool target)
{
StartupTask startupTask = await StartupTask.GetAsync(_autoStartupTaskId);
@@ -490,6 +517,10 @@ namespace BetterLyrics.WinUI3.ViewModels
{
_settingsService.LibreTranslateServer = value;
}
+ partial void OnLXMusicServerChanged(string value)
+ {
+ _settingsService.LXMusicServer = value;
+ }
partial void OnAutoStartWindowTypeChanged(AutoStartWindowType value)
{
_settingsService.AutoStartWindowType = value;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml
index 3637924..a4e851d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml
@@ -37,29 +37,28 @@
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
+
-
-
-
-
-
-
-
-
-
+ Style="{StaticResource CardGridStyle}">
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+ Style="{StaticResource CardGridStyle}">
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
+
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml.cs
index 2758997..3368088 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml.cs
@@ -48,12 +48,18 @@ namespace BetterLyrics.WinUI3.Views
private void BottomCommandGrid_PointerEntered(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
{
- BottomCommandGrid.Opacity = 0.5;
+ if (ViewModel.IsImmersiveMode)
+ {
+ ViewModel.BottomCommandGridOpacity = .5f;
+ }
}
private void BottomCommandGrid_PointerExited(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
{
- BottomCommandGrid.Opacity = 0;
+ if (ViewModel.IsImmersiveMode)
+ {
+ ViewModel.BottomCommandGridOpacity = 0f;
+ }
}
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml
index d5e2e20..dd66f4d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml
@@ -25,145 +25,161 @@
-
-
-
-
-
+ Style="{StaticResource CardGridStyle}">
+
+
+
+
+
+
+
+
+
-
-
-
-
+ Style="{StaticResource CardGridStyle}">
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml.cs
index 937d207..a29e5f0 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml.cs
@@ -165,6 +165,7 @@ namespace BetterLyrics.WinUI3.Views
AOTFlyoutItem.Visibility = DesktopFlyoutItem.Visibility = FullScreenFlyoutItem.Visibility = DockFlyoutItem.Visibility =
ClickThroughButton.Visibility = Visibility.Collapsed;
+ ViewModel.IsImmersiveMode = true;
break;
case AppWindowPresenterKind.FullScreen:
MinimiseButton.Visibility = MaximiseButton.Visibility = RestoreButton.Visibility =
@@ -175,7 +176,6 @@ namespace BetterLyrics.WinUI3.Views
DockFlyoutItem.Visibility =
Visibility.Collapsed;
FullScreenFlyoutItem.IsChecked = true;
-
break;
case AppWindowPresenterKind.Overlapped:
DockFlyoutItem.Visibility = Visibility.Visible;
@@ -193,6 +193,7 @@ namespace BetterLyrics.WinUI3.Views
MiniFlyoutItem.Visibility =
Visibility.Collapsed;
+ ViewModel.IsImmersiveMode = true;
}
else if (DesktopFlyoutItem.IsChecked)
{
@@ -234,6 +235,8 @@ namespace BetterLyrics.WinUI3.Views
MaximiseButton.Visibility = Visibility.Visible;
RestoreButton.Visibility = Visibility.Collapsed;
}
+
+ ViewModel.IsImmersiveMode = _settingsService.IsImmersiveMode;
}
break;
default:
@@ -272,12 +275,18 @@ namespace BetterLyrics.WinUI3.Views
private void TopCommandGrid_PointerEntered(object sender, PointerRoutedEventArgs e)
{
- TopCommandGrid.Opacity = 0.5;
+ if (ViewModel.IsImmersiveMode)
+ {
+ ViewModel.TopCommandGridOpacity = .5f;
+ }
}
private void TopCommandGrid_PointerExited(object sender, PointerRoutedEventArgs e)
{
- TopCommandGrid.Opacity = 0;
+ if (ViewModel.IsImmersiveMode)
+ {
+ ViewModel.TopCommandGridOpacity = 0f;
+ }
}
private void TipContainerCenter_Loaded(object sender, RoutedEventArgs e)
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/SettingsPage.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/SettingsPage.xaml
index eb0c7af..35470b5 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/SettingsPage.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/SettingsPage.xaml
@@ -175,7 +175,7 @@
-
+
@@ -912,6 +912,20 @@
+
+
+
+
+
+
+
+