This commit is contained in:
Zhe Fang
2025-06-10 22:37:32 -04:00
parent 81651abfec
commit 5b71f44bf3
12 changed files with 88 additions and 104 deletions

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;

View File

@@ -3,9 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BetterLyrics.WinUI3.Models;
using CommunityToolkit.Mvvm.Messaging.Messages;
namespace BetterLyrics.WinUI3.Messages
{
public class ReFindSongInfoRequestedMessage() : ValueChangedMessage<object?>(null) { }
public class DisplayTypeChangedMessage(DisplayType value)
: ValueChangedMessage<DisplayType>(value) { }
}

View File

@@ -8,7 +8,6 @@ using BetterLyrics.WinUI3.Messages;
using BetterLyrics.WinUI3.Models;
using BetterLyrics.WinUI3.ViewModels;
using CommunityToolkit.Mvvm.Messaging;
using DevWinUI;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Effects;
@@ -66,6 +65,8 @@ namespace BetterLyrics.WinUI3.Rendering
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
private DisplayType _displayType = DisplayType.PlaceholderOnly;
public LyricsRenderer(LyricsViewModel settingsViewModel)
{
_viewModel = settingsViewModel;
@@ -124,6 +125,14 @@ namespace BetterLyrics.WinUI3.Rendering
await ReLayoutAsync();
}
);
WeakReferenceMessenger.Default.Register<LyricsRenderer, DisplayTypeChangedMessage>(
this,
(r, m) =>
{
_displayType = m.Value;
}
);
}
public void AddElapsedTime(TimeSpan elapsedTime)
@@ -310,7 +319,8 @@ namespace BetterLyrics.WinUI3.Rendering
using var lyrics = new CanvasCommandList(control);
using (var lyricsDs = lyrics.CreateDrawingSession())
{
DrawLyrics(control, lyricsDs);
if (_displayType == DisplayType.LyricsOnly || _displayType == DisplayType.SplitView)
DrawLyrics(control, lyricsDs);
}
using var glowedLyrics = new CanvasCommandList(control);

View File

@@ -105,6 +105,11 @@ namespace BetterLyrics.WinUI3.Services.Database
{
Track track = new(found.Path);
initSongInfo.ParseLyrics(track);
if (initSongInfo.LyricsLines != null)
{
initSongInfo.FilesUsed ??= [];
initSongInfo.FilesUsed.Add(found.Path ?? string.Empty);
}
// Find lyrics
if (initSongInfo.LyricsLines == null && found?.Path?.EndsWith(".lrc") == true)
@@ -136,6 +141,8 @@ namespace BetterLyrics.WinUI3.Services.Database
if (track.EmbeddedPictures.Count > 0)
{
initSongInfo.AlbumArt = track.EmbeddedPictures[0].PictureData;
initSongInfo.FilesUsed ??= [];
initSongInfo.FilesUsed.Add(found.Path);
}
}
}

View File

@@ -7,5 +7,8 @@ using BetterLyrics.WinUI3.Models;
namespace BetterLyrics.WinUI3.Services.Playback
{
public interface IPlaybackService { }
public interface IPlaybackService
{
void ReSendingMessages();
}
}

View File

@@ -41,6 +41,14 @@ namespace BetterLyrics.WinUI3.Services.Playback
SessionManager_CurrentSessionChanged(_sessionManager, null);
}
public void ReSendingMessages()
{
// Re-send messages to update UI
CurrentSession_MediaPropertiesChanged(_currentSession, null);
CurrentSession_PlaybackInfoChanged(_currentSession, null);
CurrentSession_TimelinePropertiesChanged(_currentSession, null);
}
/// <summary>
/// Note: Non-UI thread
/// </summary>
@@ -103,9 +111,7 @@ namespace BetterLyrics.WinUI3.Services.Playback
CurrentSession_TimelinePropertiesChanged;
}
CurrentSession_MediaPropertiesChanged(_currentSession, null);
CurrentSession_PlaybackInfoChanged(_currentSession, null);
CurrentSession_TimelinePropertiesChanged(_currentSession, null);
ReSendingMessages();
}
/// <summary>

View File

