更新ShellPage

This commit is contained in:
LanZhan
2025-08-21 20:21:54 +08:00
parent c121ad33aa
commit 5b5ccfcd3c
13 changed files with 303 additions and 104 deletions

View File

@@ -25,7 +25,7 @@ public sealed partial class MainWindow : WindowEx, IRecipient<LogMessage>
{
InitializeComponent();
AppWindow.SetIcon(Path.Combine(AppContext.BaseDirectory, "Assets/AppIcon/WindowIcon.ico"));
AppWindow.SetIcon(Path.Combine(AppContext.BaseDirectory, "Assets/AppIcon/Icon.png"));
Title = "AppDisplayName".GetLocalized();
ExtendsContentIntoTitleBar = true;

View File

@@ -1,5 +1,6 @@
using System.Diagnostics;
using MemoryPack;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml.Media.Imaging;
using The_Untamed_Music_Player.Contracts.Models;
using The_Untamed_Music_Player.Helpers;
@@ -136,33 +137,51 @@ public partial class LocalAlbumInfo : IAlbumInfoBase
return string.Join(" • ", parts);
}
public void LoadCover()
public void InitializeCover()
{
if (string.IsNullOrEmpty(CoverPath))
{
return;
}
try
{
Cover = new BitmapImage { DecodePixelWidth = 160 };
}
catch
{
Debug.WriteLine($"专辑封面初始化失败:{Name}");
}
}
public void LoadCover()
{
if (Cover is null)
{
return;
}
try
{
using var musicFile = TagLib.File.Create(CoverPath);
var coverBuffer = musicFile.Tag.Pictures[0].Data.Data;
var stream = new MemoryStream(coverBuffer);
App.MainWindow?.DispatcherQueue.TryEnqueue(async () =>
{
try
App.MainWindow?.DispatcherQueue.TryEnqueue(
DispatcherQueuePriority.Low,
async () =>
{
Cover = new BitmapImage { DecodePixelWidth = 160 };
await Cover.SetSourceAsync(stream.AsRandomAccessStream());
try
{
await Cover.SetSourceAsync(stream.AsRandomAccessStream());
}
catch
{
Debug.WriteLine($"专辑封面加载失败:{Name}");
}
finally
{
stream.Dispose();
}
}
catch
{
Debug.WriteLine($"专辑封面加载失败:{Name}");
}
finally
{
stream.Dispose();
}
});
);
}
catch
{

View File

@@ -123,7 +123,7 @@ public partial class MusicLibrary : ObservableRecipient
Artists = libraryData.Artists;
Genres = libraryData.Genres;
_musicFolders = libraryData.MusicFolders;
LoadCoverAsync();
await InitializeCovers();
_dispatcherQueue.TryEnqueue(() =>
Messenger.Send(new HaveMusicMessage(!Songs.IsEmpty))
);
@@ -146,7 +146,7 @@ public partial class MusicLibrary : ObservableRecipient
.Keys.Concat(["SongInfo_AllGenres".GetLocalized()])
.OrderBy(x => x, new GenreComparer()),
];
LoadCoverAsync();
await InitializeCovers();
_dispatcherQueue.TryEnqueue(() =>
Messenger.Send(new HaveMusicMessage(!Songs.IsEmpty))
);
@@ -162,6 +162,7 @@ public partial class MusicLibrary : ObservableRecipient
}
finally
{
_ = Task.Run(LoadCovers);
_ = Task.Run(AddFolderWatcher);
_librarySemaphore.Release();
GC.Collect();
@@ -191,7 +192,7 @@ public partial class MusicLibrary : ObservableRecipient
}
}
await Task.WhenAll(loadMusicTasks);
LoadCoverAsync();
await InitializeCovers();
Genres =
[
.. _musicGenres
@@ -204,6 +205,7 @@ public partial class MusicLibrary : ObservableRecipient
_musicGenres.Clear();
FolderWatchers.Clear();
var data = new MusicLibraryData(Songs, Albums, Artists, Genres, _musicFolders);
_ = Task.Run(LoadCovers);
_ = Task.Run(AddFolderWatcher);
FileManager.SaveLibraryDataAsync(Folders, data);
}
@@ -220,11 +222,25 @@ public partial class MusicLibrary : ObservableRecipient
});
}
public void LoadCoverAsync()
public Task<bool> InitializeCovers()
{
var tcs = new TaskCompletionSource<bool>();
_dispatcherQueue.TryEnqueue(() =>
{
foreach (var album in Albums.Values)
{
album.InitializeCover();
}
tcs.SetResult(true);
});
return tcs.Task;
}
public void LoadCovers()
{
foreach (var album in Albums.Values)
{
album.LoadCover(); // 使用同步的懒加载方法
album.LoadCover();
}
}

