Added playlists view. Added messaging service. Added logic for adding and deleting playlists.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using Harmonia.Core.Extensions;
|
||||
using Harmonia.WinUI.Caching;
|
||||
using Harmonia.WinUI.Messaging;
|
||||
using Harmonia.WinUI.Storage;
|
||||
using Harmonia.WinUI.ViewModels;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -23,10 +24,12 @@ public partial class App : Application
|
||||
//services.AddSingleton<MainViewModel>();
|
||||
services.AddSingleton<PlayerViewModel>();
|
||||
services.AddSingleton<PlayingSongViewModel>();
|
||||
services.AddSingleton<PlaylistsViewModel>();
|
||||
services.AddSingleton<PlaylistDetailViewModel>();
|
||||
|
||||
services.AddSingleton<IAudioBitmapImageCache, AudioBitmapImageCache>();
|
||||
services.AddSingleton<IStorageProvider, WindowsStorageProvider>();
|
||||
services.AddSingleton<IMessageService, WindowsMessageService>();
|
||||
|
||||
services.AddHarmonia();
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\Styles.xaml" />
|
||||
<None Remove="Views\PlayerView.xaml" />
|
||||
<None Remove="Views\PlaylistsView.xaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -55,6 +56,11 @@
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\PlaylistsView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Resources\Geometry.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
|
||||
@@ -46,9 +46,11 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition></ColumnDefinition>
|
||||
<ColumnDefinition></ColumnDefinition>
|
||||
<ColumnDefinition></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<views:PlayingSongView Grid.Column="0"></views:PlayingSongView>
|
||||
<views:PlaylistDetailView Grid.Column="1"></views:PlaylistDetailView>
|
||||
<views:PlaylistsView Grid.Column="1"></views:PlaylistsView>
|
||||
<views:PlaylistDetailView Grid.Column="2"></views:PlaylistDetailView>
|
||||
</Grid>
|
||||
<views:PlayerView Grid.Row="2"></views:PlayerView>
|
||||
</Grid>
|
||||
|
||||
8
Harmonia.WinUI/Messaging/IMessageService.cs
Normal file
8
Harmonia.WinUI/Messaging/IMessageService.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Harmonia.WinUI.Messaging;
|
||||
|
||||
public interface IMessageService
|
||||
{
|
||||
Task<bool> ConfirmAsync(string title, string message);
|
||||
}
|
||||
30
Harmonia.WinUI/Messaging/WindowsMessageService.cs
Normal file
30
Harmonia.WinUI/Messaging/WindowsMessageService.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Harmonia.WinUI.Messaging;
|
||||
|
||||
public class WindowsMessageService : IMessageService
|
||||
{
|
||||
private static MainWindow MainWindow => App.ServiceProvider.GetRequiredService<MainWindow>();
|
||||
|
||||
public async Task<bool> ConfirmAsync(string title, string message)
|
||||
{
|
||||
ContentDialog dialog = new()
|
||||
{
|
||||
XamlRoot = MainWindow.Content.XamlRoot,
|
||||
Style = Application.Current.Resources["DefaultContentDialogStyle"] as Style,
|
||||
Title = title,
|
||||
Content = message,
|
||||
PrimaryButtonText = "Yes",
|
||||
CloseButtonText = "No",
|
||||
DefaultButton = ContentDialogButton.Primary
|
||||
};
|
||||
|
||||
var result = await dialog.ShowAsync();
|
||||
|
||||
return result == ContentDialogResult.Primary;
|
||||
}
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3m5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3m5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3
|
||||
</x:String>
|
||||
|
||||
<x:String x:Key="MusicNoteList">
|
||||
M12 13c0 1.105-1.12 2-2.5 2S7 14.105 7 13s1.12-2 2.5-2 2.5.895 2.5 2
|
||||
M12 3v10h-1V3z
|
||||
M11 2.82a1 1 0 0 1 .804-.98l3-.6A1 1 0 0 1 16 2.22V4l-5 1z
|
||||
M0 11.5a.5.5 0 0 1 .5-.5H4a.5.5 0 0 1 0 1H.5a.5.5 0 0 1-.5-.5m0-4A.5.5 0 0 1 .5 7H8a.5.5 0 0 1 0 1H.5a.5.5 0 0 1-.5-.5m0-4A.5.5 0 0 1 .5 3H8a.5.5 0 0 1 0 1H.5a.5.5 0 0 1-.5-.5
|
||||
</x:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -20,6 +20,139 @@
|
||||
<Setter Property="FontFamily" Value="Lexend,Noto Sans JP" />
|
||||
</Style>
|
||||
|
||||
<!-- Premium Palette (from Harmonia icon set) -->
|
||||
<LinearGradientBrush x:Key="PremiumGoldGradient" StartPoint="0,0" EndPoint="0,1">
|
||||
<GradientStop Color="#E9CFA3" Offset="0"/>
|
||||
<GradientStop Color="#C7A468" Offset="0.5"/>
|
||||
<GradientStop Color="#8A6D42" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
|
||||
<LinearGradientBrush x:Key="PremiumTileGradient" StartPoint="0,0" EndPoint="0,1">
|
||||
<GradientStop Color="#2B2830" Offset="0"/>
|
||||
<GradientStop Color="#1E1B22" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
|
||||
<SolidColorBrush x:Key="PremiumForegroundBrush" Color="#E9CFA3"/>
|
||||
|
||||
<!-- Accent: Teal (Shuffle / Repeat) -->
|
||||
<LinearGradientBrush x:Key="PremiumTealGradient" StartPoint="0,0" EndPoint="0,1">
|
||||
<GradientStop Color="#A8DFD3" Offset="0"/>
|
||||
<GradientStop Color="#6FBFAE" Offset="0.5"/>
|
||||
<GradientStop Color="#3E7A6C" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
|
||||
<LinearGradientBrush x:Key="PremiumTealTileGradient" StartPoint="0,0" EndPoint="0,1">
|
||||
<GradientStop Color="#26302D" Offset="0"/>
|
||||
<GradientStop Color="#1A211F" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
|
||||
<SolidColorBrush x:Key="PremiumTealForegroundBrush" Color="#A8DFD3"/>
|
||||
|
||||
<!-- Accent: Lavender (Previous / Next) -->
|
||||
<LinearGradientBrush x:Key="PremiumLavenderGradient" StartPoint="0,0" EndPoint="0,1">
|
||||
<GradientStop Color="#CBB8EF" Offset="0"/>
|
||||
<GradientStop Color="#A78FD6" Offset="0.5"/>
|
||||
<GradientStop Color="#6C5799" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
|
||||
<LinearGradientBrush x:Key="PremiumLavenderTileGradient" StartPoint="0,0" EndPoint="0,1">
|
||||
<GradientStop Color="#2A2733" Offset="0"/>
|
||||
<GradientStop Color="#1D1B24" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
|
||||
<SolidColorBrush x:Key="PremiumLavenderForegroundBrush" Color="#CBB8EF"/>
|
||||
|
||||
<!-- Accent: Pink (Radio / Podcasts) -->
|
||||
<LinearGradientBrush x:Key="PremiumPinkGradient" StartPoint="0,0" EndPoint="0,1">
|
||||
<GradientStop Color="#EFB8C8" Offset="0"/>
|
||||
<GradientStop Color="#D68FA8" Offset="0.5"/>
|
||||
<GradientStop Color="#99576E" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
|
||||
<LinearGradientBrush x:Key="PremiumPinkTileGradient" StartPoint="0,0" EndPoint="0,1">
|
||||
<GradientStop Color="#332730" Offset="0"/>
|
||||
<GradientStop Color="#241B21" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
|
||||
<SolidColorBrush x:Key="PremiumPinkForegroundBrush" Color="#EFB8C8"/>
|
||||
|
||||
<!-- Premium Button -->
|
||||
<Style x:Key="PremiumButton" TargetType="Button">
|
||||
<Setter Property="Foreground" Value="{StaticResource PremiumForegroundBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{StaticResource PremiumGoldGradient}"/>
|
||||
<Setter Property="Background" Value="{StaticResource PremiumTileGradient}"/>
|
||||
<Setter Property="Padding" Value="14,8"/>
|
||||
<Setter Property="CornerRadius" Value="12"/>
|
||||
<Setter Property="FontFamily" Value="Lexend,Noto Sans JP"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<!-- Outer gradient acts as the border ring -->
|
||||
<Grid x:Name="Root"
|
||||
Background="{TemplateBinding BorderBrush}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Padding="1.5">
|
||||
<Grid x:Name="Inner"
|
||||
Background="{TemplateBinding Background}"
|
||||
CornerRadius="10">
|
||||
<ContentPresenter x:Name="ContentPresenter"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||
</Grid>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal"/>
|
||||
<VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Inner.Opacity" Value="0.88"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Inner.Opacity" Value="0.75"/>
|
||||
<Setter Target="Root.Opacity" Value="0.9"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Root.Opacity" Value="0.4"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- Premium Button (Teal) -->
|
||||
<Style x:Key="PremiumButton-Teal" TargetType="Button" BasedOn="{StaticResource PremiumButton}">
|
||||
<Setter Property="Foreground" Value="{StaticResource PremiumTealForegroundBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{StaticResource PremiumTealGradient}"/>
|
||||
<Setter Property="Background" Value="{StaticResource PremiumTealTileGradient}"/>
|
||||
</Style>
|
||||
|
||||
<!-- Premium Button (Lavender) -->
|
||||
<Style x:Key="PremiumButton-Lavender" TargetType="Button" BasedOn="{StaticResource PremiumButton}">
|
||||
<Setter Property="Foreground" Value="{StaticResource PremiumLavenderForegroundBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{StaticResource PremiumLavenderGradient}"/>
|
||||
<Setter Property="Background" Value="{StaticResource PremiumLavenderTileGradient}"/>
|
||||
</Style>
|
||||
|
||||
<!-- Premium Button (Pink) -->
|
||||
<Style x:Key="PremiumButton-Pink" TargetType="Button" BasedOn="{StaticResource PremiumButton}">
|
||||
<Setter Property="Foreground" Value="{StaticResource PremiumPinkForegroundBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{StaticResource PremiumPinkGradient}"/>
|
||||
<Setter Property="Background" Value="{StaticResource PremiumPinkTileGradient}"/>
|
||||
</Style>
|
||||
|
||||
<!-- Flat Button -->
|
||||
<Style x:Key="FlatButton" TargetType="Button">
|
||||
<Setter Property="Padding" Value="10"/>
|
||||
|
||||
@@ -7,6 +7,7 @@ using Harmonia.Core.Player;
|
||||
using Harmonia.Core.Playlists;
|
||||
using Harmonia.Core.Scanner;
|
||||
using Harmonia.WinUI.Caching;
|
||||
using Harmonia.WinUI.Messaging;
|
||||
using Harmonia.WinUI.Storage;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using System;
|
||||
@@ -36,6 +37,7 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
||||
private readonly IAudioFileScanner _audioFileScanner;
|
||||
private readonly IAudioEngine _audioEngine;
|
||||
private readonly IStorageProvider _storageProvider;
|
||||
private readonly IMessageService _messageService;
|
||||
private readonly DispatcherQueue _dispatcherQueue;
|
||||
private readonly ConcurrentDictionary<int, CancellationTokenSource> _imageCancellationTokens = [];
|
||||
|
||||
@@ -100,6 +102,7 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
||||
}
|
||||
|
||||
public ICommand PlaySongCommand => new AsyncRelayCommand(PlaySongAsync, AreSongsSelected);
|
||||
public ICommand NewPlaylistCommand => new AsyncRelayCommand(NewPlaylistAsync);
|
||||
public ICommand AddFilesCommand => new AsyncRelayCommand(AddFilesAsync);
|
||||
public ICommand AddFolderCommand => new AsyncRelayCommand(AddFolderAsync);
|
||||
public ICommand RemoveSongsCommand => new RelayCommand(RemoveSongs, AreSongsSelected);
|
||||
@@ -110,6 +113,7 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
||||
public ICommand RefreshTagsCommand => new RelayCommand(RefreshTags);
|
||||
public ICommand RemoveMissingSongsCommand => new RelayCommand(RemoveMissingSongs);
|
||||
public ICommand RemoveDuplicateSongsCommand => new RelayCommand(RemoveDuplicateSongs);
|
||||
public ICommand DeletePlaylistCommand => new AsyncRelayCommand(DeletePlaylistAsync);
|
||||
|
||||
public bool IsUserUpdating { get; set; }
|
||||
private bool _isUserInitiatingSongChange;
|
||||
@@ -125,10 +129,11 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
||||
IAudioFileScanner audioFileScanner,
|
||||
IAudioEngine audioEngine,
|
||||
IStorageProvider storageProvider,
|
||||
IPlaylistManager playlistManager)
|
||||
IPlaylistManager playlistManager,
|
||||
IMessageService messageService)
|
||||
{
|
||||
_playlistManager = playlistManager;
|
||||
//_playlistManager.CurrentPlaylistChanged += OnPlaylistChanged;
|
||||
_playlistManager.CurrentPlaylistChanged += OnPlaylistChanged;
|
||||
|
||||
_audioPlayer = audioPlayer;
|
||||
_audioPlayer.PlaylistChanged += OnPlaylistChanged;
|
||||
@@ -139,6 +144,7 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
||||
_audioFileScanner = audioFileScanner;
|
||||
_audioEngine = audioEngine;
|
||||
_storageProvider = storageProvider;
|
||||
_messageService = messageService;
|
||||
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
FilteredPlaylistSongs.CollectionChanged += OnFilteredPlaylistSongsCollectionChanged;
|
||||
@@ -185,7 +191,8 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
||||
private void OnPlaylistChanged(object? sender, EventArgs e)
|
||||
{
|
||||
Playlist?.PlaylistUpdated -= OnPlaylistUpdated;
|
||||
Playlist = _audioPlayer.Playlist;
|
||||
//Playlist = _audioPlayer.Playlist;
|
||||
Playlist = _playlistManager.CurrentPlaylist;
|
||||
Playlist?.PlaylistUpdated += OnPlaylistUpdated;
|
||||
|
||||
UpdateFilteredSongs();
|
||||
@@ -369,6 +376,12 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
||||
return SelectedPlaylistSongs.Count > 0;
|
||||
}
|
||||
|
||||
private async Task NewPlaylistAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
Playlist playlist = await _playlistManager.AddPlaylistAsync();
|
||||
_playlistManager.CurrentPlaylist = playlist;
|
||||
}
|
||||
|
||||
private async Task AddFilesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (Playlist == null)
|
||||
@@ -535,5 +548,30 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
||||
Playlist?.RemoveDuplicateSongs();
|
||||
}
|
||||
|
||||
private async Task DeletePlaylistAsync()
|
||||
{
|
||||
if (Playlist == null)
|
||||
return;
|
||||
|
||||
bool confirmed = await _messageService.ConfirmAsync($"Delete Playlist - {Playlist.Name}", "Are you sure you want to delete this playlist?");
|
||||
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
_playlistManager.RemovePlaylist(Playlist);
|
||||
|
||||
if (_playlistManager.CurrentPlaylist == Playlist)
|
||||
{
|
||||
if (_playlistManager.Playlists.Count > 0)
|
||||
{
|
||||
_playlistManager.CurrentPlaylist = _playlistManager.Playlists.ElementAt(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_playlistManager.CurrentPlaylist = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
65
Harmonia.WinUI/ViewModels/PlaylistsViewModel.cs
Normal file
65
Harmonia.WinUI/ViewModels/PlaylistsViewModel.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using Harmonia.Core.Playlists;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Harmonia.WinUI.ViewModels;
|
||||
|
||||
public partial class PlaylistsViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IPlaylistManager _playlistManager;
|
||||
|
||||
private ObservableCollection<Playlist> _playlists = [];
|
||||
public ObservableCollection<Playlist> Playlists
|
||||
{
|
||||
get
|
||||
{
|
||||
return _playlists;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetProperty(ref _playlists, value);
|
||||
}
|
||||
}
|
||||
|
||||
private Playlist? _selectedPlaylist = null;
|
||||
public Playlist? SelectedPlaylist
|
||||
{
|
||||
get
|
||||
{
|
||||
return _selectedPlaylist;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedPlaylist, value))
|
||||
{
|
||||
_playlistManager.CurrentPlaylist = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PlaylistsViewModel(IPlaylistManager playlistManager)
|
||||
{
|
||||
_playlistManager = playlistManager;
|
||||
_playlistManager.PlaylistAdded += OnPlaylistAdded;
|
||||
_playlistManager.PlaylistRemoved += OnPlaylistRemoved;
|
||||
_playlistManager.CurrentPlaylistChanged += OnCurrentPlaylistChanged;
|
||||
|
||||
_playlists = new(_playlistManager.Playlists);
|
||||
_selectedPlaylist = _playlistManager.CurrentPlaylist;
|
||||
}
|
||||
|
||||
private void OnCurrentPlaylistChanged(object? sender, EventArgs e)
|
||||
{
|
||||
SelectedPlaylist = _playlistManager.CurrentPlaylist;
|
||||
}
|
||||
|
||||
private void OnPlaylistAdded(object? sender, PlaylistAddedEventArgs e)
|
||||
{
|
||||
Playlists.Add(e.Playlist);
|
||||
}
|
||||
|
||||
private void OnPlaylistRemoved(object? sender, PlaylistRemovedEventArgs e)
|
||||
{
|
||||
Playlists.Remove(e.Playlist);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,9 @@ public class ViewModelLocator
|
||||
public static PlayingSongViewModel PlayingSongViewModel
|
||||
=> App.ServiceProvider.GetRequiredService<PlayingSongViewModel>();
|
||||
|
||||
public static PlaylistsViewModel PlaylistsViewModel
|
||||
=> App.ServiceProvider.GetRequiredService<PlaylistsViewModel>();
|
||||
|
||||
public static PlaylistDetailViewModel PlaylistDetailViewModel
|
||||
=> App.ServiceProvider.GetRequiredService<PlaylistDetailViewModel>();
|
||||
}
|
||||
@@ -123,6 +123,11 @@
|
||||
<Setter Property="Background" Value="Transparent"></Setter>
|
||||
</Style>
|
||||
</MenuFlyout.MenuFlyoutPresenterStyle>
|
||||
<MenuFlyoutItem Text="New Playlist" Command="{Binding NewPlaylistCommand}">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<PathIcon Data="{StaticResource AddFileIcon}"></PathIcon>
|
||||
</MenuFlyoutItem.Icon>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Text="Add Files..." Command="{Binding AddFilesCommand}">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<PathIcon Data="{StaticResource AddFileIcon}"></PathIcon>
|
||||
@@ -167,7 +172,7 @@
|
||||
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutSeparator></MenuFlyoutSeparator>
|
||||
<MenuFlyoutItem Text="Remove Playlist" Foreground="#ff99a4">
|
||||
<MenuFlyoutItem Text="Remove Playlist" Foreground="#ff99a4" Command="{Binding DeletePlaylistCommand}">
|
||||
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutSeparator></MenuFlyoutSeparator>
|
||||
@@ -177,6 +182,12 @@
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
<!--<Button Style="{StaticResource PremiumButton-Teal}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<PathIcon Style="{StaticResource FlatButtonIcon}" Foreground="{StaticResource PremiumTeaForegroundBrush}" Data="{StaticResource AddIcon}" />
|
||||
<TextBlock Text="Go Premium"/>
|
||||
</StackPanel>
|
||||
</Button>-->
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<ListView
|
||||
|
||||
31
Harmonia.WinUI/Views/PlaylistsView.xaml
Normal file
31
Harmonia.WinUI/Views/PlaylistsView.xaml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<UserControl
|
||||
x:Class="Harmonia.WinUI.Views.PlaylistsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:Harmonia.WinUI.Views"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:Harmonia.WinUI.ViewModels"
|
||||
xmlns:playlists="using:Harmonia.Core.Playlists"
|
||||
DataContext="{Binding Source={StaticResource Locator}, Path=PlaylistsViewModel}"
|
||||
d:DataContext="{d:DesignInstance Type=vm:PlaylistsViewModel, IsDesignTimeCreatable=True}"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<DataTemplate x:Key="PlaylistTemplate" x:DataType="playlists:Playlist">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8" VerticalAlignment="Bottom">
|
||||
<Viewbox Height="24" Width="24">
|
||||
<PathIcon Data="{StaticResource MusicNoteList}" />
|
||||
</Viewbox>
|
||||
<TextBlock Text="{x:Bind Name}" FontSize="16" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</UserControl.Resources>
|
||||
<Grid Margin="10">
|
||||
<ListView
|
||||
ItemsSource="{Binding Playlists, Mode=OneWay}"
|
||||
SelectedItem="{Binding SelectedPlaylist, Mode=TwoWay}"
|
||||
ItemTemplate="{StaticResource PlaylistTemplate}">
|
||||
</ListView>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
12
Harmonia.WinUI/Views/PlaylistsView.xaml.cs
Normal file
12
Harmonia.WinUI/Views/PlaylistsView.xaml.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Harmonia.WinUI.Views;
|
||||
|
||||
public sealed partial class PlaylistsView : UserControl
|
||||
{
|
||||
public PlaylistsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user