@@ -372,7 +372,7 @@
<data name="BaseWindowHostInfoBarCheckBox.Content" xml:space="preserve">
<value>Do not show this message again</value>
</data>
<data name="MainPageNoLocalFilesMatched" xml:space="preserve">
<data name="MainPageNoLocalFilesMatched.Text" xml:space="preserve">
<value>No local files matched</value>
</data>
<data name="MainPageAlbumArtOnly.Content" xml:space="preserve">

View File

@@ -372,7 +372,7 @@
<data name="BaseWindowHostInfoBarCheckBox.Content" xml:space="preserve">
<value>不再显示此消息</value>
</data>
<data name="MainPageNoLocalFilesMatched" xml:space="preserve">
<data name="MainPageNoLocalFilesMatched.Text" xml:space="preserve">
<value>找不到匹配的本地文件</value>
</data>
<data name="MainPageAlbumArtOnly.Content" xml:space="preserve">

View File

@@ -372,7 +372,7 @@
<data name="BaseWindowHostInfoBarCheckBox.Content" xml:space="preserve">
<value>不再顯示此訊息</value>
</data>
<data name="MainPageNoLocalFilesMatched" xml:space="preserve">
<data name="MainPageNoLocalFilesMatched.Text" xml:space="preserve">
<value>找不到匹配的本地文件</value>
</data>
<data name="MainPageAlbumArtOnly.Content" xml:space="preserve">

View File

@@ -25,12 +25,6 @@ namespace BetterLyrics.WinUI3.ViewModels
{
public partial class MainViewModel : ObservableObject
{
[ObservableProperty]
private ObservableCollection<bool> _isDisplayTypeEnabled =
[
.. Enumerable.Repeat(false, Enum.GetValues<DisplayType>().Length),
];
[ObservableProperty]
private BitmapImage? _coverImage;
@@ -38,9 +32,9 @@ namespace BetterLyrics.WinUI3.ViewModels
private SongInfo? _songInfo = null;
[ObservableProperty]
private int _displayType = (int)Models.DisplayType.PlaceholderOnly;
private DisplayType _displayType = DisplayType.PlaceholderOnly;
private int? _preferredDisplayType = 2;
private DisplayType? _preferredDisplayType = DisplayType.SplitView;
[ObservableProperty]
private bool _aboutToUpdateUI;
@@ -48,9 +42,6 @@ namespace BetterLyrics.WinUI3.ViewModels
[ObservableProperty]
private bool _isPlaying = false;
[ObservableProperty]
private ObservableCollection<string> _matchedLocalFilePath = [];
private bool _isImmersiveMode = false;
public bool IsImmersiveMode
{
@@ -75,12 +66,8 @@ namespace BetterLyrics.WinUI3.ViewModels
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
private readonly IDatabaseService _databaseService;
public MainViewModel(IPlaybackService playbackService, IDatabaseService databaseService)
public MainViewModel(IPlaybackService playbackService)
{
_databaseService = databaseService;
WeakReferenceMessenger.Default.Register<MainViewModel, PlayingStatusChangedMessage>(
this,
(r, m) =>
@@ -108,19 +95,6 @@ namespace BetterLyrics.WinUI3.ViewModels
);
}
);
WeakReferenceMessenger.Default.Register<MainViewModel, ReFindSongInfoRequestedMessage>(
this,
async (r, m) =>
{
if (SongInfo == null || SongInfo.Title == null || SongInfo.Artist == null)
return;
await UpdateSongInfoUI(
_databaseService.FindSongInfo(SongInfo, SongInfo.Title, SongInfo.Artist)
);
}
);
}
private async Task UpdateSongInfoUI(SongInfo? songInfo)
@@ -137,57 +111,21 @@ namespace BetterLyrics.WinUI3.ViewModels
? null
: await ImageHelper.GetBitmapImageFromBytesAsync(songInfo.AlbumArt);
IsDisplayTypeEnabled =
[
.. Enumerable.Repeat(false, Enum.GetValues<DisplayType>().Length),
];
if (songInfo == null)
{
IsDisplayTypeEnabled[(int)Models.DisplayType.PlaceholderOnly] = true;
DisplayType = (int)Models.DisplayType.PlaceholderOnly;
DisplayType = DisplayType.PlaceholderOnly;
}
else if (_preferredDisplayType is DisplayType preferredDisplayType)
{
DisplayType = preferredDisplayType;
}
else
{
if (songInfo.LyricsLines?.Count > 0)
{
IsDisplayTypeEnabled[(int)Models.DisplayType.LyricsOnly] = true;
}
if (songInfo.AlbumArt != null)
{
IsDisplayTypeEnabled[(int)Models.DisplayType.AlbumArtOnly] = true;
}
IsDisplayTypeEnabled[(int)Models.DisplayType.SplitView] =
IsDisplayTypeEnabled[(int)Models.DisplayType.LyricsOnly]
&& IsDisplayTypeEnabled[(int)Models.DisplayType.AlbumArtOnly];
// Set checked
if (
IsDisplayTypeEnabled[(int)Models.DisplayType.SplitView]
&& _preferredDisplayType == (int)Models.DisplayType.SplitView
)
{
DisplayType = (int)Models.DisplayType.SplitView;
}
else
{
if (
IsDisplayTypeEnabled[(int)Models.DisplayType.LyricsOnly]
&& _preferredDisplayType == (int)Models.DisplayType.LyricsOnly
)
{
DisplayType = (int)Models.DisplayType.LyricsOnly;
}
else if (
IsDisplayTypeEnabled[(int)Models.DisplayType.AlbumArtOnly]
&& _preferredDisplayType == (int)Models.DisplayType.AlbumArtOnly
)
{
DisplayType = (int)Models.DisplayType.AlbumArtOnly;
}
}
DisplayType = DisplayType.SplitView;
}
WeakReferenceMessenger.Default.Send(new DisplayTypeChangedMessage(DisplayType));
AboutToUpdateUI = false;
}
@@ -207,8 +145,9 @@ namespace BetterLyrics.WinUI3.ViewModels
private void OnDisplayTypeChanged(object value)
{
int index = Convert.ToInt32(value);
_preferredDisplayType = index;
DisplayType = index;
_preferredDisplayType = (DisplayType)index;
DisplayType = (DisplayType)index;
WeakReferenceMessenger.Default.Send(new DisplayTypeChangedMessage(DisplayType));
}
}
}

