diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
index daa7392..67117f8 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
@@ -77,6 +77,7 @@
+
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml
index f43da8c..19b54c8 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PlaybackSettingsControl.xaml
@@ -345,8 +345,8 @@
@@ -356,8 +356,8 @@
Value="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.MatchPercentage, Mode=OneWay}" />
+ Link="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.SelfPath, TargetNullValue=N/A, Mode=OneWay, Converter={StaticResource UriStringToDecodedAbsoluteUri}}"
+ ToolTipService.ToolTip="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.SelfPath, TargetNullValue=N/A, Mode=OneWay, Converter={StaticResource UriStringToDecodedAbsoluteUri}}" />
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/StatsDashboardControl.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/StatsDashboardControl.xaml
index 635d9be..ed865e0 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/StatsDashboardControl.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/StatsDashboardControl.xaml
@@ -235,145 +235,132 @@
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
@@ -385,7 +372,6 @@
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Command="{x:Bind ViewModel.GenerateTestDataCommand}"
- Content="Generate test data"
- Visibility="Collapsed" />
+ Content="Generate test data" />
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/UriStringToDecodedAbsoluteUri.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/UriStringToDecodedAbsoluteUri.cs
new file mode 100644
index 0000000..1f2ad98
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/UriStringToDecodedAbsoluteUri.cs
@@ -0,0 +1,25 @@
+using BetterLyrics.WinUI3.Extensions;
+using Microsoft.UI.Xaml.Data;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BetterLyrics.WinUI3.Converter
+{
+ public partial class UriStringToDecodedAbsoluteUri : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ if (value is string uriString)
+ {
+ return uriString.ToDecodedAbsoluteUri();
+ }
+ return "";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/StringExtensions.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/StringExtensions.cs
index d3d0c77..aae5ca8 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/StringExtensions.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/StringExtensions.cs
@@ -1,4 +1,5 @@
using BetterLyrics.WinUI3.Enums;
+using System;
using System.Linq;
namespace BetterLyrics.WinUI3.Extensions
@@ -75,6 +76,18 @@ namespace BetterLyrics.WinUI3.Extensions
return null;
}
}
+
+ public string ToDecodedAbsoluteUri()
+ {
+ if (string.IsNullOrEmpty(str)) return "";
+ try
+ {
+ var u = new Uri(str);
+ return u.IsFile ? u.LocalPath : System.Net.WebUtility.UrlDecode(u.AbsoluteUri);
+ }
+ catch { return str; }
+ }
+
}
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs
index 218ea18..fca5826 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs
@@ -81,5 +81,6 @@ namespace BetterLyrics.WinUI3.Helper
Directory.CreateDirectory(iTunesAlbumArtCacheDirectory);
Directory.CreateDirectory(LocalAlbumArtCacheDirectory);
}
+
}
}
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/ExtendedTrack.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/ExtendedTrack.cs
index 0b554d3..ead4430 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/ExtendedTrack.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/ExtendedTrack.cs
@@ -10,20 +10,6 @@ namespace BetterLyrics.WinUI3.Models
{
public string Uri { get; private set; } = "";
- public string DecodedAbsoluteUri
- {
- get
- {
- if (string.IsNullOrEmpty(Uri)) return "";
- try
- {
- var u = new Uri(Uri);
- return u.IsFile ? u.LocalPath : System.Net.WebUtility.UrlDecode(u.AbsoluteUri);
- }
- catch { return Uri; }
- }
- }
-
public string? RawLyrics { get; set; }
public string? LocalAlbumArtPath { get; set; }
public byte[]? AlbumArtByteArray { get; set; }
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsSearchResult.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsSearchResult.cs
index 37fdd74..141b49a 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsSearchResult.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsSearchResult.cs
@@ -34,20 +34,6 @@ namespace BetterLyrics.WinUI3.Models
public string? SelfPath { get; set; }
- [JsonIgnore] public string DecodedAbsoluteUri
- {
- get
- {
- if (string.IsNullOrEmpty(SelfPath)) return "";
- try
- {
- var u = new Uri(SelfPath);
- return u.IsFile ? u.LocalPath : System.Net.WebUtility.UrlDecode(u.AbsoluteUri);
- }
- catch { return SelfPath; }
- }
- }
-
[JsonIgnore] public bool IsFound => !string.IsNullOrEmpty(Raw);
[JsonIgnore] public LyricsSearchProvider? ProviderIfFound => IsFound ? Provider : null;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryPageViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryPageViewModel.cs
index 72094ed..0cd64a2 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryPageViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryPageViewModel.cs
@@ -149,7 +149,7 @@ namespace BetterLyrics.WinUI3.ViewModels
private void TrackPlayingQueue_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
- AppSettings.MusicGallerySettings.PlayQueuePaths = [.. TrackPlayingQueue.Select(x => x.Track.DecodedAbsoluteUri)];
+ AppSettings.MusicGallerySettings.PlayQueuePaths = [.. TrackPlayingQueue.Select(x => x.Track.Uri.ToDecodedAbsoluteUri())];
}
private void LocalMediaFolders_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
@@ -344,7 +344,7 @@ namespace BetterLyrics.WinUI3.ViewModels
if (File.Exists(path))
{
var m3uFileContent = File.ReadAllText(path);
- _middleTracks = _allTracks.Where(t => m3uFileContent.Contains(t.DecodedAbsoluteUri)).ToList();
+ _middleTracks = _allTracks.Where(t => m3uFileContent.Contains(t.Uri.ToDecodedAbsoluteUri())).ToList();
}
else
{
@@ -496,7 +496,7 @@ namespace BetterLyrics.WinUI3.ViewModels
if (targetFolder == null)
{
- throw new FileNotFoundException(null, PlayingTrack.DecodedAbsoluteUri);
+ throw new FileNotFoundException(null, PlayingTrack.Uri.ToDecodedAbsoluteUri());
}
_currentProvider = targetFolder.CreateFileSystem();
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/StatsDashboardControlViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/StatsDashboardControlViewModel.cs
index ad343a6..2e4ad19 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/StatsDashboardControlViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/StatsDashboardControlViewModel.cs
@@ -38,8 +38,8 @@ namespace BetterLyrics.WinUI3.ViewModels
// 时间筛选
[ObservableProperty] public partial StatsRange SelectedTimeRange { get; set; }
[ObservableProperty] public partial bool IsCustomRangeSelected { get; set; }
- [ObservableProperty] public partial DateTimeOffset CustomStartDate { get; set; }
- [ObservableProperty] public partial DateTimeOffset CustomEndDate { get; set; } = DateTimeOffset.Now;
+ [ObservableProperty] public partial DateTimeOffset? CustomStartDate { get; set; }
+ [ObservableProperty] public partial DateTimeOffset? CustomEndDate { get; set; }
// 顶部基础数据
[ObservableProperty] public partial TimeSpan TotalDuration { get; set; }
@@ -54,8 +54,6 @@ namespace BetterLyrics.WinUI3.ViewModels
// 歌手
[ObservableProperty] public partial ObservableCollection TopArtists { get; set; } = new();
- [ObservableProperty] public partial ObservableCollection ArtistSeriesValues { get; set; } = new();
- public Func ArtistsLabelsFormatter { get; set; }
// 播放源
[ObservableProperty] public partial ObservableCollection SourceSeries { get; set; } = new();
@@ -71,11 +69,6 @@ namespace BetterLyrics.WinUI3.ViewModels
_localizedTimesValue = _localizationService.GetLocalizedString("StatsDashboardControlTimes");
- ArtistsLabelsFormatter = (point) =>
- {
- return TopArtists.ElementAtOrDefault(point.Index)?.Artist ?? "N/A";
- };
-
SelectedTimeRange = StatsRange.Today;
CustomStartDate = DateTimeOffset.Now.AddDays(-7);
@@ -85,13 +78,10 @@ namespace BetterLyrics.WinUI3.ViewModels
async partial void OnSelectedTimeRangeChanged(StatsRange value)
{
IsCustomRangeSelected = value == StatsRange.Custom;
- if (!IsCustomRangeSelected)
- {
- await LoadDataAsync();
- }
+ await LoadDataAsync();
}
- async partial void OnCustomEndDateChanged(DateTimeOffset value) => await LoadDataAsync();
- async partial void OnCustomStartDateChanged(DateTimeOffset value) => await LoadDataAsync();
+ async partial void OnCustomEndDateChanged(DateTimeOffset? value) => await LoadDataAsync();
+ async partial void OnCustomStartDateChanged(DateTimeOffset? value) => await LoadDataAsync();
private void ProcessHourlyStats(List logs)
{
@@ -117,16 +107,7 @@ namespace BetterLyrics.WinUI3.ViewModels
HourlySeriesValues = [.. hourCounts];
}
- private void ProcessArtistStats(List artists)
- {
- if (artists == null || !artists.Any())
- {
- ArtistSeriesValues = new();
- return;
- }
- ArtistSeriesValues = [.. artists.Select(x => x.PlayCount)];
- }
private void UpdatePlayerStats(List stats)
{
SourceSeries = new();
@@ -152,12 +133,11 @@ namespace BetterLyrics.WinUI3.ViewModels
})];
}
- private (DateTime Start, DateTime End) CalculateDateRange()
+ private (DateTime? Start, DateTime? End) CalculateDateRange()
{
- // 如果是自定义,直接返回 Picker 的值 (转为 UTC)
if (IsCustomRangeSelected)
{
- return (CustomStartDate.UtcDateTime, CustomEndDate.UtcDateTime);
+ return (CustomStartDate?.UtcDateTime, CustomEndDate?.UtcDateTime);
}
DateTime nowLocal = DateTime.Now;
@@ -166,8 +146,8 @@ namespace BetterLyrics.WinUI3.ViewModels
switch (SelectedTimeRange)
{
case StatsRange.Today:
- startLocal = nowLocal.Date.AddDays(-1);
- return (startLocal.ToUniversalTime(), nowLocal.Date.ToUniversalTime());
+ startLocal = new DateTime(nowLocal.Year, nowLocal.Month, nowLocal.Day);
+ break;
case StatsRange.ThisWeek:
int dayOfWeek = (int)nowLocal.DayOfWeek;
if (dayOfWeek == 0) dayOfWeek = 7;
@@ -198,11 +178,16 @@ namespace BetterLyrics.WinUI3.ViewModels
{
var (start, end) = CalculateDateRange();
- var durationTask = _playHistoryService.GetTotalListeningDurationAsync(start, end);
- var logsTask = _playHistoryService.GetLogsByDateRangeAsync(start, end);
- var topSongsTask = _playHistoryService.GetTopSongsAsync(start, end, 10);
- var topArtistsTask = _playHistoryService.GetTopArtistsAsync(start, end, 10);
- var playersTask = _playHistoryService.GetPlayerDistributionAsync(start, end);
+ if (start == null || end == null)
+ {
+ start = end = DateTime.Now.ToUniversalTime();
+ }
+
+ var durationTask = _playHistoryService.GetTotalListeningDurationAsync(start.Value, end.Value);
+ var logsTask = _playHistoryService.GetLogsByDateRangeAsync(start.Value, end.Value);
+ var topSongsTask = _playHistoryService.GetTopSongsAsync(start.Value, end.Value, 10);
+ var topArtistsTask = _playHistoryService.GetTopArtistsAsync(start.Value, end.Value, 10);
+ var playersTask = _playHistoryService.GetPlayerDistributionAsync(start.Value, end.Value);
await Task.WhenAll(durationTask, logsTask, topSongsTask, topArtistsTask, playersTask);
@@ -216,7 +201,6 @@ namespace BetterLyrics.WinUI3.ViewModels
UpdatePlayerStats(pStats);
TopArtists = [.. await topArtistsTask];
- ProcessArtistStats(TopArtists.ToList());
ProcessHourlyStats(logs);
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml
index f0414b2..5f8fc15 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml
@@ -169,7 +169,12 @@
x:Uid="MusicGalleryPageFolder"
Margin="1,4,0,6"
Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
-
+
-
+
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml.cs
index 04dcd85..7f71d50 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml.cs
@@ -72,7 +72,7 @@ namespace BetterLyrics.WinUI3.Views
private async void SongPathHyperlinkButton_Click(object sender, RoutedEventArgs e)
{
- await LauncherHelper.SelectAndShowFile(((ExtendedTrack)((HyperlinkButton)sender).DataContext).DecodedAbsoluteUri);
+ await LauncherHelper.SelectAndShowFile(((ExtendedTrack)((HyperlinkButton)sender).DataContext).Uri.ToDecodedAbsoluteUri());
}
private async void PlayingQueueListVireItemGrid_Tapped(object sender, TappedRoutedEventArgs e)
@@ -280,7 +280,7 @@ namespace BetterLyrics.WinUI3.Views
if (File.Exists(path))
{
var content = File.ReadAllText(path);
- foreach (var item in ViewModel.SelectedTracks.Select(x => x.DecodedAbsoluteUri).ToList())
+ foreach (var item in ViewModel.SelectedTracks.Select(x => x.Uri.ToDecodedAbsoluteUri()).ToList())
{
if (!content.Contains(item))
{