diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AboutControl.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AboutControl.xaml
index 6397a76..db9efe4 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AboutControl.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AboutControl.xaml
@@ -282,12 +282,6 @@
-
-
-
-
-
-
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsCanvas.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsCanvas.xaml.cs
index 617750f..67a752d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsCanvas.xaml.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsCanvas.xaml.cs
@@ -58,42 +58,42 @@ namespace BetterLyrics.WinUI3.Controls
private readonly ValueTransition _immersiveBgColorTransition = new(
initialValue: Colors.Transparent,
- durationSeconds: 0.3f,
+ defaultTotalDuration: 0.3f,
interpolator: (from, to, progress) => Helper.ColorHelper.GetInterpolatedColor(progress, from, to)
);
private readonly ValueTransition _immersiveBgOpacityTransition = new(
initialValue: 1f,
- durationSeconds: 0.3f
+ defaultTotalDuration: 0.3f
);
private readonly ValueTransition _accentColor1Transition = new(
initialValue: Colors.Transparent,
- durationSeconds: 0.3f,
+ defaultTotalDuration: 0.3f,
interpolator: (from, to, progress) => Helper.ColorHelper.GetInterpolatedColor(progress, from, to)
);
private readonly ValueTransition _accentColor2Transition = new(
initialValue: Colors.Transparent,
- durationSeconds: 0.3f,
+ defaultTotalDuration: 0.3f,
interpolator: (from, to, progress) => Helper.ColorHelper.GetInterpolatedColor(progress, from, to)
);
private readonly ValueTransition _accentColor3Transition = new(
initialValue: Colors.Transparent,
- durationSeconds: 0.3f,
+ defaultTotalDuration: 0.3f,
interpolator: (from, to, progress) => Helper.ColorHelper.GetInterpolatedColor(progress, from, to)
);
private readonly ValueTransition _accentColor4Transition = new(
initialValue: Colors.Transparent,
- durationSeconds: 0.3f,
+ defaultTotalDuration: 0.3f,
interpolator: (from, to, progress) => Helper.ColorHelper.GetInterpolatedColor(progress, from, to)
);
private readonly ValueTransition _canvasYScrollTransition = new(
initialValue: 0f,
- durationSeconds: 0.3f,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: 0.3f,
+ defaultEasingType: EasingType.EaseInOutSine
);
private readonly ValueTransition _mouseYScrollTransition = new(
initialValue: 0f,
- durationSeconds: 0.3f,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: 0.3f,
+ defaultEasingType: EasingType.EaseInOutSine
);
private TimeSpan _songPositionWithOffset;
@@ -292,7 +292,7 @@ namespace BetterLyrics.WinUI3.Controls
}
else if (e.Property == MouseScrollOffsetProperty)
{
- canvas._mouseYScrollTransition.StartTransition(Convert.ToDouble(e.NewValue));
+ canvas._mouseYScrollTransition.Start(Convert.ToDouble(e.NewValue));
}
else if (e.Property == MousePositionProperty)
{
@@ -318,11 +318,11 @@ namespace BetterLyrics.WinUI3.Controls
else if (e.Property == AlbumArtThemeColorsProperty)
{
var albumArtThemeColors = (AlbumArtThemeColors)e.NewValue;
- canvas._immersiveBgColorTransition.StartTransition(albumArtThemeColors.EnvColor);
- canvas._accentColor1Transition.StartTransition(albumArtThemeColors.AccentColor1);
- canvas._accentColor2Transition.StartTransition(albumArtThemeColors.AccentColor2);
- canvas._accentColor3Transition.StartTransition(albumArtThemeColors.AccentColor3);
- canvas._accentColor4Transition.StartTransition(albumArtThemeColors.AccentColor4);
+ canvas._immersiveBgColorTransition.Start(albumArtThemeColors.EnvColor);
+ canvas._accentColor1Transition.Start(albumArtThemeColors.AccentColor1);
+ canvas._accentColor2Transition.Start(albumArtThemeColors.AccentColor2);
+ canvas._accentColor3Transition.Start(albumArtThemeColors.AccentColor3);
+ canvas._accentColor4Transition.Start(albumArtThemeColors.AccentColor4);
canvas._albumArtThemeColors = albumArtThemeColors;
canvas._isLayoutChanged = true;
@@ -344,7 +344,6 @@ namespace BetterLyrics.WinUI3.Controls
var lyricsEffect = _lyricsWindowStatus.LyricsEffectSettings;
double songDuration = _gsmtcService.CurrentSongInfo.DurationMs;
- bool isForceWordByWord = _settingsService.AppSettings.GeneralSettings.IsForceWordByWordEffect;
Color overlayColor;
double finalOpacity;
@@ -410,7 +409,7 @@ namespace BetterLyrics.WinUI3.Controls
return _synchronizer.GetLinePlayingProgress(
_songPositionWithOffset.TotalMilliseconds,
line,
- isForceWordByWord
+ lyricsEffect.WordByWordEffectMode
);
}
);
@@ -486,9 +485,16 @@ namespace BetterLyrics.WinUI3.Controls
var targetScroll = LyricsLayoutManager.CalculateTargetScrollOffset(_renderLyricsLines, _primaryPlayingLineIndex);
if (targetScroll.HasValue) _canvasTargetScrollOffset = targetScroll.Value;
- _canvasYScrollTransition.SetEasingType(lyricsEffect.LyricsScrollEasingType);
- _canvasYScrollTransition.SetDuration(lyricsEffect.LyricsScrollDuration / 1000.0);
- _canvasYScrollTransition.StartTransition(_canvasTargetScrollOffset, _isLayoutChanged);
+ if (_isLayoutChanged)
+ {
+ _canvasYScrollTransition.JumpTo(_canvasTargetScrollOffset);
+ }
+ else
+ {
+ _canvasYScrollTransition.SetDurationMs(lyricsEffect.LyricsScrollDuration);
+ _canvasYScrollTransition.SetEasingType(lyricsEffect.LyricsScrollEasingType);
+ _canvasYScrollTransition.Start(_canvasTargetScrollOffset);
+ }
}
_canvasYScrollTransition.Update(elapsedTime);
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsEffectSettingsControl.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsEffectSettingsControl.xaml
index 6883d36..22546c2 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsEffectSettingsControl.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsEffectSettingsControl.xaml
@@ -23,6 +23,14 @@
Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="Effect" />
+
+
+
+
+
+
+
+
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml
index 2036240..8003fce 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml
@@ -365,10 +365,6 @@
-
-
-
-
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/WordByWordEffectMode.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/WordByWordEffectMode.cs
new file mode 100644
index 0000000..b0c623c
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/WordByWordEffectMode.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BetterLyrics.WinUI3.Enums
+{
+ public enum WordByWordEffectMode
+ {
+ Auto,
+ Never,
+ Always,
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DirectoryHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DirectoryHelper.cs
index 171c53d..b875739 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DirectoryHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DirectoryHelper.cs
@@ -56,6 +56,57 @@
}
catch (Exception) { }
}
+
+ ///
+ /// https://learn.microsoft.com/zh-cn/dotnet/standard/io/how-to-copy-directories
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive)
+ {
+ // Get information about the source directory
+ var dir = new DirectoryInfo(sourceDir);
+
+ // Check if the source directory exists
+ if (!dir.Exists)
+ throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
+
+ // Cache directories before we start copying
+ DirectoryInfo[] dirs = dir.GetDirectories();
+
+ // Create the destination directory
+ Directory.CreateDirectory(destinationDir);
+
+ // Get the files in the source directory and copy to the destination directory
+ foreach (FileInfo file in dir.GetFiles())
+ {
+ string targetFilePath = Path.Combine(destinationDir, file.Name);
+
+ CopyLockedFile(file.FullName, targetFilePath);
+ }
+
+ // If recursive and copying subdirectories, recursively call this method
+ if (recursive)
+ {
+ foreach (DirectoryInfo subDir in dirs)
+ {
+ string newDestinationDir = Path.Combine(destinationDir, subDir.Name);
+ CopyDirectory(subDir.FullName, newDestinationDir, true);
+ }
+ }
+ }
+
+ private static void CopyLockedFile(string sourcePath, string targetPath)
+ {
+ using (var sourceStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ using (var destStream = new FileStream(targetPath, FileMode.Create, FileAccess.Write))
+ {
+ sourceStream.CopyTo(destStream);
+ }
+ }
+
}
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PickerHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PickerHelper.cs
index 9649548..74962d4 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PickerHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PickerHelper.cs
@@ -42,19 +42,23 @@ namespace BetterLyrics.WinUI3.Helper
return file;
}
- public static async Task PickSaveFileAsync(IDictionary> fileTypeChoices)
+ public static async Task PickSaveFileAsync(IDictionary> fileTypeChoices, string? suggestedFileName = null)
{
var window = WindowHook.GetWindow();
- return await PickSaveFileAsync(window, fileTypeChoices);
+ return await PickSaveFileAsync(window, fileTypeChoices, suggestedFileName);
}
- public static async Task PickSaveFileAsync(T? window, IDictionary> fileTypeChoices)
+ public static async Task PickSaveFileAsync(T? window, IDictionary> fileTypeChoices, string? suggestedFileName = null)
{
if (window == null) return null;
var picker = new Windows.Storage.Pickers.FileSavePicker();
picker.FileTypeChoices.AddRange(fileTypeChoices);
+ if (suggestedFileName != null)
+ {
+ picker.SuggestedFileName = suggestedFileName;
+ }
var hwnd = WindowNative.GetWindowHandle(window);
InitializeWithWindow.Initialize(picker, hwnd);
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ValueTransition.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ValueTransition.cs
index 452395b..f87ccc3 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ValueTransition.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ValueTransition.cs
@@ -1,163 +1,252 @@
-// 2025/6/23 by Zhe Fang
-
-using BetterLyrics.WinUI3.Enums;
+using BetterLyrics.WinUI3.Enums;
+using BetterLyrics.WinUI3.Models;
using System;
+using System.Collections.Generic;
namespace BetterLyrics.WinUI3.Helper
{
- public class ValueTransition
- where T : struct
+ public class ValueTransition where T : struct
{
+ // 状态变量
private T _currentValue;
- private double _durationSeconds;
- private double _delaySeconds;
- private double _delayRemaining;
- private EasingType? _easingType;
- private Func _interpolator;
- private bool _isTransitioning;
- private double _progress;
private T _startValue;
private T _targetValue;
- public double DurationSeconds => _durationSeconds;
- public double DelaySeconds => _delaySeconds;
+ // 核心队列
+ private readonly Queue> _keyframeQueue = new Queue>();
- public bool IsTransitioning => _isTransitioning;
+ // 时间控制
+ private double _stepDuration; // 当前这一段的时长 (动态变化)
+ private double _totalDurationForAutoSplit; // 自动均分模式的总时长
+ private double _configuredDelaySeconds; // 配置的延迟时长
+
+ // 动画状态
+ private Enums.EasingType? _easingType;
+ private Func _interpolator;
+ private bool _isTransitioning;
+ private double _progress; // 当前段的进度 (0.0 ~ 1.0)
+
+ // 公开属性
public T Value => _currentValue;
- public T StartValue => _startValue;
- public T TargetValue => _targetValue;
- public EasingType? EasingType => _easingType;
- public double Progress => _progress;
+ public bool IsTransitioning => _isTransitioning;
+ public T TargetValue => _targetValue; // 获取当前段的目标值
+ public Enums.EasingType? EasingType => _easingType;
+ public double DurationSeconds => _totalDurationForAutoSplit;
- public ValueTransition(T initialValue, double durationSeconds, Func? interpolator = null, EasingType? easingType = null, double delaySeconds = 0)
+ public ValueTransition(T initialValue, double defaultTotalDuration = 0.3, EasingType? defaultEasingType = null, Func? interpolator = null)
{
_currentValue = initialValue;
_startValue = initialValue;
_targetValue = initialValue;
- _durationSeconds = durationSeconds;
- _delaySeconds = delaySeconds;
- _delayRemaining = 0;
- _progress = 1f;
- _isTransitioning = false;
+ _totalDurationForAutoSplit = defaultTotalDuration;
+
+ if (interpolator == null)
+ {
+ // 默认缓动
+ SetEasingType(Enums.EasingType.EaseInOutQuad);
+ }
+ else
+ {
+ _easingType = null;
+ _interpolator = interpolator;
+ }
if (interpolator != null)
{
_interpolator = interpolator;
_easingType = null;
}
- else if (easingType.HasValue)
+ else if (defaultEasingType != null)
{
- _easingType = easingType;
- _interpolator = GetInterpolatorByEasingType(_easingType.Value);
+ SetEasingType(defaultEasingType);
}
else
{
- _easingType = Enums.EasingType.EaseInOutQuad;
- _interpolator = GetInterpolatorByEasingType(_easingType.Value);
+ SetEasingType(Enums.EasingType.EaseInOutQuad);
}
}
+ #region Configuration
+
public void SetDuration(double seconds)
{
- if (seconds < 0)
- throw new ArgumentOutOfRangeException(nameof(seconds), "Duration must be positive.");
- _durationSeconds = seconds;
+ if (seconds < 0) throw new ArgumentOutOfRangeException(nameof(seconds));
+ _totalDurationForAutoSplit = seconds;
}
- public void SetDurationMs(double millionSeconds)
- {
- SetDuration(millionSeconds / 1000.0);
- }
-
- public void SetDuration(TimeSpan timeSpan)
- {
- SetDuration(timeSpan.TotalSeconds);
- }
+ public void SetDurationMs(double millionSeconds) => SetDuration(millionSeconds / 1000.0);
+ ///
+ /// 设置启动延迟。
+ /// 原理:在动画队列最前方插入一个“数值不变”的关键帧。
+ ///
public void SetDelay(double seconds)
{
- _delaySeconds = seconds;
+ _configuredDelaySeconds = seconds;
}
- private void JumpTo(T value)
+ public void SetEasingType(Enums.EasingType? easingType)
{
+ _easingType = easingType;
+ _interpolator = GetInterpolatorByEasingType(easingType);
+ }
+
+ #endregion
+
+ #region Control Methods
+
+ ///
+ /// 立即跳转到指定值(停止动画)
+ ///
+ public void JumpTo(T value)
+ {
+ _keyframeQueue.Clear();
_currentValue = value;
_startValue = value;
_targetValue = value;
- _progress = 1f;
- _delayRemaining = 0;
_isTransitioning = false;
+ _progress = 0;
}
- public void Reset(T value)
+ ///
+ /// 模式 A: 精确控制模式
+ /// 显式指定每一段的目标值和时长。
+ ///
+ public void Start(params Keyframe[] keyframes)
{
- _currentValue = value;
- _startValue = value;
- _targetValue = value;
- _progress = 0f;
- _delayRemaining = 0;
- _isTransitioning = false;
- }
+ if (keyframes == null || keyframes.Length == 0) return;
- public void StartTransition(T targetValue, bool jumpTo = false)
- {
- if (jumpTo)
+ PrepareStart();
+
+ // 1. 处理延迟 (插入静止帧)
+ if (_configuredDelaySeconds > 0)
{
- JumpTo(targetValue);
- return;
+ _keyframeQueue.Enqueue(new Keyframe(_currentValue, _configuredDelaySeconds));
}
- if (!targetValue.Equals(_currentValue))
+ // 2. 入队用户帧
+ foreach (var kf in keyframes)
{
- _startValue = _currentValue;
- _targetValue = targetValue;
- _progress = 0f;
- _delayRemaining = _delaySeconds;
- _isTransitioning = true;
+ _keyframeQueue.Enqueue(kf);
}
+
+ MoveToNextSegment(firstStart: true);
}
- public static bool Equals(double x, double y, double tolerance)
+ ///
+ /// 模式 B: 自动均分模式 (兼容旧写法)
+ /// 指定一串目标值,系统根据 SetDuration 的总时长平均分配。
+ ///
+ public void Start(params T[] values)
{
- var diff = Math.Abs(x - y);
- return diff <= tolerance || diff <= Math.Max(Math.Abs(x), Math.Abs(y)) * tolerance;
+ if (values == null || values.Length == 0) return;
+
+ // 如果目标就是当前值且只有1帧,直接跳过以省性能
+ if (values.Length == 1 && values[0].Equals(_currentValue) && _configuredDelaySeconds <= 0) return;
+
+ PrepareStart();
+
+ // 1. 处理延迟
+ if (_configuredDelaySeconds > 0)
+ {
+ _keyframeQueue.Enqueue(new Keyframe(_currentValue, _configuredDelaySeconds));
+ }
+
+ // 2. 计算均分时长
+ double autoStepDuration = _totalDurationForAutoSplit / values.Length;
+
+ // 3. 入队生成帧
+ foreach (var val in values)
+ {
+ _keyframeQueue.Enqueue(new Keyframe(val, autoStepDuration));
+ }
+
+ MoveToNextSegment(firstStart: true);
+ }
+
+ #endregion
+
+ #region Core Logic
+
+ private void PrepareStart()
+ {
+ _keyframeQueue.Clear();
+ _isTransitioning = true;
+ }
+
+ private void MoveToNextSegment(bool firstStart = false)
+ {
+ if (_keyframeQueue.Count > 0)
+ {
+ var kf = _keyframeQueue.Dequeue();
+
+ // 起点逻辑:如果是刚开始,起点是当前值;如果是中间切换,起点是上一段的终点
+ _startValue = firstStart ? _currentValue : _targetValue;
+ _targetValue = kf.Value;
+ _stepDuration = kf.Duration;
+
+ if (firstStart) _progress = 0f;
+ // 注意:非 firstStart 时不重置 _progress,保留溢出值以平滑过渡
+ }
+ else
+ {
+ // 队列耗尽,动画结束
+ _currentValue = _targetValue;
+ _isTransitioning = false;
+ _progress = 1f;
+ }
}
public void Update(TimeSpan elapsedTime)
{
if (!_isTransitioning) return;
- if (_delayRemaining > 0)
- {
- double consume = Math.Min(_delayRemaining, elapsedTime.TotalSeconds);
- _delayRemaining -= consume;
- if (_delayRemaining > 0)
- return;
- elapsedTime = TimeSpan.FromSeconds(elapsedTime.TotalSeconds - consume);
- }
+ double timeStep = elapsedTime.TotalSeconds;
- if (_durationSeconds <= 0)
+ // 使用 while 处理单帧时间过长跨越多段的情况
+ while (timeStep > 0 && _isTransitioning)
{
- _progress = 1f;
- }
- else
- {
- _progress += elapsedTime.TotalSeconds / _durationSeconds;
- }
+ // 计算当前帧的步进比例
+ // 极小值保护,防止除以0
+ double progressDelta = (_stepDuration > 0.000001) ? (timeStep / _stepDuration) : 1.0;
- if (_progress >= 1f)
- {
- _progress = 1f;
- _currentValue = _targetValue;
- _isTransitioning = false;
- }
- else
- {
- _currentValue = _interpolator(_startValue, _targetValue, _progress);
+ if (_progress + progressDelta >= 1.0)
+ {
+ // === 当前段结束 ===
+
+ // 1. 计算这一段实际消耗的时间
+ double timeConsumed = (1.0 - _progress) * _stepDuration;
+
+ // 2. 剩余时间留给下一段
+ timeStep -= timeConsumed;
+
+ // 3. 修正当前值到目标值
+ _progress = 1.0;
+ _currentValue = _targetValue;
+
+ // 4. 切换到下一段
+ MoveToNextSegment();
+
+ // 5. 如果还有下一段,进度归零
+ if (_isTransitioning) _progress = 0f;
+ }
+ else
+ {
+ // === 当前段进行中 ===
+ _progress += progressDelta;
+ timeStep = 0; // 时间耗尽
+
+ // 插值计算
+ _currentValue = _interpolator(_startValue, _targetValue, _progress);
+ }
}
}
- private Func GetInterpolatorByEasingType(EasingType? type)
+ #endregion
+
+ #region Interpolators
+
+ private Func GetInterpolatorByEasingType(Enums.EasingType? type)
{
if (typeof(T) == typeof(double))
{
@@ -166,58 +255,32 @@ namespace BetterLyrics.WinUI3.Helper
double s = (double)(object)start;
double e = (double)(object)end;
double t = progress;
+
+ // 使用 EasingHelper (假设您的项目中已有此辅助类)
switch (type)
{
- case Enums.EasingType.EaseInOutSine:
- t = EasingHelper.EaseInOutSine(t);
- break;
- case Enums.EasingType.EaseInOutQuad:
- t = EasingHelper.EaseInOutQuad(t);
- break;
- case Enums.EasingType.EaseInOutCubic:
- t = EasingHelper.EaseInOutCubic(t);
- break;
- case Enums.EasingType.EaseInOutQuart:
- t = EasingHelper.EaseInOutQuart(t);
- break;
- case Enums.EasingType.EaseInOutQuint:
- t = EasingHelper.EaseInOutQuint(t);
- break;
- case Enums.EasingType.EaseInOutExpo:
- t = EasingHelper.EaseInOutExpo(t);
- break;
- case Enums.EasingType.EaseInOutCirc:
- t = EasingHelper.EaseInOutCirc(t);
- break;
- case Enums.EasingType.EaseInOutBack:
- t = EasingHelper.EaseInOutBack(t);
- break;
- case Enums.EasingType.EaseInOutElastic:
- t = EasingHelper.EaseInOutElastic(t);
- break;
- case Enums.EasingType.EaseInOutBounce:
- t = EasingHelper.EaseInOutBounce(t);
- break;
- case Enums.EasingType.SmoothStep:
- t = EasingHelper.SmoothStep(t);
- break;
- case Enums.EasingType.Linear:
- t = EasingHelper.Linear(t);
- break;
- default:
- t = EasingHelper.EaseInOutQuad(t);
- break;
+ case Enums.EasingType.EaseInOutSine: t = EasingHelper.EaseInOutSine(t); break;
+ case Enums.EasingType.EaseInOutQuad: t = EasingHelper.EaseInOutQuad(t); break;
+ case Enums.EasingType.EaseInOutCubic: t = EasingHelper.EaseInOutCubic(t); break;
+ case Enums.EasingType.EaseInOutQuart: t = EasingHelper.EaseInOutQuart(t); break;
+ case Enums.EasingType.EaseInOutQuint: t = EasingHelper.EaseInOutQuint(t); break;
+ case Enums.EasingType.EaseInOutExpo: t = EasingHelper.EaseInOutExpo(t); break;
+ case Enums.EasingType.EaseInOutCirc: t = EasingHelper.EaseInOutCirc(t); break;
+ case Enums.EasingType.EaseInOutBack: t = EasingHelper.EaseInOutBack(t); break;
+ case Enums.EasingType.EaseInOutElastic: t = EasingHelper.EaseInOutElastic(t); break;
+ case Enums.EasingType.EaseInOutBounce: t = EasingHelper.EaseInOutBounce(t); break;
+ case Enums.EasingType.SmoothStep: t = EasingHelper.SmoothStep(t); break;
+ case Enums.EasingType.Linear: t = EasingHelper.Linear(t); break;
+ default: t = EasingHelper.EaseInOutQuad(t); break;
}
+
return (T)(object)(s + (e - s) * t);
};
}
- throw new NotSupportedException($"Easing type {type} is not supported for type {typeof(T)}.");
+
+ throw new NotSupportedException($"Type {typeof(T)} is not supported.");
}
- public void SetEasingType(EasingType? easingType)
- {
- _easingType = easingType;
- _interpolator = GetInterpolatorByEasingType(easingType);
- }
+ #endregion
}
}
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Logic/LyricsAnimator.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Logic/LyricsAnimator.cs
index 7da6224..dcb4068 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Logic/LyricsAnimator.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Logic/LyricsAnimator.cs
@@ -95,13 +95,13 @@ namespace BetterLyrics.WinUI3.Logic
line.BlurAmountTransition.SetDuration(yScrollDuration);
line.BlurAmountTransition.SetDelay(yScrollDelay);
- line.BlurAmountTransition.StartTransition(
+ line.BlurAmountTransition.Start(
(isMouseScrolling || isSecondaryLinePlaying) ? 0 :
(lyricsEffect.IsLyricsBlurEffectEnabled ? (5 * distanceFactor) : 0));
line.ScaleTransition.SetDuration(yScrollDuration);
line.ScaleTransition.SetDelay(yScrollDelay);
- line.ScaleTransition.StartTransition(
+ line.ScaleTransition.Start(
isSecondaryLinePlaying ? _highlightedScale :
(lyricsEffect.IsLyricsOutOfSightEffectEnabled ?
(_highlightedScale - distanceFactor * (_highlightedScale - _defaultScale)) :
@@ -109,37 +109,37 @@ namespace BetterLyrics.WinUI3.Logic
line.PhoneticOpacityTransition.SetDuration(yScrollDuration);
line.PhoneticOpacityTransition.SetDelay(yScrollDelay);
- line.PhoneticOpacityTransition.StartTransition(
+ line.PhoneticOpacityTransition.Start(
isSecondaryLinePlaying ? phoneticOpacity :
CalculateTargetOpacity(phoneticOpacity, phoneticOpacity, distanceFactor, isMouseScrolling, lyricsEffect));
// 原文不透明度(已播放)
line.PlayedOriginalOpacityTransition.SetDuration(yScrollDuration);
line.PlayedOriginalOpacityTransition.SetDelay(yScrollDelay);
- line.PlayedOriginalOpacityTransition.StartTransition(
+ line.PlayedOriginalOpacityTransition.Start(
isSecondaryLinePlaying ? 1.0 :
CalculateTargetOpacity(originalOpacity, 1.0, distanceFactor, isMouseScrolling, lyricsEffect));
// 原文不透明度(未播放)
line.UnplayedOriginalOpacityTransition.SetDuration(yScrollDuration);
line.UnplayedOriginalOpacityTransition.SetDelay(yScrollDelay);
- line.UnplayedOriginalOpacityTransition.StartTransition(
+ line.UnplayedOriginalOpacityTransition.Start(
isSecondaryLinePlaying ? originalOpacity :
CalculateTargetOpacity(originalOpacity, originalOpacity, distanceFactor, isMouseScrolling, lyricsEffect));
line.TranslatedOpacityTransition.SetDuration(yScrollDuration);
line.TranslatedOpacityTransition.SetDelay(yScrollDelay);
- line.TranslatedOpacityTransition.StartTransition(
+ line.TranslatedOpacityTransition.Start(
isSecondaryLinePlaying ? translatedOpacity :
CalculateTargetOpacity(translatedOpacity, translatedOpacity, distanceFactor, isMouseScrolling, lyricsEffect));
line.ColorTransition.SetDuration(yScrollDuration);
line.ColorTransition.SetDelay(yScrollDelay);
- line.ColorTransition.StartTransition(isSecondaryLinePlaying ? fgColor : bgColor);
+ line.ColorTransition.Start(isSecondaryLinePlaying ? fgColor : bgColor);
line.AngleTransition.SetEasingType(canvasYScrollTransition.EasingType);
line.AngleTransition.SetDuration(yScrollDuration);
line.AngleTransition.SetDelay(yScrollDelay);
- line.AngleTransition.StartTransition(
+ line.AngleTransition.Start(
(lyricsEffect.IsFanLyricsEnabled && !isMouseScrolling) ?
Math.PI * (lyricsEffect.FanLyricsAngle / 180.0) * distanceFactor * (i > primaryPlayingLineIndex ? 1 : -1) :
0);
@@ -149,7 +149,7 @@ namespace BetterLyrics.WinUI3.Logic
line.YOffsetTransition.SetDelay(yScrollDelay);
// 设计之初是当 isLayoutChanged 为真时 jumpTo
// 但考虑到动画视觉,强制使用动画
- line.YOffsetTransition.StartTransition(targetYScrollOffset);
+ line.YOffsetTransition.Start(targetYScrollOffset);
}
var maxAnimationDurationMs = Math.Max(line.EndMs - currentPositionMs, 0);
@@ -170,10 +170,15 @@ namespace BetterLyrics.WinUI3.Logic
switch (lyricsEffect.LyricsGlowEffectScope)
{
case Enums.LyricsEffectScope.LineStartToCurrentChar:
- if (isSecondaryLinePlayingChanged)
+ if (isSecondaryLinePlayingChanged && isSecondaryLinePlaying)
{
- renderChar.GlowTransition.SetDurationMs(Math.Min(Time.AnimationDuration.TotalMilliseconds, maxAnimationDurationMs));
- renderChar.GlowTransition.StartTransition(isSecondaryLinePlaying ? targetGlow : 0);
+ var stepInOutDuration = Math.Min(Time.AnimationDuration.TotalMilliseconds, maxAnimationDurationMs) / 2.0 / 1000.0;
+ var stepLastingDuration = Math.Max(maxAnimationDurationMs / 1000.0 - stepInOutDuration * 2, 0);
+ renderChar.GlowTransition.Start(
+ new Models.Keyframe(targetGlow, stepInOutDuration),
+ new Models.Keyframe(targetGlow, stepLastingDuration),
+ new Models.Keyframe(0, stepInOutDuration)
+ );
}
break;
default:
@@ -188,12 +193,12 @@ namespace BetterLyrics.WinUI3.Logic
if (isSecondaryLinePlayingChanged)
{
- renderChar.FloatTransition.StartTransition(isSecondaryLinePlaying ? targetFloat : 0);
+ renderChar.FloatTransition.Start(isSecondaryLinePlaying ? targetFloat : 0);
}
if (isCharPlayingChanged)
{
renderChar.FloatTransition.SetDurationMs(Math.Min(lyricsEffect.LyricsFloatAnimationDuration, maxAnimationDurationMs));
- renderChar.FloatTransition.StartTransition(0);
+ renderChar.FloatTransition.Start(0);
}
}
@@ -223,8 +228,14 @@ namespace BetterLyrics.WinUI3.Logic
{
if (syllable.DurationMs >= lyricsEffect.LyricsScaleEffectLongSyllableDuration)
{
- renderChar.ScaleTransition.SetDurationMs(Math.Min(syllable.DurationMs, maxAnimationDurationMs) / 2.0);
- renderChar.ScaleTransition.StartTransition(isSyllablePlaying ? targetScale : 1);
+ if (isSyllablePlaying)
+ {
+ var stepDuration = Math.Min(syllable.DurationMs, maxAnimationDurationMs) / 2.0 / 1000.0;
+ renderChar.ScaleTransition.Start(
+ new Models.Keyframe(targetScale, stepDuration),
+ new Models.Keyframe(1.0, stepDuration)
+ );
+ }
}
}
}
@@ -239,8 +250,14 @@ namespace BetterLyrics.WinUI3.Logic
{
foreach (var renderChar in syllable.ChildrenRenderLyricsChars)
{
- renderChar.GlowTransition.SetDurationMs(Math.Min(syllable.DurationMs, maxAnimationDurationMs) / 2.0);
- renderChar.GlowTransition.StartTransition(isSyllablePlaying ? targetGlow : 0);
+ if (isSyllablePlaying)
+ {
+ var stepDuration = Math.Min(syllable.DurationMs, maxAnimationDurationMs) / 2.0 / 1000.0;
+ renderChar.GlowTransition.Start(
+ new Models.Keyframe(targetGlow, stepDuration),
+ new Models.Keyframe(0, stepDuration)
+ );
+ }
}
}
break;
@@ -256,20 +273,10 @@ namespace BetterLyrics.WinUI3.Logic
// 更新动画
foreach (var renderChar in line.PrimaryRenderChars)
{
- renderChar.ScaleTransition.Update(elapsedTime);
- renderChar.GlowTransition.Update(elapsedTime);
- renderChar.FloatTransition.Update(elapsedTime);
+ renderChar.Update(elapsedTime);
}
- line.AngleTransition.Update(elapsedTime);
- line.ScaleTransition.Update(elapsedTime);
- line.BlurAmountTransition.Update(elapsedTime);
- line.PhoneticOpacityTransition.Update(elapsedTime);
- line.PlayedOriginalOpacityTransition.Update(elapsedTime);
- line.UnplayedOriginalOpacityTransition.Update(elapsedTime);
- line.TranslatedOpacityTransition.Update(elapsedTime);
- line.YOffsetTransition.Update(elapsedTime);
- line.ColorTransition.Update(elapsedTime);
+ line.Update(elapsedTime);
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Logic/LyricsSynchronizer.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Logic/LyricsSynchronizer.cs
index 2b05cce..6619507 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Logic/LyricsSynchronizer.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Logic/LyricsSynchronizer.cs
@@ -1,4 +1,5 @@
-using BetterLyrics.WinUI3.Models;
+using BetterLyrics.WinUI3.Enums;
+using BetterLyrics.WinUI3.Models;
using BetterLyrics.WinUI3.Models.Lyrics;
using System;
using System.Collections.Generic;
@@ -67,7 +68,7 @@ namespace BetterLyrics.WinUI3.Logic
public LinePlaybackState GetLinePlayingProgress(
double currentTimeMs,
RenderLyricsLine line,
- bool isForceWordByWord)
+ WordByWordEffectMode wordByWordEffectMode)
{
var state = new LinePlaybackState { SyllableStartIndex = 0, SyllableLength = 0, SyllableProgress = 0 };
@@ -87,23 +88,34 @@ namespace BetterLyrics.WinUI3.Logic
return state;
}
- // 逐字
- if (line.PrimaryRenderSyllables != null && line.PrimaryRenderSyllables.Count > 1)
+ switch (wordByWordEffectMode)
{
- return CalculateSyllableProgress(currentTimeMs, line, lineEndMs);
- }
-
- // 强制逐字
- if (isForceWordByWord && line.PrimaryText.Length > 0)
- {
- return CalculateSimulatedProgress(currentTimeMs, line, lineEndMs);
- }
- else
- {
- // 普通行
- state.SyllableStartIndex = line.PrimaryText.Length;
- state.SyllableProgress = 1f;
- return state;
+ case WordByWordEffectMode.Auto:
+ if (line.PrimaryRenderSyllables.Count > 1)
+ {
+ return CalculateSyllableProgress(currentTimeMs, line, lineEndMs);
+ }
+ else
+ {
+ state.SyllableStartIndex = line.PrimaryText.Length;
+ state.SyllableProgress = 1f;
+ return state;
+ }
+ case WordByWordEffectMode.Never:
+ state.SyllableStartIndex = line.PrimaryText.Length;
+ state.SyllableProgress = 1f;
+ return state;
+ case WordByWordEffectMode.Always:
+ if (line.PrimaryRenderSyllables.Count > 1)
+ {
+ return CalculateSyllableProgress(currentTimeMs, line, lineEndMs);
+ }
+ else
+ {
+ return CalculateSimulatedProgress(currentTimeMs, line, lineEndMs);
+ }
+ default:
+ return state;
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Keyframe.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Keyframe.cs
new file mode 100644
index 0000000..7294b89
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Keyframe.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BetterLyrics.WinUI3.Models
+{
+ public struct Keyframe
+ {
+ public T Value { get; }
+ public double Duration { get; }
+
+ public Keyframe(T value, double durationSeconds)
+ {
+ Value = value;
+ Duration = durationSeconds;
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Lyrics/RenderLyricsChar.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Lyrics/RenderLyricsChar.cs
index c0fa3c4..ec6c610 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Lyrics/RenderLyricsChar.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Lyrics/RenderLyricsChar.cs
@@ -1,6 +1,7 @@
using BetterLyrics.WinUI3.Constants;
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Helper;
+using System;
using Windows.Foundation;
namespace BetterLyrics.WinUI3.Models.Lyrics
@@ -19,20 +20,28 @@ namespace BetterLyrics.WinUI3.Models.Lyrics
{
ScaleTransition = new(
initialValue: 1.0,
- durationSeconds: Time.AnimationDuration.TotalSeconds,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: Time.AnimationDuration.TotalSeconds,
+ defaultEasingType: EasingType.EaseInOutSine
);
GlowTransition = new(
initialValue: 0,
- durationSeconds: Time.AnimationDuration.TotalSeconds,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: Time.AnimationDuration.TotalSeconds,
+ defaultEasingType: EasingType.EaseInOutSine
);
FloatTransition = new(
initialValue: 0,
- durationSeconds: Time.LongAnimationDuration.TotalSeconds,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: Time.LongAnimationDuration.TotalSeconds,
+ defaultEasingType: EasingType.EaseInOutSine
);
LayoutRect = layoutRect;
}
+
+ public void Update(TimeSpan elapsedTime)
+ {
+ ScaleTransition.Update(elapsedTime);
+ GlowTransition.Update(elapsedTime);
+ FloatTransition.Update(elapsedTime);
+ }
+
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Lyrics/RenderLyricsLine.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Lyrics/RenderLyricsLine.cs
index 210c0d3..7322cbe 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Lyrics/RenderLyricsLine.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Lyrics/RenderLyricsLine.cs
@@ -5,6 +5,7 @@ using Microsoft.Graphics.Canvas.Geometry;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
using Microsoft.UI;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
@@ -77,47 +78,47 @@ namespace BetterLyrics.WinUI3.Models.Lyrics
{
AngleTransition = new(
initialValue: 0,
- durationSeconds: AnimationDuration,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: AnimationDuration,
+ defaultEasingType: EasingType.EaseInOutSine
);
BlurAmountTransition = new(
initialValue: 0,
- durationSeconds: AnimationDuration,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: AnimationDuration,
+ defaultEasingType: EasingType.EaseInOutSine
);
PhoneticOpacityTransition = new(
initialValue: 0,
- durationSeconds: AnimationDuration,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: AnimationDuration,
+ defaultEasingType: EasingType.EaseInOutSine
);
PlayedOriginalOpacityTransition = new(
initialValue: 0,
- durationSeconds: AnimationDuration,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: AnimationDuration,
+ defaultEasingType: EasingType.EaseInOutSine
);
UnplayedOriginalOpacityTransition = new(
initialValue: 0,
- durationSeconds: AnimationDuration,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: AnimationDuration,
+ defaultEasingType: EasingType.EaseInOutSine
);
TranslatedOpacityTransition = new(
initialValue: 0,
- durationSeconds: AnimationDuration,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: AnimationDuration,
+ defaultEasingType: EasingType.EaseInOutSine
);
ScaleTransition = new(
initialValue: 0,
- durationSeconds: AnimationDuration,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: AnimationDuration,
+ defaultEasingType: EasingType.EaseInOutSine
);
YOffsetTransition = new(
initialValue: 0,
- durationSeconds: AnimationDuration,
- easingType: EasingType.EaseInOutSine
+ defaultTotalDuration: AnimationDuration,
+ defaultEasingType: EasingType.EaseInOutSine
);
ColorTransition = new(
initialValue: Colors.Transparent,
- durationSeconds: 0.3f,
+ defaultTotalDuration: 0.3f,
interpolator: (from, to, progress) => Helper.ColorHelper.GetInterpolatedColor(progress, from, to)
);
@@ -282,5 +283,18 @@ namespace BetterLyrics.WinUI3.Models.Lyrics
}
}
+ public void Update(TimeSpan elapsedTime)
+ {
+ AngleTransition.Update(elapsedTime);
+ ScaleTransition.Update(elapsedTime);
+ BlurAmountTransition.Update(elapsedTime);
+ PhoneticOpacityTransition.Update(elapsedTime);
+ PlayedOriginalOpacityTransition.Update(elapsedTime);
+ UnplayedOriginalOpacityTransition.Update(elapsedTime);
+ TranslatedOpacityTransition.Update(elapsedTime);
+ YOffsetTransition.Update(elapsedTime);
+ ColorTransition.Update(elapsedTime);
+ }
+
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/GeneralSettings.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/GeneralSettings.cs
index 74d11af..41ca7c5 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/GeneralSettings.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/GeneralSettings.cs
@@ -8,7 +8,6 @@ namespace BetterLyrics.WinUI3.Models.Settings
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LanguageCode { get; set; } = "";
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string LXMusicServer { get; set; } = string.Empty;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string AmllTtmlDbBaseUrl { get; set; } = Constants.AmllTTmlDB.BaseUrl;
- [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsForceWordByWordEffect { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List ShowOrHideLyricsWindowShortcut { get; set; } = new List { "Ctrl", "Alt", "H" };
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ExitOnLyricsWindowClosed { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ListenOnNewPlaybackSource { get; set; } = true;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/LyricsEffectSettings.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/LyricsEffectSettings.cs
index 5be05ce..c443909 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/LyricsEffectSettings.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/LyricsEffectSettings.cs
@@ -6,6 +6,8 @@ namespace BetterLyrics.WinUI3.Models.Settings
{
public partial class LyricsEffectSettings : ObservableRecipient, ICloneable
{
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial WordByWordEffectMode WordByWordEffectMode { get; set; } = WordByWordEffectMode.Auto;
+
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsBlurEffectEnabled { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsFadeOutEffectEnabled { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsOutOfSightEffectEnabled { get; set; } = true;
@@ -54,6 +56,8 @@ namespace BetterLyrics.WinUI3.Models.Settings
{
return new LyricsEffectSettings(this.LyricsScrollTopDuration, this.LyricsScrollDuration, this.LyricsScrollBottomDuration, this.LyricsScrollEasingType)
{
+ WordByWordEffectMode = this.WordByWordEffectMode,
+
IsLyricsBlurEffectEnabled = this.IsLyricsBlurEffectEnabled,
IsLyricsFadeOutEffectEnabled = this.IsLyricsFadeOutEffectEnabled,
IsLyricsOutOfSightEffectEnabled = this.IsLyricsOutOfSightEffectEnabled,
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Renderer/CoverBackgroundRenderer.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Renderer/CoverBackgroundRenderer.cs
index 3a3eb9d..1d699f6 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Renderer/CoverBackgroundRenderer.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Renderer/CoverBackgroundRenderer.cs
@@ -58,7 +58,7 @@ namespace BetterLyrics.WinUI3.Renderer
public CoverBackgroundRenderer()
{
- _crossfadeTransition = new ValueTransition(1.0, 0.7, easingType: EasingType.Linear);
+ _crossfadeTransition = new ValueTransition(1.0, 0.7, defaultEasingType: EasingType.Linear);
}
public void SetCoverBitmap(CanvasBitmap? newBitmap)
@@ -73,18 +73,18 @@ namespace BetterLyrics.WinUI3.Renderer
if (_currentBitmap == null)
{
- _crossfadeTransition.StartTransition(1.0, jumpTo: true);
+ _crossfadeTransition.JumpTo(1.0);
}
else
{
if (_previousBitmap == null)
{
- _crossfadeTransition.StartTransition(1.0, jumpTo: true);
+ _crossfadeTransition.JumpTo(1.0);
}
else
{
- _crossfadeTransition.Reset(0.0);
- _crossfadeTransition.StartTransition(1.0);
+ _crossfadeTransition.JumpTo(0.0);
+ _crossfadeTransition.Start(1.0);
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/FileSystemService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/FileSystemService.cs
index 8c6440f..1565387 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/FileSystemService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/FileSystemService.cs
@@ -251,11 +251,7 @@ namespace BetterLyrics.WinUI3.Services.FileSystemService
.Where(x => x.MediaFolderId == folder.Id)
.ExecuteDeleteAsync();
- // VACUUM 是 SQLite 特有的命令
- if (context.Database.IsSqlite())
- {
- await context.Database.ExecuteSqlRawAsync("VACUUM");
- }
+ await context.Database.ExecuteSqlRawAsync("VACUUM");
}
finally
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsCacheService/ILyricsCacheService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsCacheService/ILyricsCacheService.cs
index d4e5495..43b283a 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsCacheService/ILyricsCacheService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsCacheService/ILyricsCacheService.cs
@@ -8,5 +8,6 @@ namespace BetterLyrics.WinUI3.Services.LyricsCacheService
{
Task GetLyricsAsync(SongInfo songInfo, LyricsSearchProvider provider);
Task SaveLyricsAsync(SongInfo songInfo, LyricsCacheItem result);
+ Task ClearCacheAsync();
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsCacheService/LyricsCacheService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsCacheService/LyricsCacheService.cs
index 9612d91..7810805 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsCacheService/LyricsCacheService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsCacheService/LyricsCacheService.cs
@@ -69,5 +69,13 @@ namespace BetterLyrics.WinUI3.Services.LyricsCacheService
await context.SaveChangesAsync();
}
+ public async Task ClearCacheAsync()
+ {
+ using var context = await _contextFactory.CreateDbContextAsync();
+
+ await context.LyricsCache.ExecuteDeleteAsync();
+ await context.Database.ExecuteSqlRawAsync("VACUUM;");
+ }
+
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ar/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ar/Resources.resw
index a61435e..586c494 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ar/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ar/Resources.resw
@@ -888,12 +888,6 @@
فرض البقاء في المقدمة
-
- فرض محاكاة تأثير كلمة بكلمة حتى إذا كانت الكلمات الحالية لا تحتوي على معلومات كلمة بكلمة
-
-
- فرض تفعيل تأثير الكلمات كلمة بكلمة
-
معدل إطارات التصيير (FPS)
@@ -1575,4 +1569,13 @@
دليل المستخدم
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/de/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/de/Resources.resw
index d1c7efb..d9d1f4e 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/de/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/de/Resources.resw
@@ -888,12 +888,6 @@
Immer im Vordergrund erzwingen
-
- Wort-für-Wort-Simulation erzwingen, auch wenn der aktuelle Songtext keine entsprechenden Infos enthält
-
-
- Wort-für-Wort-Effekt erzwingen
-
Rendering-FPS
@@ -1575,4 +1569,13 @@
Benutzerhandbuch
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en/Resources.resw
index 029e22e..ce3c074 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en/Resources.resw
@@ -891,12 +891,6 @@
Force Always on Top
-
- Force word-by-word simulation even if current lyrics don't have word-by-word info
-
-
- Force Word-by-Word Effect
-
Render FPS
@@ -1143,6 +1137,18 @@
Lyrics Window Status Switch Shortcut
+
+ Word-by-word Animation Strategy
+
+
+ Always
+
+
+ Auto
+
+
+ Never
+
Adjusting this value will affect sequential search and best match search results, but will not affect search results in the manual lyrics search interface
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/es/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/es/Resources.resw
index 352822e..c749408 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/es/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/es/Resources.resw
@@ -888,12 +888,6 @@
Forzar siempre visible
-
- Forzar simulación palabra por palabra incluso si la letra actual no tiene información palabra por palabra
-
-
- Forzar efecto palabra por palabra
-
FPS de renderizado
@@ -1575,4 +1569,13 @@
Guía de usuario
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/fr/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/fr/Resources.resw
index 35186ff..a417457 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/fr/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/fr/Resources.resw
@@ -888,12 +888,6 @@
Forcer toujours au premier plan
-
- Forcer la simulation mot à mot même si les paroles n'ont pas d'infos mot à mot
-
-
- Forcer l'effet mot à mot
-
FPS de rendu
@@ -1575,4 +1569,13 @@
Guide de l'utilisateur
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/hi/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/hi/Resources.resw
index d9505d8..db24b43 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/hi/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/hi/Resources.resw
@@ -888,12 +888,6 @@
हमेशा शीर्ष पर रखने के लिए बाध्य करें
-
- शब्द-दर-शब्द प्रभाव का अनुकरण करने के लिए बाध्य करें, भले ही वर्तमान बोल में शब्द-दर-शब्द जानकारी न हो
-
-
- शब्द-दर-शब्द प्रभाव सक्षम करने के लिए बाध्य करें
-
रेंडरिंग फ्रेम दर
@@ -1575,4 +1569,13 @@
उपयोगकर्ता गाइड
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/id/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/id/Resources.resw
index 2bc2f27..04f61d2 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/id/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/id/Resources.resw
@@ -888,12 +888,6 @@
Paksa Selalu di Atas
-
- Paksa simulasi efek kata-demi-kata meskipun lirik saat ini tidak memiliki informasi kata-demi-kata
-
-
- Paksa Aktifkan Efek Kata-demi-Kata
-
Frame Rate Rendering
@@ -1575,4 +1569,13 @@
Panduan Pengguna
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja/Resources.resw
index 60a9737..0877b35 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja/Resources.resw
@@ -888,12 +888,6 @@
常にトップに強制的に表示
-
- 現在の歌詞に文字単位の情報がない場合でも、文字単位の歌詞シミュレーションをします
-
-
- 文字単位の歌詞効果を強制する
-
描画 FPS
@@ -1575,4 +1569,13 @@
ユーザーガイド
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko/Resources.resw
index 9ccc429..108baf9 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko/Resources.resw
@@ -888,12 +888,6 @@
항상 위에 표시 강제
-
- 현재 가사에 글자 단위 정보가 없더라도 글자 단위 시뮬레이션을 강제합니다
-
-
- 단어 단위 효과 강제 적용
-
렌더링 FPS
@@ -1575,4 +1569,13 @@
사용자 가이드
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ms/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ms/Resources.resw
index 6289ceb..c7a621e 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ms/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ms/Resources.resw
@@ -888,12 +888,6 @@
Paksa Sentiasa di Atas
-
- Paksa simulasi kesan perkataan-demi-perkataan walaupun lirik semasa tidak mempunyai maklumat perkataan-demi-perkataan
-
-
- Paksa Dayakan Kesan Perkataan-demi-Perkataan
-
Kadar Bingkai Penyajian (FPS)
@@ -1575,4 +1569,13 @@
Panduan Pengguna
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/pt/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/pt/Resources.resw
index ec955c6..48e84f5 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/pt/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/pt/Resources.resw
@@ -888,12 +888,6 @@
Forçar Sempre no Topo
-
- Forçar a simulação do efeito palavra por palavra, mesmo que a letra atual não tenha informações palavra por palavra
-
-
- Forçar Efeito Palavra por Palavra
-
Taxa de Fotogramas de Renderização
@@ -1575,4 +1569,13 @@
Guia do Utilizador
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ru/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ru/Resources.resw
index 26cf55c..b8afc3f 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ru/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ru/Resources.resw
@@ -888,12 +888,6 @@
Принудительно поверх всех окон
-
- Принудительно имитировать пословный эффект, даже если текущий текст не имеет пословной информации
-
-
- Принудительно включить пословный эффект
-
FPS рендеринга
@@ -1575,4 +1569,13 @@
Руководство пользователя
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/th/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/th/Resources.resw
index 46e4165..b063908 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/th/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/th/Resources.resw
@@ -888,12 +888,6 @@
บังคับให้อยู่บนสุดเสมอ
-
- บังคับจำลองเอฟเฟกต์ทีละคำแม้ว่าเนื้อเพลงปัจจุบันจะไม่มีข้อมูลทีละคำ
-
-
- บังคับเปิดใช้เอฟเฟกต์ทีละคำ
-
เฟรมเรตการเรนเดอร์
@@ -1575,4 +1569,13 @@
คู่มือผู้ใช้
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/vi/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/vi/Resources.resw
index fed2c08..0ac7501 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/vi/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/vi/Resources.resw
@@ -888,12 +888,6 @@
Buộc luôn ở trên cùng
-
- Buộc mô phỏng hiệu ứng từng từ ngay cả khi lời bài hát hiện tại không có thông tin từng từ
-
-
- Buộc bật hiệu ứng từng từ
-
Tốc độ khung hình kết xuất
@@ -1575,4 +1569,13 @@
Hướng dẫn sử dụng
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-Hans/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-Hans/Resources.resw
index a2620cb..e81c176 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-Hans/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-Hans/Resources.resw
@@ -891,12 +891,6 @@
强制置于顶层
-
- 即使当前歌词没有逐字信息,仍强制模拟逐字效果
-
-
- 强制启用逐字歌词效果
-
渲染帧率
@@ -1143,6 +1137,15 @@
歌词窗口状态切换快捷键
+
+
+
+
+
+
+
+
+
调整此值将影响顺序搜索和最佳匹配搜索结果,但不会影响手动歌词搜索界面中的搜索结果
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-Hant/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-Hant/Resources.resw
index 06cfd6c..ea3c613 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-Hant/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-Hant/Resources.resw
@@ -888,12 +888,6 @@
強制置於頂層
-
- 即使目前歌詞沒有逐字資訊,仍強制模擬逐字效果
-
-
- 強制啟用逐字歌詞效果
-
渲染畫面播放速率
@@ -1575,4 +1569,13 @@
使用指南
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/AboutControlViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/AboutControlViewModel.cs
index f0d8e9a..3a18653 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/AboutControlViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/AboutControlViewModel.cs
@@ -2,27 +2,35 @@
using BetterLyrics.WinUI3.Helper.BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Hooks;
using BetterLyrics.WinUI3.Models.Settings;
+using BetterLyrics.WinUI3.Services.LyricsCacheService;
using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
+using Microsoft.Data.Sqlite;
using Microsoft.UI.Xaml.Controls;
using System;
+using System.Collections.Generic;
using System.IO;
+using System.IO.Compression;
using System.Threading.Tasks;
+using Windows.Storage;
+using WinRT.Interop;
namespace BetterLyrics.WinUI3.ViewModels
{
public partial class AboutControlViewModel : BaseViewModel
{
private readonly ISettingsService _settingsService;
+ private readonly ILyricsCacheService _lyricsCacheService;
[ObservableProperty]
public partial AppSettings AppSettings { get; set; }
- public AboutControlViewModel(ISettingsService settingsService)
+ public AboutControlViewModel(ISettingsService settingsService, ILyricsCacheService lyricsCacheService)
{
_settingsService = settingsService;
+ _lyricsCacheService = lyricsCacheService;
AppSettings = _settingsService.AppSettings;
}
@@ -47,18 +55,34 @@ namespace BetterLyrics.WinUI3.ViewModels
[RelayCommand]
private async Task ImportSettingsAsync()
{
- var file = await PickerHelper.PickSingleFileAsync([".json"]);
+ var file = await PickerHelper.PickSingleFileAsync([".zip"]);
if (file != null)
{
- var succeed = _settingsService.ImportSettings(file.Path);
- if (succeed)
+ try
{
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
+ SqliteConnection.ClearAllPools();
+
+ string tempExtractPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
+ Directory.CreateDirectory(tempExtractPath);
+
+ using (var stream = await file.OpenStreamForReadAsync())
+ {
+ ZipFile.ExtractToDirectory(stream, tempExtractPath);
+ }
+
+ DirectoryHelper.CopyDirectory(tempExtractPath, PathHelper.LocalFolder, true);
+
+ Directory.Delete(tempExtractPath, true);
+
WindowHook.RestartApp();
}
- else
+ catch (Exception ex)
{
- ToastHelper.ShowToast("ImportSettingsFailed", null, InfoBarSeverity.Error);
+ ToastHelper.ShowToast("ImportSettingsFailed", ex.Message, InfoBarSeverity.Error);
}
}
}
@@ -66,31 +90,49 @@ namespace BetterLyrics.WinUI3.ViewModels
[RelayCommand]
private async Task ExportSettingsAsync()
{
- var folder = await PickerHelper.PickSingleFolderAsync();
-
- if (folder != null)
+ try
{
- _settingsService.ExportSettings(folder.Path);
+ var suggestedFileName = $"{Constants.App.AppName}_{_settingsService.AppSettings.Version}_{DateTime.Now:yyyyMMdd_HHmmss}";
+ IDictionary> fileTypeChoices = new Dictionary>()
+ {
+ { "Zip Archive", new List() { ".zip" } }
+ };
+
+ var destinationFile = await PickerHelper.PickSaveFileAsync(fileTypeChoices, suggestedFileName);
+ if (destinationFile == null) return;
+
+ string tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
+ Directory.CreateDirectory(tempDir);
+
+ DirectoryHelper.CopyDirectory(PathHelper.LocalFolder, tempDir, true);
+
+ string tempZipPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".zip");
+
+ ZipFile.CreateFromDirectory(tempDir, tempZipPath);
+
+ using (var sourceStream = File.OpenRead(tempZipPath))
+ using (var destStream = await destinationFile.OpenStreamForWriteAsync())
+ {
+ sourceStream.CopyTo(destStream);
+ destStream.SetLength(sourceStream.Length);
+ }
+
+ Directory.Delete(tempDir, true);
+ File.Delete(tempZipPath);
+
ToastHelper.ShowToast("ExportSettingsSuccess", null, InfoBarSeverity.Success);
}
+ catch (Exception ex)
+ {
+ ToastHelper.ShowToast("Error", ex.Message, InfoBarSeverity.Error);
+ }
}
[RelayCommand]
- private async Task ExportPlayHistoryAsync()
+ private async Task ClearCacheFilesAsync()
{
- var folder = await PickerHelper.PickSingleFolderAsync();
+ await _lyricsCacheService.ClearCacheAsync();
- if (folder != null)
- {
- var dest = Path.Combine(folder.Path, $"BetterLyrics_Play_History_Export_{DateTime.Now:yyyyMMdd_HHmmss}.db");
- await FileHelper.CopyFileAsync(PathHelper.PlayHistoryPath, dest);
- ToastHelper.ShowToast("ExportSettingsSuccess", null, InfoBarSeverity.Success);
- }
- }
-
- [RelayCommand]
- private void ClearCacheFiles()
- {
DirectoryHelper.DeleteAllFiles(PathHelper.LogDirectory);
DirectoryHelper.DeleteAllFiles(PathHelper.LyricsCacheDirectory);
DirectoryHelper.DeleteAllFiles(PathHelper.iTunesAlbumArtCacheDirectory);