View File

@@ -85,13 +85,19 @@ namespace BetterLyrics.WinUI3.ViewModels
private readonly MediaPlayer _mediaPlayer = new();
private readonly IDatabaseService _databaseService;
private readonly IPlaybackService _playbackService;
public string Version => AppInfo.AppVersion;
public SettingsViewModel(IDatabaseService databaseService, ISettingsService settingsService)
public SettingsViewModel(
IDatabaseService databaseService,
ISettingsService settingsService,
IPlaybackService playbackService
)
: base(settingsService)
{
_databaseService = databaseService;
_playbackService = playbackService;
_musicLibraries =
[
@@ -109,7 +115,7 @@ namespace BetterLyrics.WinUI3.ViewModels
IsRebuildingLyricsIndexDatabase = true;
await _databaseService.RebuildDatabaseAsync(MusicLibraries);
IsRebuildingLyricsIndexDatabase = false;
WeakReferenceMessenger.Default.Send(new ReFindSongInfoRequestedMessage());
_playbackService.ReSendingMessages();
}
public async Task RemoveFolderAsync(string path)

View File

@@ -288,24 +288,21 @@
<Setter Property="CornerRadius" Value="8" />
</Style>
</Flyout.FlyoutPresenterStyle>
<RadioButtons MaxColumns="1" SelectedIndex="{x:Bind ViewModel.DisplayType, Mode=OneWay}">
<RadioButtons MaxColumns="1" SelectedIndex="{x:Bind ViewModel.DisplayType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}">
<RadioButton
x:Uid="MainPageAlbumArtOnly"
Command="{x:Bind ViewModel.DisplayTypeChangedCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Tag}"
IsEnabled="{x:Bind ViewModel.IsDisplayTypeEnabled[0], Mode=OneWay}"
Tag="0" />
<RadioButton
x:Uid="MainPageLyriscOnly"
Command="{x:Bind ViewModel.DisplayTypeChangedCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Tag}"
IsEnabled="{x:Bind ViewModel.IsDisplayTypeEnabled[1], Mode=OneWay}"
Tag="1" />
<RadioButton
x:Uid="MainPageSplitView"
Command="{x:Bind ViewModel.DisplayTypeChangedCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Tag}"
IsEnabled="{x:Bind ViewModel.IsDisplayTypeEnabled[2], Mode=OneWay}"
Tag="2" />
</RadioButtons>
</Flyout>
@@ -337,7 +334,10 @@
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="12">
<FontIcon FontFamily="Segoe Fluent Icons" Glyph="&#xF0E3;" />
<ListView ItemsSource="{x:Bind ViewModel.MatchedLocalFilePath, Mode=OneWay}" SelectionMode="None">
<ListView
x:Name="MatchedFilesListView"
ItemsSource="{x:Bind ViewModel.SongInfo.FilesUsed, Mode=OneWay}"
SelectionMode="None">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="VerticalContentAlignment" Value="Center" />
@@ -356,12 +356,15 @@
Click="OpenMatchedFileButton_Click"
Content="{ui:FontIcon Glyph=&#xE838;}"
Style="{StaticResource GhostButtonStyle}"
Tag="{Binding Mode=OneWay}"
Visibility="{Binding Converter={StaticResource MatchedLocalFilesPathToVisibilityConverter}, Mode=OneWay}" />
Tag="{Binding Mode=OneWay}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<TextBlock
x:Name="NoLocalFilesMatchedTextBlock"
x:Uid="MainPageNoLocalFilesMatched"
Visibility="Collapsed" />
</StackPanel>
</StackPanel>
</Flyout>
@@ -386,19 +389,19 @@
Target="{x:Bind SettingsButton}" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualStateGroup x:Name="LayoutStates">
<!-- Album art only -->
<VisualState x:Name="AlbumArtOnly">
<VisualState.StateTriggers>
<ui:CompareStateTrigger
Comparison="Equal"
Value="{x:Bind ViewModel.DisplayType, Mode=OneWay}"
Value="{x:Bind ViewModel.DisplayType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
To="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="SongInfoGrid.Opacity" Value="1" />
<Setter Target="LyricsGrid.Opacity" Value="0" />
<Setter Target="LyricsGrid.Opacity" Value="1" />
<Setter Target="SongInfoInnerGrid.(Grid.Column)" Value="0" />
<Setter Target="SongInfoInnerGrid.(Grid.ColumnSpan)" Value="3" />
<Setter Target="MainPageNoMusicPlayingTextBlock.Opacity" Value="0" />
@@ -410,7 +413,7 @@
<VisualState.StateTriggers>
<ui:CompareStateTrigger
Comparison="Equal"
Value="{x:Bind ViewModel.DisplayType, Mode=OneWay}"
Value="{x:Bind ViewModel.DisplayType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
To="1" />
</VisualState.StateTriggers>
<VisualState.Setters>
@@ -427,7 +430,7 @@
<VisualState.StateTriggers>
<ui:CompareStateTrigger
Comparison="Equal"
Value="{x:Bind ViewModel.DisplayType, Mode=OneWay}"
Value="{x:Bind ViewModel.DisplayType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
To="2" />
</VisualState.StateTriggers>
<VisualState.Setters>
@@ -446,7 +449,7 @@
<VisualState.StateTriggers>
<ui:CompareStateTrigger
Comparison="Equal"
Value="{x:Bind ViewModel.DisplayType, Mode=OneWay}"
Value="{x:Bind ViewModel.DisplayType, Mode=OneWay, Converter={StaticResource EnumToIntConverter}}"
To="3" />
</VisualState.StateTriggers>
<VisualState.Setters>
@@ -457,6 +460,18 @@
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FilesMatchStates">
<VisualState x:Name="Matched" />
<VisualState x:Name="NotMatched">
<VisualState.StateTriggers>
<ui:IsNullOrEmptyStateTrigger Value="{x:Bind ViewModel.SongInfo.FilesUsed, Mode=OneWay}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="NoLocalFilesMatchedTextBlock.Visibility" Value="Visible" />
<Setter Target="MatchedFilesListView.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>