mirror of
https://github.com/LanZhan-Harmony/WindowsMusicPlayer-TheUntamedMusicPlayer.git
synced 2026-05-06 19:20:18 +08:00
更新播放列表编辑
This commit is contained in:
@@ -1,10 +1,173 @@
|
||||
<ContentDialog x:Class="The_Untamed_Music_Player.Controls.EditPlaylistInfoDialog"
|
||||
<ContentDialog x:Uid="EditPlaylistInfoDialog"
|
||||
x:Class="The_Untamed_Music_Player.Controls.EditPlaylistInfoDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:helper="using:The_Untamed_Music_Player.Helpers"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:local="using:The_Untamed_Music_Player.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:toolkitConverters="using:CommunityToolkit.WinUI.Converters"
|
||||
CloseButtonClick="CloseButtonClick"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonClick="SaveButtonClick"
|
||||
Style="{StaticResource DefaultContentDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid/>
|
||||
<ContentDialog.Resources>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">2000</x:Double>
|
||||
<toolkitConverters:EmptyObjectToObjectConverter x:Key="InverseEmptyObjectToVisibilityConverter"
|
||||
EmptyValue="Visible" NotEmptyValue="Collapsed"/>
|
||||
|
||||
<DataTemplate x:Key="SongListViewTemplate" x:DataType="local:DisplaySongInfo">
|
||||
<Grid Background="Transparent">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200"/>
|
||||
<ColumnDefinition Width="17"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="{x:Bind Type}"/>
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{x:Bind Song.Title}"
|
||||
ToolTipService.ToolTip="{x:Bind Song.Title}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<ScrollViewer Margin="-24,0,-24,0">
|
||||
<StackPanel>
|
||||
<Grid Width="625">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition x:Name="Column0" Width="*"/>
|
||||
<ColumnDefinition x:Name="Column1" Width="17"/>
|
||||
<ColumnDefinition x:Name="Column2" Width="280"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Row="0" Grid.Column="0"
|
||||
Padding="24,0,0,0"
|
||||
Spacing="12">
|
||||
<TextBox x:Name="PlaylistNameTextBox"
|
||||
Text="{x:Bind _name, Mode=TwoWay}"
|
||||
TextChanged="PlaylistNameTextBox_TextChanged">
|
||||
<TextBox.Header>
|
||||
<TextBlock x:Uid="ImportPlaylistDialog_Name"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"/>
|
||||
</TextBox.Header>
|
||||
</TextBox>
|
||||
<StackPanel>
|
||||
<TextBlock x:Uid="ImportPlaylistDialog_NumberOfSongs"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"/>
|
||||
<TextBlock Text="{x:Bind SongCount, Mode=OneWay}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock x:Uid="ImportPlaylistDialog_ImportSongs"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"/>
|
||||
<Button x:Name="ImportFromM3u8FilesButton" x:Uid="ImportPlaylistDialog_ImportFromM3u8Files"
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="ImportFromM3u8FilesButton_Click"/>
|
||||
<Button x:Name="ImportFromFolderButton" x:Uid="ImportPlaylistDialog_ImportFromFolder"
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="ImportFromFolderButton_Click"/>
|
||||
</StackPanel>
|
||||
|
||||
<ProgressRing Width="40" Height="40"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsActive="{x:Bind IsImportingProgressRingActive, Mode=OneWay}"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="0" Grid.Column="2"
|
||||
Padding="0,0,24,0" VerticalAlignment="Bottom">
|
||||
<Border Width="256" Height="256"
|
||||
Margin="0,4,0,0" Padding="0"
|
||||
BorderBrush="{ThemeResource SolidBackgroundFillColorBaseAltBrush}"
|
||||
BorderThickness="1" Canvas.ZIndex="0"
|
||||
CornerRadius="5">
|
||||
<Grid>
|
||||
<StackPanel Margin="2,0,0,2" VerticalAlignment="Bottom"
|
||||
Canvas.ZIndex="2" Orientation="Horizontal"
|
||||
Spacing="2">
|
||||
<Button Background="{ThemeResource SolidBackgroundFillColorBaseBrush}"
|
||||
Click="ChangeCoverButton_Click"
|
||||
Style="{StaticResource MenuButtonStyle}">
|
||||
<FontIcon FontFamily="{StaticResource UntamedFontFamily}" Glyph=""/>
|
||||
</Button>
|
||||
<Button Background="{ThemeResource SolidBackgroundFillColorBaseBrush}"
|
||||
Click="DeleteCoverButton_Click"
|
||||
IsEnabled="{x:Bind IsSaveCoverButtonEnabled, Mode=OneWay}"
|
||||
Style="{StaticResource MenuButtonStyle}">
|
||||
<FontIcon FontFamily="{StaticResource UntamedFontFamily}" Glyph=""/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<Button x:Name="SaveCoverButton"
|
||||
Margin="0,0,2,2" HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="{ThemeResource SolidBackgroundFillColorBaseBrush}"
|
||||
Canvas.ZIndex="2" Click="SaveCoverButton_Click"
|
||||
IsEnabled="{x:Bind IsSaveCoverButtonEnabled, Mode=OneWay}"
|
||||
Style="{StaticResource MenuButtonStyle}">
|
||||
<FontIcon FontFamily="{StaticResource UntamedFontFamily}" Glyph=""/>
|
||||
</Button>
|
||||
<ProgressRing Width="48" Height="48"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Canvas.ZIndex="2"
|
||||
IsActive="{x:Bind IsChangingCoverProgressRingActive, Mode=OneWay}"/>
|
||||
<Image Canvas.ZIndex="1" Source="{x:Bind Cover, Mode=OneWay}"/>
|
||||
<Grid Background="{ThemeResource SolidBackgroundFillColorSecondaryBrush}"
|
||||
Canvas.ZIndex="0"
|
||||
Visibility="{x:Bind Cover, Mode=OneWay, Converter={StaticResource InverseEmptyObjectToVisibilityConverter}}">
|
||||
<FontIcon Canvas.ZIndex="0"
|
||||
FontFamily="{StaticResource UntamedFontFamily}"
|
||||
FontSize="85"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Glyph=""/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<Grid Grid.Row="1" Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="24,12,24,0"
|
||||
Visibility="{x:Bind SongListViewVisibility, Mode=OneWay}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<ColumnDefinition Width="217"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Uid="ImportPlaylistDialog_Type"
|
||||
Grid.Column="1"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"/>
|
||||
<TextBlock x:Uid="PropertiesDialog_Title"
|
||||
Grid.Column="2"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"/>
|
||||
</Grid>
|
||||
|
||||
<ListView Grid.Row="1" Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="24,40,24,0"
|
||||
helper:ListViewExtensions.ItemCornerRadius="8"
|
||||
IsItemClickEnabled="False"
|
||||
ItemTemplate="{StaticResource SongListViewTemplate}"
|
||||
ItemsSource="{x:Bind Songs, Mode=OneWay}"
|
||||
SelectionMode="None"
|
||||
Visibility="{x:Bind SongListViewVisibility, Mode=OneWay}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<helper:AlternatingListViewBehavior AlternateBackground="{ThemeResource AlternateBackgroundBrush}"
|
||||
AlternateBorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
AlternateBorderThickness="1"/>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</ContentDialog>
|
||||
|
||||
@@ -1,11 +1,383 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using The_Untamed_Music_Player.Contracts.Models;
|
||||
using The_Untamed_Music_Player.Helpers;
|
||||
using The_Untamed_Music_Player.Messages;
|
||||
using The_Untamed_Music_Player.Models;
|
||||
using Windows.Graphics.Imaging;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace The_Untamed_Music_Player.Controls;
|
||||
|
||||
public sealed partial class EditPlaylistInfoDialog : ContentDialog
|
||||
public sealed partial class EditPlaylistInfoDialog : ContentDialog, INotifyPropertyChanged
|
||||
{
|
||||
public EditPlaylistInfoDialog()
|
||||
private readonly PlaylistInfo _playlist;
|
||||
private readonly string _originalName;
|
||||
private string _name;
|
||||
private ObservableCollection<DisplaySongInfo> Songs { get; set; } = [];
|
||||
private int SongCount
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
field = value;
|
||||
SongListViewVisibility = value > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||
OnPropertyChanged(nameof(SongCount));
|
||||
}
|
||||
}
|
||||
|
||||
private Visibility SongListViewVisibility
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
field = value;
|
||||
OnPropertyChanged(nameof(SongListViewVisibility));
|
||||
}
|
||||
} = Visibility.Collapsed;
|
||||
|
||||
private bool _isCoverEdited;
|
||||
|
||||
private readonly List<string> _coverPaths;
|
||||
|
||||
private WriteableBitmap? Cover
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
field = value;
|
||||
OnPropertyChanged(nameof(Cover));
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSaveCoverButtonEnabled
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
field = value;
|
||||
OnPropertyChanged(nameof(IsSaveCoverButtonEnabled));
|
||||
}
|
||||
} = false;
|
||||
|
||||
private bool IsChangingCoverProgressRingActive
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
field = value;
|
||||
OnPropertyChanged(nameof(IsChangingCoverProgressRingActive));
|
||||
}
|
||||
} = false;
|
||||
|
||||
private bool IsImportingProgressRingActive
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
field = value;
|
||||
ImportFromM3u8FilesButton.IsEnabled = !value;
|
||||
ImportFromFolderButton.IsEnabled = !value;
|
||||
OnPropertyChanged(nameof(IsImportingProgressRingActive));
|
||||
}
|
||||
} = false;
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
private void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
public EditPlaylistInfoDialog(PlaylistInfo info)
|
||||
{
|
||||
_playlist = info;
|
||||
_originalName = info.Name;
|
||||
_name = info.Name;
|
||||
foreach (var song in info.SongList)
|
||||
{
|
||||
Songs.Add(new DisplaySongInfo(song.Song));
|
||||
}
|
||||
SongCount = Songs.Count;
|
||||
Cover = info.Cover;
|
||||
_isCoverEdited = info.IsCoverEdited;
|
||||
_coverPaths = [.. info.CoverPaths]; // 注意要创建副本
|
||||
IsSaveCoverButtonEnabled = Cover is not null;
|
||||
RequestedTheme = Data.MainViewModel!.IsDarkTheme ? ElementTheme.Dark : ElementTheme.Light;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void PlaylistNameTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
IsPrimaryButtonEnabled = !string.IsNullOrEmpty((sender as TextBox)!.Text);
|
||||
}
|
||||
|
||||
private async void ChangeCoverButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
(sender as Button)!.IsEnabled = false;
|
||||
IsChangingCoverProgressRingActive = true;
|
||||
try
|
||||
{
|
||||
var openPicker = new FileOpenPicker
|
||||
{
|
||||
SuggestedStartLocation = PickerLocationId.PicturesLibrary,
|
||||
};
|
||||
foreach (var type in Data.SupportedCoverTypes)
|
||||
{
|
||||
openPicker.FileTypeFilter.Add(type);
|
||||
}
|
||||
var hWnd = WindowNative.GetWindowHandle(App.MainWindow);
|
||||
InitializeWithWindow.Initialize(openPicker, hWnd);
|
||||
var file = await openPicker.PickSingleFileAsync();
|
||||
if (file is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var localFolder = ApplicationData.Current.LocalFolder;
|
||||
var playlistCoverFolder = await localFolder.CreateFolderAsync(
|
||||
"PlaylistCover",
|
||||
CreationCollisionOption.OpenIfExists
|
||||
);
|
||||
var extension = Path.GetExtension(file.Name);
|
||||
var newFileName = $"{Guid.CreateVersion7()}{extension}";
|
||||
var targetFile = await playlistCoverFolder.CreateFileAsync(
|
||||
newFileName,
|
||||
CreationCollisionOption.ReplaceExisting
|
||||
);
|
||||
await file.CopyAndReplaceAsync(targetFile);
|
||||
_isCoverEdited = true;
|
||||
_coverPaths.Clear();
|
||||
_coverPaths.Add(targetFile.Path);
|
||||
await GetCover();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"更改封面失败: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsSaveCoverButtonEnabled = Cover is not null;
|
||||
IsChangingCoverProgressRingActive = false;
|
||||
(sender as Button)!.IsEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteCoverButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_isCoverEdited = true;
|
||||
_coverPaths.Clear();
|
||||
Cover = null;
|
||||
IsSaveCoverButtonEnabled = false;
|
||||
}
|
||||
|
||||
private async void SaveCoverButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
(sender as Button)!.IsEnabled = false;
|
||||
try
|
||||
{
|
||||
if (_coverPaths.Count == 0 || !File.Exists(_coverPaths[0]))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var extension = Path.GetExtension(_coverPaths[0]);
|
||||
var fileName = string.IsNullOrWhiteSpace(PlaylistNameTextBox.Text)
|
||||
? "PlaylistInfo_UntitledPlaylist".GetLocalized()
|
||||
: PlaylistNameTextBox.Text;
|
||||
var savePicker = new FileSavePicker
|
||||
{
|
||||
SuggestedStartLocation = PickerLocationId.PicturesLibrary,
|
||||
SuggestedFileName = fileName,
|
||||
FileTypeChoices =
|
||||
{
|
||||
new("EditSongInfoDialog_CoverImage".GetLocalized(), [extension]),
|
||||
},
|
||||
};
|
||||
var hWnd = WindowNative.GetWindowHandle(App.MainWindow);
|
||||
InitializeWithWindow.Initialize(savePicker, hWnd);
|
||||
var file = await savePicker.PickSaveFileAsync();
|
||||
if (file is not null)
|
||||
{
|
||||
var imageBytes = await File.ReadAllBytesAsync(_coverPaths[0]);
|
||||
await FileIO.WriteBytesAsync(file, imageBytes);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"保存封面失败: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
(sender as Button)!.IsEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async void ImportFromM3u8FilesButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
IsImportingProgressRingActive = true;
|
||||
try
|
||||
{
|
||||
var picker = new FileOpenPicker
|
||||
{
|
||||
SuggestedStartLocation = PickerLocationId.MusicLibrary,
|
||||
FileTypeFilter = { ".m3u8", ".m3u" },
|
||||
};
|
||||
var hWnd = WindowNative.GetWindowHandle(App.MainWindow);
|
||||
InitializeWithWindow.Initialize(picker, hWnd);
|
||||
var files = await picker.PickMultipleFilesAsync();
|
||||
if (files.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var shouldSetCoverPath = (Cover is null) && !_isCoverEdited;
|
||||
string? coverPath = null;
|
||||
foreach (var file in files)
|
||||
{
|
||||
var (_, path, songs) = await M3u8Helper.GetNameAndSongsFromM3u8(file);
|
||||
foreach (var song in songs)
|
||||
{
|
||||
Songs.Add(new DisplaySongInfo(song));
|
||||
}
|
||||
if (shouldSetCoverPath && coverPath is null && path is not null)
|
||||
{
|
||||
coverPath = path;
|
||||
}
|
||||
}
|
||||
if (shouldSetCoverPath && coverPath is not null)
|
||||
{
|
||||
_isCoverEdited = true;
|
||||
_coverPaths.Clear();
|
||||
_coverPaths.Add(coverPath);
|
||||
await GetCover();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
finally
|
||||
{
|
||||
SongCount = Songs.Count;
|
||||
IsSaveCoverButtonEnabled = Cover is not null;
|
||||
IsImportingProgressRingActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async void ImportFromFolderButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
IsImportingProgressRingActive = true;
|
||||
try
|
||||
{
|
||||
var folderPicker = new FolderPicker
|
||||
{
|
||||
SuggestedStartLocation = PickerLocationId.MusicLibrary,
|
||||
FileTypeFilter = { "*" },
|
||||
};
|
||||
var hWnd = WindowNative.GetWindowHandle(App.MainWindow);
|
||||
InitializeWithWindow.Initialize(folderPicker, hWnd);
|
||||
var folder = await folderPicker.PickSingleFolderAsync();
|
||||
if (folder is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var songList = new ConcurrentBag<IBriefSongInfoBase>();
|
||||
await ImportPlaylistDialog.LoadMusicAsync(songList, folder);
|
||||
foreach (var song in songList)
|
||||
{
|
||||
Songs.Add(new DisplaySongInfo(song));
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
finally
|
||||
{
|
||||
SongCount = Songs.Count;
|
||||
IsImportingProgressRingActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task GetCover()
|
||||
{
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var imagePath = _coverPaths[0];
|
||||
if (!File.Exists(imagePath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
const int canvasSize = 256;
|
||||
var imageBytes = await File.ReadAllBytesAsync(imagePath);
|
||||
var resizedImageBytes = await PlaylistInfo.ResizeImageToFitRegionAsync(
|
||||
imageBytes,
|
||||
canvasSize,
|
||||
canvasSize
|
||||
);
|
||||
if (resizedImageBytes is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DispatcherQueue.TryEnqueue(
|
||||
DispatcherQueuePriority.Low,
|
||||
async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Cover ??= new(256, 256);
|
||||
using var pixelStream = Cover.PixelBuffer.AsStream();
|
||||
await pixelStream.WriteAsync(resizedImageBytes);
|
||||
Cover.Invalidate();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
);
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
}
|
||||
|
||||
private async void SaveButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
if (_originalName != _name)
|
||||
{
|
||||
var uniqueName = Data.PlaylistLibrary.GetUniquePlaylistName(_name);
|
||||
_playlist.Name = uniqueName;
|
||||
StrongReferenceMessenger.Default.Send(
|
||||
new PlaylistRenameMessage(_originalName, uniqueName)
|
||||
);
|
||||
}
|
||||
if (_isCoverEdited)
|
||||
{
|
||||
_playlist.ClearCover();
|
||||
_playlist.CoverPaths = _coverPaths;
|
||||
_playlist.Cover = Cover;
|
||||
}
|
||||
_playlist.SongList.Clear();
|
||||
await _playlist.AddRange([.. Songs.Select(s => s.Song)]);
|
||||
StrongReferenceMessenger.Default.Send(new HavePlaylistMessage(true));
|
||||
StrongReferenceMessenger.Default.Send(new PlaylistChangeMessage(_playlist));
|
||||
_ = FileManager.SavePlaylistDataAsync(Data.PlaylistLibrary.Playlists);
|
||||
}
|
||||
|
||||
private new void CloseButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
if (_isCoverEdited && _coverPaths.Count > 0)
|
||||
{
|
||||
if (File.Exists(_coverPaths[0]))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(_coverPaths[0]);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ public sealed partial class ImportPlaylistDialog : ContentDialog, INotifyPropert
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task LoadMusicAsync(
|
||||
public static async Task LoadMusicAsync(
|
||||
ConcurrentBag<IBriefSongInfoBase> songList,
|
||||
StorageFolder folder
|
||||
)
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
<ContentDialog x:Uid="RenamePlaylistInfoDialog"
|
||||
x:Class="The_Untamed_Music_Player.Controls.RenamePlaylistInfoDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:The_Untamed_Music_Player.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:toolkitConverters="using:CommunityToolkit.WinUI.Converters"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonClick="RenameButtonClick"
|
||||
Style="{StaticResource DefaultContentDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
<ContentDialog.Resources>
|
||||
<toolkitConverters:EmptyObjectToObjectConverter x:Key="InverseEmptyObjectToVisibilityConverter"
|
||||
EmptyValue="Visible" NotEmptyValue="Collapsed"/>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<Grid>
|
||||
<StackPanel Spacing="16">
|
||||
<Border x:Name="CoverBorder"
|
||||
Width="120" Height="120"
|
||||
Padding="0"
|
||||
CornerRadius="5">
|
||||
<Grid>
|
||||
<Image x:Name="ControllerCover"
|
||||
Width="120" Height="120"
|
||||
HorizontalAlignment="Center"
|
||||
Canvas.ZIndex="1"
|
||||
Source="{x:Bind _playlist.Cover}"
|
||||
Stretch="UniformToFill"/>
|
||||
<Grid Width="120" Height="120"
|
||||
Background="{ThemeResource SolidBackgroundFillColorSecondaryBrush}"
|
||||
Canvas.ZIndex="0">
|
||||
<FontIcon Canvas.ZIndex="0"
|
||||
FontFamily="{StaticResource UntamedFontFamily}"
|
||||
FontSize="40"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind _playlist.Cover, Converter={StaticResource InverseEmptyObjectToVisibilityConverter}}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
<TextBox x:Name="RenameTextBox"
|
||||
Width="290"
|
||||
HorizontalAlignment="Center"
|
||||
SelectedText="{x:Bind _playlist.Name}"
|
||||
TextChanged="RenameTextBox_TextChanged"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ContentDialog>
|
||||
@@ -1,37 +0,0 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using The_Untamed_Music_Player.Models;
|
||||
using The_Untamed_Music_Player.Services;
|
||||
|
||||
namespace The_Untamed_Music_Player.Controls;
|
||||
|
||||
public sealed partial class RenamePlaylistInfoDialog : ContentDialog
|
||||
{
|
||||
private static readonly ILogger _logger =
|
||||
LoggingService.CreateLogger<RenamePlaylistInfoDialog>();
|
||||
private readonly PlaylistInfo _playlist;
|
||||
|
||||
public RenamePlaylistInfoDialog(PlaylistInfo info)
|
||||
{
|
||||
_playlist = info;
|
||||
RequestedTheme = Data.MainViewModel!.IsDarkTheme ? ElementTheme.Dark : ElementTheme.Light;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void RenameButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
var newName = RenameTextBox.Text;
|
||||
var result = Data.PlaylistLibrary.RenamePlaylist(_playlist, newName);
|
||||
if (!result)
|
||||
{
|
||||
_logger.SamePlaylistName();
|
||||
}
|
||||
}
|
||||
|
||||
private void RenameTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
IsPrimaryButtonEnabled = !string.IsNullOrEmpty((sender as TextBox)!.Text);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
using The_Untamed_Music_Player.Models;
|
||||
|
||||
namespace The_Untamed_Music_Player.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// 用于指示某个播放列表重命名的消息
|
||||
/// </summary>
|
||||
/// <param name="playlist"></param>
|
||||
public sealed class PlaylistRenameMessage(string oldName, PlaylistInfo playlist)
|
||||
public sealed class PlaylistRenameMessage(string oldName, string newName)
|
||||
{
|
||||
public string OldName { get; } = oldName;
|
||||
public PlaylistInfo Playlist { get; } = playlist;
|
||||
public string NewName { get; } = newName;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,11 @@ public partial class PlaylistInfo
|
||||
ModifiedDate = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仅在创建播放列表时使用
|
||||
/// </summary>
|
||||
/// <param name="songs"></param>
|
||||
/// <returns></returns>
|
||||
public async Task AddSongs(List<IBriefSongInfoBase> songs)
|
||||
{
|
||||
foreach (var song in songs)
|
||||
@@ -293,32 +298,20 @@ public partial class PlaylistInfo
|
||||
}
|
||||
const int canvasSize = 256;
|
||||
|
||||
// 使用BitmapDecoder读取图片文件
|
||||
using var fileStream = new FileStream(
|
||||
imagePath,
|
||||
FileMode.Open,
|
||||
FileAccess.Read
|
||||
);
|
||||
var decoder = await BitmapDecoder.CreateAsync(
|
||||
fileStream.AsRandomAccessStream()
|
||||
// 读取图片文件为字节数组
|
||||
var imageBytes = await File.ReadAllBytesAsync(imagePath);
|
||||
|
||||
// 使用ResizeImageToFitRegionAsync来正确调整图片尺寸
|
||||
var resizedImageBytes = await ResizeImageToFitRegionAsync(
|
||||
imageBytes,
|
||||
canvasSize,
|
||||
canvasSize
|
||||
);
|
||||
|
||||
// 调整图片尺寸到256x256
|
||||
var transform = new BitmapTransform
|
||||
if (resizedImageBytes is null)
|
||||
{
|
||||
ScaledWidth = canvasSize,
|
||||
ScaledHeight = canvasSize,
|
||||
};
|
||||
|
||||
var pixelData = await decoder.GetPixelDataAsync(
|
||||
BitmapPixelFormat.Bgra8,
|
||||
BitmapAlphaMode.Premultiplied,
|
||||
transform,
|
||||
ExifOrientationMode.RespectExifOrientation,
|
||||
ColorManagementMode.DoNotColorManage
|
||||
);
|
||||
|
||||
var pixels = pixelData.DetachPixelData();
|
||||
return;
|
||||
}
|
||||
|
||||
// 切换到UI线程更新WriteableBitmap
|
||||
App.MainWindow?.DispatcherQueue.TryEnqueue(
|
||||
@@ -329,8 +322,7 @@ public partial class PlaylistInfo
|
||||
{
|
||||
// 将像素数据写入WriteableBitmap
|
||||
using var pixelStream = Cover.PixelBuffer.AsStream();
|
||||
await pixelStream.WriteAsync(pixels);
|
||||
|
||||
await pixelStream.WriteAsync(resizedImageBytes);
|
||||
Cover.Invalidate();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -466,7 +458,7 @@ public partial class PlaylistInfo
|
||||
});
|
||||
}
|
||||
|
||||
private static async Task<byte[]?> ResizeImageToFitRegionAsync(
|
||||
public static async Task<byte[]?> ResizeImageToFitRegionAsync(
|
||||
byte[] imageBytes,
|
||||
int targetWidth,
|
||||
int targetHeight
|
||||
|
||||
@@ -75,21 +75,6 @@ public partial class PlaylistLibrary : ObservableRecipient
|
||||
_ = FileManager.SavePlaylistDataAsync(Playlists);
|
||||
}
|
||||
|
||||
public bool RenamePlaylist(PlaylistInfo info, string newName)
|
||||
{
|
||||
var oldName = info.Name;
|
||||
if (string.IsNullOrEmpty(newName) || newName == oldName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var uniqueName = GetUniquePlaylistName(newName);
|
||||
info.Name = uniqueName;
|
||||
Messenger.Send(new HavePlaylistMessage(Playlists.Count > 0));
|
||||
Messenger.Send(new PlaylistRenameMessage(oldName, info));
|
||||
_ = FileManager.SavePlaylistDataAsync(Playlists);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void DeletePlaylist(PlaylistInfo info)
|
||||
{
|
||||
Playlists.Remove(info);
|
||||
@@ -168,7 +153,7 @@ public partial class PlaylistLibrary : ObservableRecipient
|
||||
_ = FileManager.SavePlaylistDataAsync(Playlists);
|
||||
}
|
||||
|
||||
private string GetUniquePlaylistName(string baseName)
|
||||
public string GetUniquePlaylistName(string baseName)
|
||||
{
|
||||
var existingNames = Playlists.AsValueEnumerable().Select(p => p.Name).ToHashSet();
|
||||
if (!existingNames.Contains(baseName))
|
||||
|
||||
@@ -669,8 +669,8 @@
|
||||
<data name="EditAlbumInfoDialog.Title" xml:space="preserve">
|
||||
<value>Edit album info</value>
|
||||
</data>
|
||||
<data name="RenamePlaylistInfoDialog.Title" xml:space="preserve">
|
||||
<value>Rename playlist</value>
|
||||
<data name="EditPlaylistInfoDialog.Title" xml:space="preserve">
|
||||
<value>Edit playlist info</value>
|
||||
</data>
|
||||
<data name="NewPlaylistInfoDialog.Title" xml:space="preserve">
|
||||
<value>Add to new playlist</value>
|
||||
@@ -687,7 +687,7 @@
|
||||
<data name="EditAlbumInfoDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="RenamePlaylistInfoDialog.CloseButtonText" xml:space="preserve">
|
||||
<data name="EditPlaylistInfoDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="NewPlaylistInfoDialog.CloseButtonText" xml:space="preserve">
|
||||
@@ -726,8 +726,8 @@
|
||||
<data name="EditAlbumInfoDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>Save</value>
|
||||
</data>
|
||||
<data name="RenamePlaylistInfoDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>Rename</value>
|
||||
<data name="EditPlaylistInfoDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>Save</value>
|
||||
</data>
|
||||
<data name="NewPlaylistInfoDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>Create</value>
|
||||
|
||||
@@ -669,8 +669,8 @@
|
||||
<data name="EditAlbumInfoDialog.Title" xml:space="preserve">
|
||||
<value>编辑专辑信息</value>
|
||||
</data>
|
||||
<data name="RenamePlaylistInfoDialog.Title" xml:space="preserve">
|
||||
<value>重命名播放列表</value>
|
||||
<data name="EditPlaylistInfoDialog.Title" xml:space="preserve">
|
||||
<value>编辑播放列表信息</value>
|
||||
</data>
|
||||
<data name="NewPlaylistInfoDialog.Title" xml:space="preserve">
|
||||
<value>添加到新建播放列表</value>
|
||||
@@ -687,7 +687,7 @@
|
||||
<data name="EditAlbumInfoDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>取消</value>
|
||||
</data>
|
||||
<data name="RenamePlaylistInfoDialog.CloseButtonText" xml:space="preserve">
|
||||
<data name="EditPlaylistInfoDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>取消</value>
|
||||
</data>
|
||||
<data name="NewPlaylistInfoDialog.CloseButtonText" xml:space="preserve">
|
||||
@@ -726,8 +726,8 @@
|
||||
<data name="EditAlbumInfoDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>保存</value>
|
||||
</data>
|
||||
<data name="RenamePlaylistInfoDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>重命名</value>
|
||||
<data name="EditPlaylistInfoDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>保存</value>
|
||||
</data>
|
||||
<data name="NewPlaylistInfoDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>创建</value>
|
||||
|
||||
@@ -52,12 +52,7 @@ public partial class PlayListDetailViewModel
|
||||
{
|
||||
if (PlaylistName == message.OldName)
|
||||
{
|
||||
Playlist = Data.SelectedPlaylist = message.Playlist;
|
||||
PlaylistName = Playlist.Name;
|
||||
TotalSongNumStr = Playlist.TotalSongNumStr;
|
||||
Cover = Playlist.Cover;
|
||||
SongList = Playlist.SongList;
|
||||
IsPlayAllButtonEnabled = SongList.Count > 0;
|
||||
PlaylistName = message.NewName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,8 +60,6 @@ public partial class PlayListDetailViewModel
|
||||
{
|
||||
if (PlaylistName == message.Playlist.Name)
|
||||
{
|
||||
Playlist = Data.SelectedPlaylist = message.Playlist;
|
||||
PlaylistName = Playlist.Name;
|
||||
TotalSongNumStr = Playlist.TotalSongNumStr;
|
||||
Cover = null;
|
||||
Cover = Playlist.Cover;
|
||||
|
||||
@@ -229,7 +229,7 @@ public partial class PlayQueueViewModel : ObservableObject
|
||||
IsButtonEnabled = PlayQueue.Count > 0;
|
||||
}
|
||||
|
||||
public void PlayqueueListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
|
||||
public void PlayQueueListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
|
||||
{
|
||||
_currentSong = PlayQueue[Data.MusicPlayer.PlayQueueIndex];
|
||||
if (e.Items.Count > 0)
|
||||
@@ -238,7 +238,7 @@ public partial class PlayQueueViewModel : ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayqueueListView_DragOver(object sender, DragEventArgs e)
|
||||
public void PlayQueueListView_DragOver(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.DataView.Contains(StandardDataFormats.StorageItems))
|
||||
{
|
||||
@@ -250,7 +250,7 @@ public partial class PlayQueueViewModel : ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayqueueListView_DragItemsCompleted(
|
||||
public void PlayQueueListView_DragItemsCompleted(
|
||||
object sender,
|
||||
DragItemsCompletedEventArgs args
|
||||
)
|
||||
@@ -277,7 +277,7 @@ public partial class PlayQueueViewModel : ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
public async void PlayqueueListView_Drop(object sender, DragEventArgs e)
|
||||
public async void PlayQueueListView_Drop(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.DataView.Contains(StandardDataFormats.StorageItems))
|
||||
{
|
||||
|
||||
@@ -163,10 +163,10 @@
|
||||
<Setter Target="CoverArt.Height" Value="136"/>
|
||||
<Setter Target="TitleText.FontSize" Value="28"/>
|
||||
<Setter Target="CaptionText.Margin" Value="0,8,0,0"/>
|
||||
<Setter Target="RenameButton.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="EditInfoButton.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="DeleteButton.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="MoreButton.Visibility" Value="Visible"/>
|
||||
<Setter Target="RenameInfoFlyout.Visibility" Value="Visible"/>
|
||||
<Setter Target="EditInfoInfoFlyout.Visibility" Value="Visible"/>
|
||||
<Setter Target="DeleteInfoFlyout.Visibility" Value="Visible"/>
|
||||
<Setter Target="SongListView.Padding" Value="12,0,12,0"/>
|
||||
<Setter Target="SongListView.Margin" Value="0,68,0,0"/>
|
||||
@@ -184,10 +184,10 @@
|
||||
<Setter Target="CoverArt.Height" Value="162"/>
|
||||
<Setter Target="TitleText.FontSize" Value="28"/>
|
||||
<Setter Target="CaptionText.Margin" Value="0,8,0,0"/>
|
||||
<Setter Target="RenameButton.Visibility" Value="Visible"/>
|
||||
<Setter Target="EditInfoButton.Visibility" Value="Visible"/>
|
||||
<Setter Target="DeleteButton.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="MoreButton.Visibility" Value="Visible"/>
|
||||
<Setter Target="RenameInfoFlyout.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="EditInfoInfoFlyout.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="DeleteInfoFlyout.Visibility" Value="Visible"/>
|
||||
<Setter Target="SongListView.Padding" Value="52,0,52,0"/>
|
||||
<Setter Target="SongListView.Margin" Value="0,46,0,0"/>
|
||||
@@ -205,10 +205,10 @@
|
||||
<Setter Target="CoverArt.Height" Value="208"/>
|
||||
<Setter Target="TitleText.FontSize" Value="40"/>
|
||||
<Setter Target="CaptionText.Margin" Value="0,8,0,0"/>
|
||||
<Setter Target="RenameButton.Visibility" Value="Visible"/>
|
||||
<Setter Target="EditInfoButton.Visibility" Value="Visible"/>
|
||||
<Setter Target="DeleteButton.Visibility" Value="Visible"/>
|
||||
<Setter Target="MoreButton.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="RenameInfoFlyout.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="EditInfoInfoFlyout.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="DeleteInfoFlyout.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="SongListView.Padding" Value="52,0,52,0"/>
|
||||
<Setter Target="SongListView.Margin" Value="0,15,0,0"/>
|
||||
@@ -314,14 +314,14 @@
|
||||
<TextBlock x:Uid="Songs_AddTo" FontSize="12"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button x:Name="RenameButton"
|
||||
<Button x:Name="EditInfoButton"
|
||||
Padding="11,9,11,9" HorizontalAlignment="Stretch"
|
||||
Click="RenameButton_Click"
|
||||
Click="EditInfoButton_Click"
|
||||
XYFocusDown="{x:Bind SongListView}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<FontIcon FontFamily="{StaticResource UntamedFontFamily}"
|
||||
FontSize="16" Glyph=""/>
|
||||
<TextBlock x:Uid="PlayLists_Rename" FontSize="12"/>
|
||||
FontSize="16" Glyph=""/>
|
||||
<TextBlock x:Uid="Songs_EditInfo" FontSize="12"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button x:Name="DeleteButton"
|
||||
@@ -338,11 +338,11 @@
|
||||
Padding="11,9,11,9" HorizontalAlignment="Stretch">
|
||||
<Button.Flyout>
|
||||
<MenuFlyout Placement="Bottom">
|
||||
<MenuFlyoutItem x:Name="RenameInfoFlyout" x:Uid="PlayLists_Rename"
|
||||
<MenuFlyoutItem x:Name="EditInfoInfoFlyout" x:Uid="Songs_EditInfo"
|
||||
Width="158"
|
||||
Click="RenameButton_Click"
|
||||
Click="EditInfoButton_Click"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource UntamedFontFamily},
|
||||
Glyph=}"/>
|
||||
Glyph=}"/>
|
||||
<MenuFlyoutItem x:Name="DeleteInfoFlyout" x:Uid="PlayLists_Delete"
|
||||
Width="158"
|
||||
Click="{x:Bind ViewModel.DeleteButton_Click}"
|
||||
|
||||
@@ -289,9 +289,9 @@ public sealed partial class PlayListDetailPage : Page
|
||||
}
|
||||
}
|
||||
|
||||
private async void RenameButton_Click(object sender, RoutedEventArgs e)
|
||||
private async void EditInfoButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dialog = new RenamePlaylistInfoDialog(ViewModel.Playlist) { XamlRoot = XamlRoot };
|
||||
var dialog = new EditPlaylistInfoDialog(ViewModel.Playlist) { XamlRoot = XamlRoot };
|
||||
await dialog.ShowAsync();
|
||||
}
|
||||
|
||||
|
||||
@@ -49,10 +49,10 @@
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource UntamedFontFamily},
|
||||
Glyph=}"/>
|
||||
</MenuFlyoutSubItem>
|
||||
<MenuFlyoutItem x:Uid="PlayLists_Rename"
|
||||
Click="RenameButton_Click"
|
||||
<MenuFlyoutItem x:Uid="Songs_EditInfo"
|
||||
Click="EditInfoButton_Click"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource UntamedFontFamily},
|
||||
Glyph=}"/>
|
||||
Glyph=}"/>
|
||||
<MenuFlyoutItem x:Uid="PlayLists_Delete"
|
||||
Click="DeleteButton_Click"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource UntamedFontFamily},
|
||||
@@ -119,10 +119,10 @@
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource UntamedFontFamily},
|
||||
Glyph=}"/>
|
||||
</MenuFlyoutSubItem>
|
||||
<MenuFlyoutItem x:Uid="PlayLists_Rename"
|
||||
Click="RenameButton_Click"
|
||||
<MenuFlyoutItem x:Uid="Songs_EditInfo"
|
||||
Click="EditInfoButton_Click"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource UntamedFontFamily},
|
||||
Glyph=}"/>
|
||||
Glyph=}"/>
|
||||
<MenuFlyoutItem x:Uid="PlayLists_Delete"
|
||||
Click="DeleteButton_Click"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource UntamedFontFamily},
|
||||
|
||||
@@ -195,11 +195,11 @@ public sealed partial class PlayListsPage : Page
|
||||
}
|
||||
}
|
||||
|
||||
private async void RenameButton_Click(object sender, RoutedEventArgs e)
|
||||
private async void EditInfoButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is FrameworkElement { DataContext: PlaylistInfo info })
|
||||
{
|
||||
var dialog = new RenamePlaylistInfoDialog(info) { XamlRoot = XamlRoot };
|
||||
var dialog = new EditPlaylistInfoDialog(info) { XamlRoot = XamlRoot };
|
||||
await dialog.ShowAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
<Setter Target="AddToButton.Width" Value="68"/>
|
||||
<Setter Target="ClearTextBlock.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="AddToTextBlock.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="PlayqueueListView.Padding" Value="12,0,12,0"/>
|
||||
<Setter Target="PlayQueueListView.Padding" Value="12,0,12,0"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Normal">
|
||||
@@ -200,7 +200,7 @@
|
||||
<Setter Target="MenuPanel.Margin" Value="56,22,56,0"/>
|
||||
<Setter Target="ClearTextBlock.Visibility" Value="Visible"/>
|
||||
<Setter Target="AddToTextBlock.Visibility" Value="Visible"/>
|
||||
<Setter Target="PlayqueueListView.Padding" Value="52,0,52,0"/>
|
||||
<Setter Target="PlayQueueListView.Padding" Value="52,0,52,0"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
@@ -341,7 +341,7 @@
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<ListView x:Name="PlayqueueListView"
|
||||
<ListView x:Name="PlayQueueListView"
|
||||
Grid.Row="2"
|
||||
Margin="0,22,0,0"
|
||||
helper:CurrentSongHighlightExtensions.IsPlayQueue="True"
|
||||
@@ -351,10 +351,10 @@
|
||||
helper:ListViewExtensions.ItemMargin="0,3,0,3"
|
||||
AllowDrop="True" CanDragItems="True"
|
||||
CanReorderItems="True"
|
||||
DragItemsCompleted="{x:Bind ViewModel.PlayqueueListView_DragItemsCompleted}"
|
||||
DragItemsStarting="{x:Bind ViewModel.PlayqueueListView_DragItemsStarting}"
|
||||
DragOver="{x:Bind ViewModel.PlayqueueListView_DragOver}"
|
||||
Drop="{x:Bind ViewModel.PlayqueueListView_Drop}"
|
||||
DragItemsCompleted="{x:Bind ViewModel.PlayQueueListView_DragItemsCompleted}"
|
||||
DragItemsStarting="{x:Bind ViewModel.PlayQueueListView_DragItemsStarting}"
|
||||
DragOver="{x:Bind ViewModel.PlayQueueListView_DragOver}"
|
||||
Drop="{x:Bind ViewModel.PlayQueueListView_Drop}"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="{x:Bind ViewModel.PlayQueueListView_ItemClick}"
|
||||
ItemTemplate="{StaticResource PlayQueueListViewTemplate}"
|
||||
|
||||
@@ -102,7 +102,7 @@ public sealed partial class PlayQueuePage : Page
|
||||
{
|
||||
return;
|
||||
}
|
||||
var listViewSource = PlayqueueListView.ItemsSource;
|
||||
var listViewSource = PlayQueueListView.ItemsSource;
|
||||
if (listViewSource is IEnumerable<IndexedPlayQueueSong> songs)
|
||||
{
|
||||
var targetSong = currentSong switch
|
||||
@@ -119,7 +119,7 @@ public sealed partial class PlayQueuePage : Page
|
||||
};
|
||||
if (targetSong is not null)
|
||||
{
|
||||
PlayqueueListView.ScrollIntoView(targetSong, ScrollIntoViewAlignment.Leading);
|
||||
PlayQueueListView.ScrollIntoView(targetSong, ScrollIntoViewAlignment.Leading);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user