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}" /> -