View File

@@ -2,6 +2,7 @@ using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using MemoryPack;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml.Media.Imaging;
using The_Untamed_Music_Player.Contracts.Models;
using The_Untamed_Music_Player.Helpers;
@@ -55,6 +56,7 @@ public partial class PlaylistInfo
if (coverPathIndex >= 0)
{
InitializeCover();
GetCover();
}
}
@@ -80,6 +82,7 @@ public partial class PlaylistInfo
ModifiedDate = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
if (coverUpdated)
{
InitializeCover();
GetCover();
}
}
@@ -120,6 +123,7 @@ public partial class PlaylistInfo
{
await RefillCoverPaths();
}
InitializeCover();
GetCover();
}
}
@@ -225,36 +229,35 @@ public partial class PlaylistInfo
}
}
public void GetCover()
public void InitializeCover()
{
if (CoverPaths.Count == 0)
{
Cover = null;
return;
}
else if (Cover is null)
{
const int canvasSize = 256;
Cover = new WriteableBitmap(canvasSize, canvasSize);
}
}
App.MainWindow?.DispatcherQueue.TryEnqueue(async () =>
public async void GetCover()
{
if (Cover is null)
{
return;
}
await Task.Run(async () =>
{
try
{
// 创建一个256x256的WriteableBitmap作为画布
const int canvasSize = 256;
const int halfSize = canvasSize / 2;
Cover = new WriteableBitmap(canvasSize, canvasSize);
var buffer = Cover.PixelBuffer;
var pixels = new byte[buffer.Length];
// 初始化为透明
Array.Fill(pixels, (byte)0);
// 定义四个区域的位置 (x, y, width, height)
var regions = new[]
{
new PictureRegion(0, 0, halfSize, halfSize), // 左上
new PictureRegion(halfSize, 0, halfSize, halfSize), // 右上
new PictureRegion(0, halfSize, halfSize, halfSize), // 左下
new PictureRegion(halfSize, halfSize, halfSize, halfSize), // 右下
};
// 在后台线程中处理所有图像数据
var processedRegions = new List<(byte[] pixels, int regionIndex)>();
for (var i = 0; i < CoverPaths.Count; i++)
{
@@ -263,13 +266,13 @@ public partial class PlaylistInfo
{
byte[]? imageBytes = null;
// 获取图片字节数据
if (coverPath.StartsWith("http", StringComparison.OrdinalIgnoreCase)) // 网络图片
if (coverPath.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
using var httpClient = new HttpClient();
httpClient.Timeout = TimeSpan.FromSeconds(5); // 设置超时
imageBytes = await httpClient.GetByteArrayAsync(coverPath);
}
else if (File.Exists(coverPath)) // 本地音乐文件
else if (File.Exists(coverPath))
{
using var musicFile = TagLib.File.Create(coverPath);
if (musicFile.Tag.Pictures.Length > 0)
@@ -283,19 +286,20 @@ public partial class PlaylistInfo
continue;
}
// 加载并调整图片大小
// 处理图像并立即释放原始数据
var resizedImageBytes = await ResizeImageToFitRegionAsync(
imageBytes,
halfSize,
halfSize
);
if (resizedImageBytes is null)
{
continue;
}
// 将调整后的图片绘制到对应区域
DrawImageToRegion(pixels, resizedImageBytes, regions[i], canvasSize);
// 释放原始图像数据
imageBytes = null;
if (resizedImageBytes is not null)
{
processedRegions.Add((resizedImageBytes, i));
}
}
catch (Exception ex)
{
@@ -303,14 +307,57 @@ public partial class PlaylistInfo
}
}
// 将像素数据写入WriteableBitmap
using (var pixelStream = buffer.AsStream())
{
pixelStream.Write(pixels, 0, pixels.Length);
}
// 切换回UI线程进行最终的绘制
App.MainWindow?.DispatcherQueue.TryEnqueue(
DispatcherQueuePriority.Low,
async () =>
{
try
{
var buffer = Cover.PixelBuffer;
var pixels = new byte[buffer.Length];
// 使WriteableBitmap失效以更新显示
Cover.Invalidate();
// 初始化为透明
Array.Fill(pixels, (byte)0);
// 定义四个区域的位置
var regions = new[]
{
new PictureRegion(0, 0, halfSize, halfSize), // 左上
new PictureRegion(halfSize, 0, halfSize, halfSize), // 右上
new PictureRegion(0, halfSize, halfSize, halfSize), // 左下
new PictureRegion(halfSize, halfSize, halfSize, halfSize), // 右下
};
// 绘制所有处理好的区域
foreach (var (regionPixels, regionIndex) in processedRegions)
{
if (regionIndex < regions.Length)
{
DrawImageToRegion(
pixels,
regionPixels,
regions[regionIndex],
canvasSize
);
}
}
// 将像素数据写入WriteableBitmap
using (var pixelStream = buffer.AsStream())
{
await pixelStream.WriteAsync(pixels);
}
// 使WriteableBitmap失效以更新显示
Cover.Invalidate();
}
catch (Exception ex)
{
Debug.WriteLine($"UI线程绘制失败: {ex.Message}");
}
}
);
}
catch (Exception ex)
{

View File

@@ -1,3 +1,5 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.Logging;
using The_Untamed_Music_Player.Contracts.Models;
@@ -7,11 +9,12 @@ using ZLinq;
namespace The_Untamed_Music_Player.Models;
public class PlaylistLibrary
public partial class PlaylistLibrary : ObservableRecipient
{
public List<PlaylistInfo> Playlists { get; set; } = [];
public PlaylistLibrary()
: base(StrongReferenceMessenger.Default)
{
_ = LoadLibraryAsync();
}
@@ -19,11 +22,17 @@ public class PlaylistLibrary
public async Task LoadLibraryAsync()
{
Playlists = await FileManager.LoadPlaylistDataAsync();
foreach (var playlist in Playlists)
{
playlist.InitializeCover();
}
Messenger.Send(new HavePlaylistMessage(Playlists.Count > 0));
foreach (var playlist in Playlists)
{
playlist.GetCover();
}
StrongReferenceMessenger.Default.Send(new HavePlaylistMessage(Playlists.Count > 0));
GC.Collect();
}
public PlaylistInfo? NewPlaylist(string? name)
@@ -35,8 +44,9 @@ public class PlaylistLibrary
var uniqueName = GetUniquePlaylistName(name);
var info = new PlaylistInfo(uniqueName);
Playlists.Add(info);
StrongReferenceMessenger.Default.Send(new HavePlaylistMessage(true));
StrongReferenceMessenger.Default.Send(
Playlists = [.. Playlists.OrderBy(p => p.Name, new TitleComparer())];
Messenger.Send(new HavePlaylistMessage(true));
Messenger.Send(
new LogMessage(
LogLevel.None,
"PlaylistInfo_Create".GetLocalizedWithReplace("{title}", uniqueName)
@@ -54,16 +64,16 @@ public class PlaylistLibrary
}
var uniqueName = GetUniquePlaylistName(newName);
info.Name = uniqueName;
StrongReferenceMessenger.Default.Send(new HavePlaylistMessage(Playlists.Count > 0));
StrongReferenceMessenger.Default.Send(new PlaylistRenameMessage(oldName, info));
Messenger.Send(new HavePlaylistMessage(Playlists.Count > 0));
Messenger.Send(new PlaylistRenameMessage(oldName, info));
return true;
}
public void DeletePlaylist(PlaylistInfo info)
{
Playlists.Remove(info);
StrongReferenceMessenger.Default.Send(new HavePlaylistMessage(Playlists.Count > 0));
StrongReferenceMessenger.Default.Send(
Messenger.Send(new HavePlaylistMessage(Playlists.Count > 0));
Messenger.Send(
new LogMessage(
LogLevel.None,
"PlaylistInfo_Delete".GetLocalizedWithReplace("{title}", info.Name)
@@ -74,14 +84,14 @@ public class PlaylistLibrary
public async Task AddToPlaylist(PlaylistInfo info, IBriefSongInfoBase song)
{
await info.Add(song);
StrongReferenceMessenger.Default.Send(new HavePlaylistMessage(Playlists.Count > 0));
StrongReferenceMessenger.Default.Send(new PlaylistChangeMessage(info));
Messenger.Send(new HavePlaylistMessage(Playlists.Count > 0));
Messenger.Send(new PlaylistChangeMessage(info));
var replacements = new Dictionary<string, string>
{
{ "{num}", "1" },
{ "{title}", info.Name },
};
StrongReferenceMessenger.Default.Send(
Messenger.Send(
new LogMessage(
LogLevel.None,
"PlaylistInfo_AddItem".GetLocalizedWithReplace(replacements)
@@ -96,15 +106,15 @@ public class PlaylistLibrary
return;
}
await info.AddRange(songs);
StrongReferenceMessenger.Default.Send(new HavePlaylistMessage(Playlists.Count > 0));
StrongReferenceMessenger.Default.Send(new PlaylistChangeMessage(info));
Messenger.Send(new HavePlaylistMessage(Playlists.Count > 0));
Messenger.Send(new PlaylistChangeMessage(info));
var count = songs.Count();
var replacements = new Dictionary<string, string>
{
{ "{num}", $"{count}" },
{ "{title}", info.Name },
};
StrongReferenceMessenger.Default.Send(
Messenger.Send(
new LogMessage(
LogLevel.None,
count == 1
@@ -117,8 +127,8 @@ public class PlaylistLibrary
public async Task DeleteFromPlaylist(PlaylistInfo info, IndexedPlaylistSong song)
{
await info.Delete(song);
StrongReferenceMessenger.Default.Send(new HavePlaylistMessage(Playlists.Count > 0));
StrongReferenceMessenger.Default.Send(new PlaylistChangeMessage(info));
Messenger.Send(new HavePlaylistMessage(Playlists.Count > 0));
Messenger.Send(new PlaylistChangeMessage(info));
}
public void MoveUpInPlaylist(PlaylistInfo info, IndexedPlaylistSong song)

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
@@ -7,7 +7,8 @@
xmlns:genTemplate="http://schemas.microsoft.com/appx/developer/templatestudio"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
IgnorableNamespaces="uap rescap genTemplate">
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
IgnorableNamespaces="uap rescap genTemplate uap3">
<Identity
Name="C19A3696.28439CB846862"
@@ -70,6 +71,7 @@
<Capabilities>
<rescap:Capability Name="runFullTrust" />
<uap:Capability Name="musicLibrary"/>
<uap3:Capability Name="backgroundMediaPlayback"/>
</Capabilities>
<genTemplate:Metadata>

View File

@@ -111,7 +111,14 @@ public partial class PlayListDetailViewModel
public void DeleteButton_Click(object sender, RoutedEventArgs e)
{
Data.SelectedPlaylist = null;
Data.ShellPage!.GetFrame().GoBack();
if (Data.ShellViewModel!.CurrentPage == nameof(PlayListsPage))
{
Data.ShellPage!.GoBack();
}
else
{
Data.ShellPage!.GoBack();
}
Data.PlaylistLibrary.DeletePlaylist(Playlist);
}

View File

@@ -1,4 +1,5 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
using The_Untamed_Music_Player.Contracts.Services;
using The_Untamed_Music_Player.Models;
@@ -17,6 +18,8 @@ public partial class ShellViewModel : ObservableObject
public string CurrentPage { get; set; } = null!;
public PlaylistInfo? PrevPlaylistInfo { get; set; }
[ObservableProperty]
public partial object SelectedItem { get; set; } = null!;
@@ -28,6 +31,10 @@ public partial class ShellViewModel : ObservableObject
public void NavigationFrame_Navigating(object sender, NavigatingCancelEventArgs e)
{
if (e.NavigationMode == NavigationMode.Back)
{
PrevPlaylistInfo = null;
}
CurrentPage = e.SourcePageType.Name;
var navView = Data.ShellPage!.GetNavigationView();
if (
@@ -53,10 +60,27 @@ public partial class ShellViewModel : ObservableObject
{
SelectedItem = navView.MenuItems[3];
}
else if (CurrentPage is nameof(PlayListsPage) or nameof(PlayListDetailPage))
else if (CurrentPage is nameof(PlayListsPage))
{
SelectedItem = navView.MenuItems[4];
}
else if (CurrentPage is nameof(PlayListDetailPage))
{
var playlistsNavItem = navView.MenuItems[4] as NavigationViewItem;
var playlistSubItem = playlistsNavItem!
.MenuItems.Cast<NavigationViewItem>()
.FirstOrDefault(item =>
item.DataContext is PlaylistInfo playlist && playlist == PrevPlaylistInfo
);
if (playlistSubItem is not null)
{
SelectedItem = playlistSubItem;
}
else
{
SelectedItem = playlistsNavItem;
}
}
else if (CurrentPage is nameof(SettingsPage))
{
SelectedItem = navView.FooterMenuItems[0];

View File

@@ -110,7 +110,7 @@
Style="{StaticResource NavigationBackButtonNormalStyle}"/>
<Image Width="16" Height="16"
Margin="12,0,0,0" HorizontalAlignment="Left"
Source="/Assets/AppIcon/WindowIcon.ico"/>
Source="/Assets/AppIcon/Icon.png"/>
<TextBlock x:Name="AppTitleBarText"
Margin="12,0,0,0" VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}"

View File

@@ -252,7 +252,7 @@
<Grid Background="{ThemeResource SolidBackgroundFillColorSecondaryBrush}" Canvas.ZIndex="0">
<FontIcon Canvas.ZIndex="0"
FontFamily="{StaticResource UntamedFontFamily}"
FontSize="50"
FontSize="64"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Glyph="&#xED3B;"
Visibility="{x:Bind ViewModel.Cover, Mode=OneWay, Converter={StaticResource InverseEmptyObjectToVisibilityConverter}}"/>

View File

@@ -245,8 +245,7 @@
Style="{StaticResource BodyStrongTextBlockStyle}"/>
<toolkit:SettingsExpander x:Name="About" x:Uid="Settings_AboutDescription"
Header="{x:Bind model:Data.AppDisplayName}"
HeaderIcon="{ui:BitmapIcon ShowAsMonochrome=False,
Source=ms-appx:///Assets/AppIcon/WindowIcon.ico}">
HeaderIcon="{ui:BitmapIcon Source=ms-appx:///Assets/AppIcon/Icon.png}">
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="{x:Bind ViewModel.VersionDescription, Mode=OneWay}"/>
<toolkit:SettingsExpander.Items>
<toolkit:SettingsCard x:Uid="Settings_Thanks"/>

View File

@@ -6,7 +6,8 @@
xmlns:helper="using:The_Untamed_Music_Player.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI"
Loaded="OnLoaded">
Loaded="ShellPage_Loaded"
Unloaded="ShellPage_Unloaded">
<Page.Resources>
<SolidColorBrush x:Key="NavigationViewContentBackground" Color="Transparent"/>
@@ -25,7 +26,7 @@
Canvas.ZIndex="1">
<Image Width="16" Height="16"
Margin="12,0,0,0" HorizontalAlignment="Left"
Source="/Assets/AppIcon/WindowIcon.ico"/>
Source="/Assets/AppIcon/Icon.png"/>
<TextBlock Margin="40,0,0,0" VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind _appTitleBarText}"
@@ -80,10 +81,11 @@
<KeyboardAccelerator Key="Q" Modifiers="Control"/>
</NavigationViewItem.KeyboardAccelerators>
</NavigationViewItem>
<NavigationViewItem x:Uid="Shell_PlayLists"
<NavigationViewItem x:Name="PlaylistsNavItem" x:Uid="Shell_PlayLists"
AccessKey="NP"
Icon="{ui:FontIcon FontFamily={StaticResource UntamedFontFamily},
Glyph=&#xED3B;}"
Loaded="PlaylistsNavItem_Loaded"
Tag="PlayListsPage">
<NavigationViewItem.KeyboardAccelerators>
<KeyboardAccelerator Key="Y" Modifiers="Control"/>

View File

@@ -1,13 +1,15 @@
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Animation;
using The_Untamed_Music_Player.Helpers;
using The_Untamed_Music_Player.Messages;
using The_Untamed_Music_Player.Models;
using The_Untamed_Music_Player.ViewModels;
namespace The_Untamed_Music_Player.Views;
public sealed partial class ShellPage : Page
public sealed partial class ShellPage : Page, IRecipient<HavePlaylistMessage>
{
public ShellViewModel ViewModel { get; }
@@ -15,17 +17,39 @@ public sealed partial class ShellPage : Page
public ShellPage() //注意修改, 不能有参数
{
StrongReferenceMessenger.Default.Register(this);
InitializeComponent();
Data.ShellPage = this;
ViewModel = App.GetService<ShellViewModel>();
Data.MainWindow!.SetTitleBar(AppTitleBar);
}
private void OnLoaded(object sender, RoutedEventArgs e)
public void Receive(HavePlaylistMessage message)
{
PlaylistsNavItem.MenuItems.Clear();
foreach (var playlist in Data.PlaylistLibrary.Playlists)
{
var playlistItem = new NavigationViewItem
{
Content = playlist.Name,
Tag = nameof(PlayListDetailPage),
DataContext = playlist,
};
ToolTipService.SetToolTip(playlistItem, playlist.Name);
PlaylistsNavItem.MenuItems.Add(playlistItem);
}
}
private void ShellPage_Loaded(object sender, RoutedEventArgs e)
{
TitleBarHelper.UpdateTitleBar(RequestedTheme);
}
private void ShellPage_Unloaded(object sender, RoutedEventArgs e)
{
StrongReferenceMessenger.Default.Unregister<HavePlaylistMessage>(this);
}
public void NavigationViewControl_DisplayModeChanged(
NavigationView sender,
NavigationViewDisplayModeChangedEventArgs args
@@ -77,6 +101,25 @@ public sealed partial class ShellPage : Page
}
}
private void PlaylistsNavItem_Loaded(object sender, RoutedEventArgs e)
{
if (sender is NavigationViewItem navItem)
{
navItem.MenuItems.Clear();
foreach (var playlist in Data.PlaylistLibrary.Playlists)
{
var playlistItem = new NavigationViewItem
{
Content = playlist.Name,
Tag = nameof(PlayListDetailPage),
DataContext = playlist,
};
ToolTipService.SetToolTip(playlistItem, playlist.Name);
navItem.MenuItems.Add(playlistItem);
}
}
}
private void NavigationViewControl_BackRequested(
NavigationView sender,
NavigationViewBackRequestedEventArgs args
@@ -95,28 +138,41 @@ public sealed partial class ShellPage : Page
{
if (args.InvokedItemContainer is NavigationViewItem invokedItem)
{
Navigate($"{invokedItem.Tag}");
var tag = $"{invokedItem.Tag}";
if (
tag == nameof(PlayListDetailPage)
&& invokedItem.DataContext is PlaylistInfo playlist
)
{
if (ViewModel.PrevPlaylistInfo == playlist)
{
return;
}
Data.SelectedPlaylist = playlist;
ViewModel.PrevPlaylistInfo = playlist;
}
else if (ViewModel.CurrentPage == tag)
{
return; // 避免重复导航到同一页面
}
else
{
ViewModel.PrevPlaylistInfo = null;
}
var pageToNavigate = tag switch
{
nameof(HomePage) => typeof(HomePage),
nameof(MusicLibraryPage) => typeof(MusicLibraryPage),
nameof(PlayQueuePage) => typeof(PlayQueuePage),
nameof(PlayListsPage) => typeof(PlayListsPage),
nameof(PlayListDetailPage) => typeof(PlayListDetailPage),
nameof(SettingsPage) => typeof(SettingsPage),
_ => typeof(HomePage),
};
NavigationFrame.Navigate(pageToNavigate);
}
}
public void Navigate(string tag)
{
if (ViewModel.CurrentPage == tag)
{
return;
}
var pageToNavigate = tag switch
{
nameof(HomePage) => typeof(HomePage),
nameof(MusicLibraryPage) => typeof(MusicLibraryPage),
nameof(PlayQueuePage) => typeof(PlayQueuePage),
nameof(PlayListsPage) => typeof(PlayListsPage),
nameof(SettingsPage) => typeof(SettingsPage),
_ => typeof(HomePage),
};
NavigationFrame.Navigate(pageToNavigate);
}
public void Navigate(
string destPage,
string parameter,
@@ -141,4 +197,21 @@ public sealed partial class ShellPage : Page
};
NavigationFrame.Navigate(pageToNavigate, null, infoOverride);
}
public void GoBack()
{
if (NavigationFrame.CanGoBack)
{
var page = NavigationFrame.BackStack.LastOrDefault();
if (page?.SourcePageType == typeof(PlayListDetailPage) && Data.SelectedPlaylist is null)
{
NavigationFrame.BackStack.Remove(page);
GoBack();
}
else
{
NavigationFrame.GoBack();
}
}
}
}