mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-12 10:54:55 +08:00
fix: stats dashboard data selection issue
This commit is contained in:
@@ -77,6 +77,7 @@
|
||||
<converter:FileSourceTypeToIconConverter x:Key="FileSourceTypeToIconConverter" />
|
||||
<converter:PathToImageConverter x:Key="PathToImageConverter" />
|
||||
<converter:DoubleToDecimalConverter x:Key="DoubleToDecimalConverter" />
|
||||
<converter:UriStringToDecodedAbsoluteUri x:Key="UriStringToDecodedAbsoluteUri" />
|
||||
|
||||
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
||||
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
|
||||
|
||||
@@ -345,8 +345,8 @@
|
||||
<local:PropertyRow x:Uid="LyricsPageLanguageCode" Value="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsData.LanguageCode, TargetNullValue=N/A, Mode=OneWay, Converter={StaticResource LanguageCodeToDisplayedNameConverter}}" />
|
||||
<local:PropertyRow
|
||||
x:Uid="LyricsPageLyricsProviderPrefix"
|
||||
Link="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.Reference, Mode=OneWay}"
|
||||
ToolTipService.ToolTip="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.Reference, TargetNullValue=N/A, Mode=OneWay}"
|
||||
Link="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.Reference, Mode=OneWay, Converter={StaticResource UriStringToDecodedAbsoluteUri}}"
|
||||
ToolTipService.ToolTip="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.Reference, TargetNullValue=N/A, Mode=OneWay, Converter={StaticResource UriStringToDecodedAbsoluteUri}}"
|
||||
Value="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.ProviderIfFound, Mode=OneWay, Converter={StaticResource LyricsSearchProviderToDisplayNameConverter}}" />
|
||||
<local:PropertyRow x:Uid="LyricsPageTransliterationProviderPrefix" Value="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.TransliterationProvider, Mode=OneWay, Converter={StaticResource TransliterationSearchProviderToDisplayNameConverter}}" />
|
||||
<local:PropertyRow x:Uid="LyricsPageTranslationProviderPrefix" Value="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.TranslationProvider, Mode=OneWay, Converter={StaticResource TranslationSearchProviderToDisplayNameConverter}}" />
|
||||
@@ -356,8 +356,8 @@
|
||||
Value="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.MatchPercentage, Mode=OneWay}" />
|
||||
<local:PropertyRow
|
||||
x:Uid="LyricsPageCachePath"
|
||||
Link="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.DecodedAbsoluteUri, TargetNullValue=N/A, Mode=OneWay}"
|
||||
ToolTipService.ToolTip="{x:Bind ViewModel.MediaSessionsService.CurrentLyricsSearchResult.DecodedAbsoluteUri, TargetNullValue=N/A, 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}}" />
|
||||
</StackPanel>
|
||||
</Expander>
|
||||
|
||||
|
||||
@@ -235,56 +235,113 @@
|
||||
|
||||
<!-- Top artists -->
|
||||
<Border Grid.Column="0" Style="{StaticResource StatsCardStyle}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition MinHeight="250" />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
x:Uid="StatsDashboardControlTopArtists"
|
||||
Margin="0,0,0,12"
|
||||
Style="{ThemeResource SubtitleTextBlockStyle}" />
|
||||
|
||||
<lvc:CartesianChart
|
||||
Grid.Row="1"
|
||||
Margin="0,8,0,0"
|
||||
Background="Transparent">
|
||||
|
||||
<lvc:CartesianChart.XAxes>
|
||||
<lvc:AxesCollection>
|
||||
<lvc:XamlAxis x:Uid="StatsDashboardControlTrackCountAxis" NameTextSize="{StaticResource BodyTextBlockFontSize}" />
|
||||
</lvc:AxesCollection>
|
||||
</lvc:CartesianChart.XAxes>
|
||||
|
||||
<lvc:CartesianChart.YAxes>
|
||||
<lvc:AxesCollection>
|
||||
<lvc:XamlAxis IsInverted="True" IsVisible="False" />
|
||||
</lvc:AxesCollection>
|
||||
</lvc:CartesianChart.YAxes>
|
||||
|
||||
<lvc:CartesianChart.Series>
|
||||
<lvc:SeriesCollection>
|
||||
<lvc:XamlRowSeries
|
||||
Padding="4"
|
||||
DataLabelsFormatter="{x:Bind ViewModel.ArtistsLabelsFormatter}"
|
||||
DataLabelsSize="{StaticResource BodyTextBlockFontSize}"
|
||||
Rx="4"
|
||||
Ry="4"
|
||||
ShowDataLabels="True"
|
||||
Values="{x:Bind ViewModel.ArtistSeriesValues, Mode=OneWay}" />
|
||||
</lvc:SeriesCollection>
|
||||
</lvc:CartesianChart.Series>
|
||||
|
||||
</lvc:CartesianChart>
|
||||
|
||||
<ItemsControl ItemsSource="{x:Bind ViewModel.TopArtists, Mode=OneWay}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="statsmodels:ArtistPlayCount">
|
||||
<Grid Margin="0,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<PersonPicture
|
||||
Width="32"
|
||||
Height="32"
|
||||
DisplayName="{x:Bind Artist}" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Style="{ThemeResource BodyStrongTextBlockStyle}"
|
||||
Text="{x:Bind Artist}" />
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="SemiBold">
|
||||
<Run Text="{x:Bind PlayCount}" />
|
||||
<Run
|
||||
x:Uid="StatsDashboardControlTrackCountText"
|
||||
FontSize="10"
|
||||
FontWeight="Normal"
|
||||
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 播放源分布 -->
|
||||
<!-- Top tracks -->
|
||||
<Border
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,12"
|
||||
Style="{StaticResource StatsCardStyle}">
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
x:Uid="StatsDashboardControlTopSongs"
|
||||
Margin="0,0,0,12"
|
||||
Style="{ThemeResource SubtitleTextBlockStyle}" />
|
||||
<ItemsControl ItemsSource="{x:Bind ViewModel.TopSongs, Mode=OneWay}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="statsmodels:SongPlayCount">
|
||||
<Grid Margin="0,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid
|
||||
Width="40"
|
||||
Height="40"
|
||||
Margin="0,0,12,0"
|
||||
Background="{ThemeResource LayerFillColorAltBrush}"
|
||||
CornerRadius="4">
|
||||
<FontIcon
|
||||
FontSize="16"
|
||||
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}"
|
||||
Glyph="" />
|
||||
</Grid>
|
||||
|
||||
<StackPanel Grid.Column="1" VerticalAlignment="Center">
|
||||
<TextBlock Style="{ThemeResource BodyStrongTextBlockStyle}" Text="{x:Bind Title}" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}"
|
||||
Style="{ThemeResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Artist}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="SemiBold">
|
||||
<Run Text="{x:Bind PlayCount}" />
|
||||
<Run
|
||||
x:Uid="StatsDashboardControlTrackCountText"
|
||||
FontSize="10"
|
||||
FontWeight="Normal"
|
||||
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
|
||||
<!-- 播放源分布 -->
|
||||
<Border
|
||||
Grid.Row="3"
|
||||
Margin="0,0,0,20"
|
||||
Style="{StaticResource StatsCardStyle}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
@@ -297,85 +354,15 @@
|
||||
|
||||
<lvc:PieChart
|
||||
Grid.Row="1"
|
||||
MinHeight="160"
|
||||
MinHeight="250"
|
||||
Background="Transparent"
|
||||
LegendPosition="Right"
|
||||
LegendPosition="Bottom"
|
||||
LegendTextSize="{StaticResource BodyTextBlockFontSize}"
|
||||
Series="{x:Bind ViewModel.SourceSeries, Mode=OneWay}"
|
||||
TooltipPosition="Center" />
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- Top tracks -->
|
||||
<Border
|
||||
Grid.Row="3"
|
||||
Margin="0,0,0,20"
|
||||
Style="{StaticResource StatsCardStyle}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
x:Uid="StatsDashboardControlTopSongs"
|
||||
Margin="0,0,0,18"
|
||||
Style="{ThemeResource SubtitleTextBlockStyle}" />
|
||||
<dev:OpacityMaskView Grid.Row="1" Margin="-20,0">
|
||||
<dev:OpacityMaskView.OpacityMask>
|
||||
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
|
||||
<GradientStop Offset="0" Color="Transparent" />
|
||||
<GradientStop Offset="0.02" Color="#FFFFFFFF" />
|
||||
<GradientStop Offset="0.98" Color="#FFFFFFFF" />
|
||||
<GradientStop Offset="1" Color="Transparent" />
|
||||
</LinearGradientBrush>
|
||||
</dev:OpacityMaskView.OpacityMask>
|
||||
<ListView
|
||||
Padding="20,0"
|
||||
ItemContainerStyle="{StaticResource ListViewStretchedItemContainerStyle}"
|
||||
ItemsSource="{x:Bind ViewModel.TopSongs, Mode=OneWay}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
|
||||
ScrollViewer.HorizontalScrollMode="Enabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollMode="Disabled"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<ItemsStackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListView.ItemsPanel>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="statsmodels:SongPlayCount">
|
||||
<Grid
|
||||
MinWidth="200"
|
||||
Margin="6,0"
|
||||
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4">
|
||||
<StackPanel Margin="20">
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
Style="{StaticResource SubtitleTextBlockStyle}"
|
||||
Text="{x:Bind Title}"
|
||||
TextWrapping="Wrap" />
|
||||
<RichTextBlock>
|
||||
<Paragraph>
|
||||
<Run Text="{x:Bind Artist}" />
|
||||
<Run Text="·" />
|
||||
<Run Text="{x:Bind PlayCount}" />
|
||||
<Run x:Uid="StatsDashboardControlTrackCountText" />
|
||||
</Paragraph>
|
||||
</RichTextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</dev:OpacityMaskView>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
@@ -385,7 +372,6 @@
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Command="{x:Bind ViewModel.GenerateTestDataCommand}"
|
||||
Content="Generate test data"
|
||||
Visibility="Collapsed" />
|
||||
Content="Generate test data" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,5 +81,6 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
Directory.CreateDirectory(iTunesAlbumArtCacheDirectory);
|
||||
Directory.CreateDirectory(LocalAlbumArtCacheDirectory);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<ArtistPlayCount> TopArtists { get; set; } = new();
|
||||
[ObservableProperty] public partial ObservableCollection<int> ArtistSeriesValues { get; set; } = new();
|
||||
public Func<ChartPoint, string> ArtistsLabelsFormatter { get; set; }
|
||||
|
||||
// 播放源
|
||||
[ObservableProperty] public partial ObservableCollection<ISeries> 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();
|
||||
}
|
||||
}
|
||||
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<PlayHistoryItem> logs)
|
||||
{
|
||||
@@ -117,16 +107,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
HourlySeriesValues = [.. hourCounts];
|
||||
}
|
||||
private void ProcessArtistStats(List<ArtistPlayCount> artists)
|
||||
{
|
||||
if (artists == null || !artists.Any())
|
||||
{
|
||||
ArtistSeriesValues = new();
|
||||
return;
|
||||
}
|
||||
|
||||
ArtistSeriesValues = [.. artists.Select(x => x.PlayCount)];
|
||||
}
|
||||
private void UpdatePlayerStats(List<PlayerStats> 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);
|
||||
}
|
||||
|
||||
@@ -169,7 +169,12 @@
|
||||
x:Uid="MusicGalleryPageFolder"
|
||||
Margin="1,4,0,6"
|
||||
Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<Button Command="{x:Bind ViewModel.OpenMediaSettingsCommand}" Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, FontSize=12, Glyph=}" Style="{StaticResource GhostButtonStyle}" />
|
||||
<Button
|
||||
Command="{x:Bind ViewModel.OpenMediaSettingsCommand}"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<TreeView
|
||||
@@ -244,7 +249,10 @@
|
||||
<uc:PropertyRow x:Uid="MusicGalleryPageFileInfoBitDepth" Value="{x:Bind ViewModel.TrackRightTapped.BitDepth, Mode=OneWay}" />
|
||||
<uc:PropertyRow x:Uid="MusicGalleryPageFileInfoFormat" Value="{x:Bind ViewModel.TrackRightTapped.AudioFormatName, Mode=OneWay}" />
|
||||
<uc:PropertyRow x:Uid="MusicGalleryPageFileInfoEncoder" Value="{x:Bind ViewModel.TrackRightTapped.Encoder, Mode=OneWay}" />
|
||||
<uc:PropertyRow x:Uid="MusicGalleryPageFileInfoPath" Value="{x:Bind ViewModel.TrackRightTapped.DecodedAbsoluteUri, Mode=OneWay}" />
|
||||
<uc:PropertyRow
|
||||
x:Uid="MusicGalleryPageFileInfoPath"
|
||||
Link="{x:Bind ViewModel.TrackRightTapped.Uri, Mode=OneWay, Converter={StaticResource UriStringToDecodedAbsoluteUri}}"
|
||||
Value="{x:Bind ViewModel.TrackRightTapped.Uri, Mode=OneWay, Converter={StaticResource UriStringToDecodedAbsoluteUri}}" />
|
||||
<uc:PropertyRow x:Uid="MusicGalleryPageFileInfoLyrics" Value="{x:Bind ViewModel.TrackRightTapped.RawLyrics, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user