Added playlist view.
This commit is contained in:
BIN
Harmonia.WinUI/Assets/Default.png
Normal file
BIN
Harmonia.WinUI/Assets/Default.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net9.0-windows10.0.19041.0</TargetFramework>
|
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework>
|
||||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||||
<RootNamespace>Harmonia.WinUI</RootNamespace>
|
<RootNamespace>Harmonia.WinUI</RootNamespace>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||||
|
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.1.240916" />
|
||||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" />
|
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" />
|
||||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250310001" />
|
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250310001" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@@ -59,6 +60,9 @@
|
|||||||
<Page Update="Resources\Converters.xaml">
|
<Page Update="Resources\Converters.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Update="Views\PlaylistView.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
<Page Update="Views\PlayerView.xaml">
|
<Page Update="Views\PlayerView.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="using:Harmonia.WinUI"
|
xmlns:local="using:Harmonia.WinUI"
|
||||||
xmlns:views="using:Harmonia.WinUI.Views"
|
xmlns:views="using:Harmonia.WinUI.Views"
|
||||||
|
xmlns:Media="using:CommunityToolkit.WinUI.Media"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
@@ -18,6 +19,22 @@
|
|||||||
<RowDefinition Height="*"></RowDefinition>
|
<RowDefinition Height="*"></RowDefinition>
|
||||||
<RowDefinition Height="Auto"></RowDefinition>
|
<RowDefinition Height="Auto"></RowDefinition>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
<Grid Grid.RowSpan="2">
|
||||||
|
<Image Source="/Assets/Default.png" Stretch="UniformToFill" VerticalAlignment="Center" HorizontalAlignment="Center"></Image>
|
||||||
|
<Canvas Background="#99000000"></Canvas>
|
||||||
|
<Border>
|
||||||
|
<Border.Background>
|
||||||
|
<Media:BackdropBlurBrush Amount="20"></Media:BackdropBlurBrush>
|
||||||
|
</Border.Background>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
<Grid Grid.Row="0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition></ColumnDefinition>
|
||||||
|
<ColumnDefinition></ColumnDefinition>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<views:PlaylistView Grid.Column="1"></views:PlaylistView>
|
||||||
|
</Grid>
|
||||||
<!--<views:PlayingSongInfo Grid.Row="0"></views:PlayingSongInfo>-->
|
<!--<views:PlayingSongInfo Grid.Row="0"></views:PlayingSongInfo>-->
|
||||||
<views:PlayerView Grid.Row="1"></views:PlayerView>
|
<views:PlayerView Grid.Row="1"></views:PlayerView>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,36 +1,11 @@
|
|||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
|
||||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
|
||||||
using Microsoft.UI.Xaml.Data;
|
|
||||||
using Microsoft.UI.Xaml.Input;
|
|
||||||
using Microsoft.UI.Xaml.Media;
|
|
||||||
using Microsoft.UI.Xaml.Navigation;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
|
|
||||||
// To learn more about WinUI, the WinUI project structure,
|
namespace Harmonia.WinUI;
|
||||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
|
||||||
|
|
||||||
namespace Harmonia.WinUI
|
public sealed partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
/// <summary>
|
public MainWindow()
|
||||||
/// An empty window that can be used on its own or navigated to within a Frame.
|
|
||||||
/// </summary>
|
|
||||||
public sealed partial class MainWindow : Window
|
|
||||||
{
|
{
|
||||||
public MainWindow()
|
InitializeComponent();
|
||||||
{
|
|
||||||
this.InitializeComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void myButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
//myButton.Content = "Clicked";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,4 +122,13 @@
|
|||||||
M11 1a2 2 0 0 0-2 2v4a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h5V3a3 3 0 0 1 6 0v4a.5.5 0 0 1-1 0V3a2 2 0 0 0-2-2M3 8a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1z
|
M11 1a2 2 0 0 0-2 2v4a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h5V3a3 3 0 0 1 6 0v4a.5.5 0 0 1-1 0V3a2 2 0 0 0-2-2M3 8a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1z
|
||||||
</x:String>
|
</x:String>
|
||||||
|
|
||||||
|
<x:String x:Key="AddIcon">
|
||||||
|
M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4
|
||||||
|
</x:String>
|
||||||
|
|
||||||
|
<x:String x:Key="MoreIcon">
|
||||||
|
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>
|
||||||
|
|
||||||
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|||||||
@@ -10,6 +10,11 @@
|
|||||||
<Setter Property="BorderThickness" Value="0"/>
|
<Setter Property="BorderThickness" Value="0"/>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<!-- Flat Round Button -->
|
||||||
|
<Style x:Key="FlatRoundButton" TargetType="Button" BasedOn="{StaticResource FlatButton}">
|
||||||
|
<Setter Property="CornerRadius" Value="32"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
<!-- Flat Button Path Icon -->
|
<!-- Flat Button Path Icon -->
|
||||||
<Style x:Key="FlatButtonIcon" TargetType="PathIcon">
|
<Style x:Key="FlatButtonIcon" TargetType="PathIcon">
|
||||||
<Setter Property="Width" Value="18"/>
|
<Setter Property="Width" Value="18"/>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace Harmonia.WinUI.Storage;
|
|||||||
|
|
||||||
public interface IStorageProvider
|
public interface IStorageProvider
|
||||||
{
|
{
|
||||||
public Task<string> GetFileAsync(FilePickerOptions? options = null);
|
public Task<string?> GetSingleFileAsync(FilePickerOptions? options = null);
|
||||||
public Task<string[]> GetFilesAsync(FilePickerOptions? options = null);
|
public Task<string[]> GetFilesAsync(FilePickerOptions? options = null);
|
||||||
public Task<string> GetPathAsync();
|
public Task<string?> GetPathAsync();
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -7,16 +8,18 @@ using Windows.Storage.Pickers;
|
|||||||
|
|
||||||
namespace Harmonia.WinUI.Storage;
|
namespace Harmonia.WinUI.Storage;
|
||||||
|
|
||||||
public class WindowsStorageProvider(MainWindow mainWindow) : IStorageProvider
|
public class WindowsStorageProvider : IStorageProvider
|
||||||
{
|
{
|
||||||
public async Task<string> GetFileAsync(FilePickerOptions? options = null)
|
private static MainWindow MainWindow => App.ServiceProvider.GetRequiredService<MainWindow>();
|
||||||
|
|
||||||
|
public async Task<string?> GetSingleFileAsync(FilePickerOptions? options = null)
|
||||||
{
|
{
|
||||||
FileOpenPicker fileOpenPicker = GetFileOpenPicker(options);
|
FileOpenPicker fileOpenPicker = GetFileOpenPicker(options);
|
||||||
InitializePicker(fileOpenPicker);
|
InitializePicker(fileOpenPicker);
|
||||||
|
|
||||||
StorageFile storageFile = await fileOpenPicker.PickSingleFileAsync();
|
StorageFile? storageFile = await fileOpenPicker.PickSingleFileAsync();
|
||||||
|
|
||||||
return storageFile.Path;
|
return storageFile?.Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string[]> GetFilesAsync(FilePickerOptions? options = null)
|
public async Task<string[]> GetFilesAsync(FilePickerOptions? options = null)
|
||||||
@@ -67,7 +70,7 @@ public class WindowsStorageProvider(MainWindow mainWindow) : IStorageProvider
|
|||||||
return [.. fileTypes.SelectMany(fileType => fileType.Patterns)];
|
return [.. fileTypes.SelectMany(fileType => fileType.Patterns)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetPathAsync()
|
public async Task<string?> GetPathAsync()
|
||||||
{
|
{
|
||||||
var folderPicker = new FolderPicker
|
var folderPicker = new FolderPicker
|
||||||
{
|
{
|
||||||
@@ -77,14 +80,14 @@ public class WindowsStorageProvider(MainWindow mainWindow) : IStorageProvider
|
|||||||
|
|
||||||
InitializePicker(folderPicker);
|
InitializePicker(folderPicker);
|
||||||
|
|
||||||
StorageFolder folder = await folderPicker.PickSingleFolderAsync();
|
StorageFolder? folder = await folderPicker.PickSingleFolderAsync();
|
||||||
|
|
||||||
return folder.Path;
|
return folder?.Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializePicker(object target)
|
private static void InitializePicker(object target)
|
||||||
{
|
{
|
||||||
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(mainWindow);
|
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(MainWindow);
|
||||||
WinRT.Interop.InitializeWithWindow.Initialize(target, hWnd);
|
WinRT.Interop.InitializeWithWindow.Initialize(target, hWnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using Harmonia.Core.Engine;
|
||||||
using Harmonia.Core.Models;
|
using Harmonia.Core.Models;
|
||||||
using Harmonia.Core.Player;
|
using Harmonia.Core.Player;
|
||||||
using Harmonia.WinUI.Caching;
|
using Harmonia.WinUI.Caching;
|
||||||
@@ -7,6 +8,7 @@ using Microsoft.UI.Dispatching;
|
|||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Media.Imaging;
|
using Microsoft.UI.Xaml.Media.Imaging;
|
||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
@@ -196,6 +198,7 @@ public partial class PlayerViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
_audioPlayer = audioPlayer;
|
_audioPlayer = audioPlayer;
|
||||||
_audioPlayer.PlayingSongChanged += OnPlayingSongChanged;
|
_audioPlayer.PlayingSongChanged += OnPlayingSongChanged;
|
||||||
|
_audioPlayer.PropertyChanged += OnAudioPlayerPropertyChanged;
|
||||||
|
|
||||||
_audioBitmapImageCache = audioBitmapCache;
|
_audioBitmapImageCache = audioBitmapCache;
|
||||||
|
|
||||||
@@ -232,6 +235,28 @@ public partial class PlayerViewModel : ViewModelBase
|
|||||||
DispatcherQueue.GetForCurrentThread().TryEnqueue(() => SongImageSource = bitmapImage);
|
DispatcherQueue.GetForCurrentThread().TryEnqueue(() => SongImageSource = bitmapImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnAudioPlayerPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
switch (e.PropertyName)
|
||||||
|
{
|
||||||
|
case nameof(_audioPlayer.State):
|
||||||
|
UpdateTimer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTimer()
|
||||||
|
{
|
||||||
|
if (_audioPlayer.State == AudioPlaybackState.Playing)
|
||||||
|
{
|
||||||
|
_timer.Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_timer.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void TickTock(object? sender, object e)
|
private void TickTock(object? sender, object e)
|
||||||
{
|
{
|
||||||
Position = _audioPlayer.Position;
|
Position = _audioPlayer.Position;
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ using System.Threading.Tasks;
|
|||||||
using System.Timers;
|
using System.Timers;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Windows.ApplicationModel.DataTransfer;
|
using Windows.ApplicationModel.DataTransfer;
|
||||||
|
using Windows.System;
|
||||||
|
using DispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue;
|
||||||
using Timer = System.Timers.Timer;
|
using Timer = System.Timers.Timer;
|
||||||
|
|
||||||
namespace Harmonia.WinUI.ViewModels;
|
namespace Harmonia.WinUI.ViewModels;
|
||||||
@@ -31,6 +33,7 @@ public partial class PlaylistViewModel : ViewModelBase
|
|||||||
private readonly IAudioFileScanner _audioFileScanner;
|
private readonly IAudioFileScanner _audioFileScanner;
|
||||||
private readonly IAudioEngine _audioEngine;
|
private readonly IAudioEngine _audioEngine;
|
||||||
private readonly IStorageProvider _storageProvider;
|
private readonly IStorageProvider _storageProvider;
|
||||||
|
private readonly DispatcherQueue _dispatcherQueue;
|
||||||
|
|
||||||
private Timer? _filterTimer;
|
private Timer? _filterTimer;
|
||||||
|
|
||||||
@@ -121,7 +124,8 @@ public partial class PlaylistViewModel : ViewModelBase
|
|||||||
IAudioBitmapImageCache audioBitmapImageCache,
|
IAudioBitmapImageCache audioBitmapImageCache,
|
||||||
IAudioFileScanner audioFileScanner,
|
IAudioFileScanner audioFileScanner,
|
||||||
IAudioEngine audioEngine,
|
IAudioEngine audioEngine,
|
||||||
IStorageProvider storageProvider)
|
IStorageProvider storageProvider,
|
||||||
|
IPlaylistRepository playlistRepository)
|
||||||
{
|
{
|
||||||
_audioPlayer = audioPlayer;
|
_audioPlayer = audioPlayer;
|
||||||
_audioPlayer.PlaylistChanged += OnPlaylistChanged;
|
_audioPlayer.PlaylistChanged += OnPlaylistChanged;
|
||||||
@@ -131,6 +135,23 @@ public partial class PlaylistViewModel : ViewModelBase
|
|||||||
_audioFileScanner = audioFileScanner;
|
_audioFileScanner = audioFileScanner;
|
||||||
_audioEngine = audioEngine;
|
_audioEngine = audioEngine;
|
||||||
_storageProvider = storageProvider;
|
_storageProvider = storageProvider;
|
||||||
|
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||||
|
|
||||||
|
// Testing
|
||||||
|
Task.Run(() => PlayDemoSong(playlistRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task PlayDemoSong(IPlaylistRepository playlistRepository)
|
||||||
|
{
|
||||||
|
if (playlistRepository.Get().Count == 0)
|
||||||
|
{
|
||||||
|
playlistRepository.AddPlaylist();
|
||||||
|
}
|
||||||
|
|
||||||
|
Playlist playlist = playlistRepository.Get().First();
|
||||||
|
|
||||||
|
if (playlist.Songs.Count > 0)
|
||||||
|
await _audioPlayer.LoadAsync(playlist.Songs[0], PlaybackMode.LoadOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPlaylistChanged(object? sender, EventArgs e)
|
private void OnPlaylistChanged(object? sender, EventArgs e)
|
||||||
@@ -161,10 +182,10 @@ public partial class PlaylistViewModel : ViewModelBase
|
|||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
case PlaylistUpdateAction.Add:
|
case PlaylistUpdateAction.Add:
|
||||||
DispatcherQueue.GetForCurrentThread().TryEnqueue(() => AddSongs(e.Songs, e.Index));
|
_dispatcherQueue.TryEnqueue(() => AddSongs(e.Songs, e.Index));
|
||||||
break;
|
break;
|
||||||
case PlaylistUpdateAction.Remove:
|
case PlaylistUpdateAction.Remove:
|
||||||
DispatcherQueue.GetForCurrentThread().TryEnqueue(() => RemoveSongsFromCollection(e.Songs));
|
_dispatcherQueue.TryEnqueue(() => RemoveSongsFromCollection(e.Songs));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,7 +253,7 @@ public partial class PlaylistViewModel : ViewModelBase
|
|||||||
_filterTimer.Dispose();
|
_filterTimer.Dispose();
|
||||||
_filterTimer = null;
|
_filterTimer = null;
|
||||||
|
|
||||||
DispatcherQueue.GetForCurrentThread().TryEnqueue(UpdateFilteredSongs);
|
_dispatcherQueue.TryEnqueue(UpdateFilteredSongs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateFilteredSongs()
|
private void UpdateFilteredSongs()
|
||||||
@@ -304,10 +325,12 @@ public partial class PlaylistViewModel : ViewModelBase
|
|||||||
|
|
||||||
private FilePickerFileType GetAudioFileTypes()
|
private FilePickerFileType GetAudioFileTypes()
|
||||||
{
|
{
|
||||||
|
string[] patterns = _audioEngine.SupportedFormats.Select(format => format.Replace("*", "")).ToArray();
|
||||||
|
|
||||||
return new()
|
return new()
|
||||||
{
|
{
|
||||||
Name = "Audio Files",
|
Name = "Audio Files",
|
||||||
Patterns = [.. _audioEngine.SupportedFormats]
|
Patterns = patterns
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +339,7 @@ public partial class PlaylistViewModel : ViewModelBase
|
|||||||
if (Playlist == null)
|
if (Playlist == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string path = await _storageProvider.GetPathAsync();
|
string? path = await _storageProvider.GetPathAsync();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(path))
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<Style x:Key="PlayerGrid" TargetType="Grid">
|
<Style x:Key="PlayerGrid" TargetType="Grid">
|
||||||
<Setter Property="Background" Value="#1a1a1a"/>
|
<Setter Property="Background" Value="#1a1a1a"/>
|
||||||
<Setter Property="Padding" Value="10"/>
|
<Setter Property="Padding" Value="10"/>
|
||||||
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
</Style>
|
</Style>
|
||||||
<Style x:Key="SongImage" TargetType="Image">
|
<Style x:Key="SongImage" TargetType="Image">
|
||||||
<Setter Property="Width" Value="80"/>
|
<Setter Property="Width" Value="80"/>
|
||||||
|
|||||||
134
Harmonia.WinUI/Views/PlaylistView.xaml
Normal file
134
Harmonia.WinUI/Views/PlaylistView.xaml
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
<UserControl
|
||||||
|
x:Class="Harmonia.WinUI.Views.PlaylistView"
|
||||||
|
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:vm="using:Harmonia.WinUI.ViewModels"
|
||||||
|
xmlns:playlists="using:Harmonia.Core.Playlists"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
DataContext="{Binding Source={StaticResource Locator}, Path=PlaylistViewModel}"
|
||||||
|
d:DataContext="{d:DesignInstance Type=vm:PlaylistViewModel, IsDesignTimeCreatable=True}"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<!--<SolidColorBrush x:Key="PlaylistBackground" Color="#393a45"/>-->
|
||||||
|
<SolidColorBrush x:Key="PlaylistBackground" Color="#292a35"/>
|
||||||
|
<SolidColorBrush x:Key="PlaylistItemHighlightColor" Color="#494a55"/>
|
||||||
|
<!--<SolidColorBrush x:Key="PlaylistBackground" Color="#222"/>-->
|
||||||
|
<SolidColorBrush x:Key="SongItemTitleBrush" Color="#dddddd"/>
|
||||||
|
<SolidColorBrush x:Key="SongItemTitleBrushHighlighted" Color="#A2D2F6"/>
|
||||||
|
<SolidColorBrush x:Key="SongItemSubtitleBrush" Color="#aaaaaa"/>
|
||||||
|
<!--<SolidColorBrush x:Key="SongItemSubtitleBrushHighlighted" Color="#76b9ed"/>-->
|
||||||
|
<SolidColorBrush x:Key="SongItemSubtitleBrushHighlighted" Color="#ddA2D2F6"/>
|
||||||
|
|
||||||
|
<SolidColorBrush x:Key="SongItemFooterBrush" Color="#888"/>
|
||||||
|
<SolidColorBrush x:Key="SongItemFooterBrushHighlighted" Color="#aaA2D2F6"/>
|
||||||
|
|
||||||
|
<!-- Image Border -->
|
||||||
|
<Style x:Key="PlaylistSongImageBorder" TargetType="Border">
|
||||||
|
<Setter Property="Width" Value="75"/>
|
||||||
|
<Setter Property="Height" Value="75"/>
|
||||||
|
<Setter Property="CornerRadius" Value="8"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<DataTemplate x:Key="SongTemplate" x:DataType="playlists:PlaylistSong">
|
||||||
|
<!-- Background was formerly transparent -->
|
||||||
|
<Border DoubleTapped="PlaylistListViewItem_DoubleTapped" Background="Transparent">
|
||||||
|
<Grid Padding="10">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"></ColumnDefinition>
|
||||||
|
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Border Grid.Column="0" Style="{StaticResource PlaylistSongImageBorder}">
|
||||||
|
<Grid>
|
||||||
|
<Image Loaded="Image_Loaded" Unloaded="Image_Unloaded"></Image>
|
||||||
|
<Canvas Background="#19000000"></Canvas>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
<Grid Grid.Column="1" Margin="10 0 0 0" VerticalAlignment="Center">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||||
|
<ColumnDefinition Width="60"></ColumnDefinition>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition></RowDefinition>
|
||||||
|
<RowDefinition></RowDefinition>
|
||||||
|
<RowDefinition></RowDefinition>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<TextBlock Grid.Column="0" Grid.Row="0" Foreground="{StaticResource SongItemTitleBrush}" Text="{x:Bind Song, Converter={StaticResource SongTitle}, Mode=OneWay}" FontSize="15" FontWeight="SemiBold" LineStackingStrategy="BlockLineHeight" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" LineHeight="0">
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Grid.Row="1" Text="{Binding Song.Artists, Converter={StaticResource ArtistsToString}}" Foreground="{StaticResource SongItemSubtitleBrush}" TextTrimming="CharacterEllipsis" LineStackingStrategy="BlockLineHeight" LineHeight="0" FontSize="14" Margin="0 0 0 0">
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Grid.Row="2" Text="{Binding Song.Album}" Foreground="{StaticResource SongItemSubtitleBrush}" TextTrimming="CharacterEllipsis" LineStackingStrategy="BlockLineHeight" LineHeight="0" FontSize="14" Margin="0 0 0 0">
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" TextAlignment="Right" HorizontalTextAlignment="Right" Foreground="{StaticResource SongItemSubtitleBrush}" TextTrimming="CharacterEllipsis" LineStackingStrategy="BlockLineHeight" LineHeight="0" FontSize="13" Text="{Binding Song.Length.TotalSeconds, Converter={StaticResource SecondsToString}}"></TextBlock>
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="{StaticResource SongItemFooterBrush}" TextTrimming="CharacterEllipsis" LineStackingStrategy="BlockLineHeight" LineHeight="0" FontSize="12" Text="{Binding Song.FileType}"></TextBlock>
|
||||||
|
<TextBlock Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="{StaticResource SongItemFooterBrush}" TextTrimming="CharacterEllipsis" LineStackingStrategy="BlockLineHeight" LineHeight="0" FontSize="12">
|
||||||
|
<Run Text="{Binding Song.BitRate}"></Run><Run Text=" kbps"></Run>
|
||||||
|
</TextBlock>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</DataTemplate>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"></RowDefinition>
|
||||||
|
<RowDefinition Height="*"></RowDefinition>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid Grid.Row="0" Margin="10">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||||
|
<ColumnDefinition Width="Auto"></ColumnDefinition>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBox Grid.Column="0" Text="{Binding Filter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" Margin="10 0" HorizontalAlignment="Stretch" PlaceholderText="Filter"></TextBox>
|
||||||
|
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="10">
|
||||||
|
<Button Style="{StaticResource FlatRoundButton}" Foreground="#7FD184">
|
||||||
|
<Button.Content>
|
||||||
|
<Path Style="{StaticResource FlatButtonPath}" Fill="#7FD184" Data="{StaticResource AddIcon}"></Path>
|
||||||
|
</Button.Content>
|
||||||
|
<Button.Flyout>
|
||||||
|
<MenuFlyout Placement="Bottom">
|
||||||
|
<MenuFlyoutItem Text="Add Files..." Command="{Binding AddFilesCommand}">
|
||||||
|
<MenuFlyoutItem.Icon>
|
||||||
|
<PathIcon Data="{StaticResource CopyIcon}"></PathIcon>
|
||||||
|
</MenuFlyoutItem.Icon>
|
||||||
|
</MenuFlyoutItem>
|
||||||
|
<MenuFlyoutItem Text="Add Folder..." Command="{Binding AddFolderCommand}">
|
||||||
|
<MenuFlyoutItem.Icon>
|
||||||
|
<PathIcon Data="{StaticResource CopyIcon}"></PathIcon>
|
||||||
|
</MenuFlyoutItem.Icon>
|
||||||
|
</MenuFlyoutItem>
|
||||||
|
</MenuFlyout>
|
||||||
|
</Button.Flyout>
|
||||||
|
</Button>
|
||||||
|
<Button Style="{StaticResource FlatRoundButton}">
|
||||||
|
<Button.Content>
|
||||||
|
<Path Style="{StaticResource FlatButtonPath}" Data="{StaticResource MoreIcon}"></Path>
|
||||||
|
</Button.Content>
|
||||||
|
<Button.Flyout>
|
||||||
|
<MenuFlyout Placement="Bottom">
|
||||||
|
<MenuFlyoutItem Text="Add Files..." Command="{Binding AddFilesCommand}">
|
||||||
|
<MenuFlyoutItem.Icon>
|
||||||
|
<PathIcon Data="{StaticResource CopyIcon}"></PathIcon>
|
||||||
|
</MenuFlyoutItem.Icon>
|
||||||
|
</MenuFlyoutItem>
|
||||||
|
<MenuFlyoutItem Text="Add Folder..." Command="{Binding AddFolderCommand}">
|
||||||
|
<MenuFlyoutItem.Icon>
|
||||||
|
<PathIcon Data="{StaticResource CopyIcon}"></PathIcon>
|
||||||
|
</MenuFlyoutItem.Icon>
|
||||||
|
</MenuFlyoutItem>
|
||||||
|
</MenuFlyout>
|
||||||
|
</Button.Flyout>
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
<ListView
|
||||||
|
Grid.Row="1"
|
||||||
|
Name="PlaylistListView"
|
||||||
|
ItemsSource="{Binding FilteredPlaylistSongs}"
|
||||||
|
ItemTemplate="{StaticResource SongTemplate}"
|
||||||
|
SelectionMode="Extended">
|
||||||
|
</ListView>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
57
Harmonia.WinUI/Views/PlaylistView.xaml.cs
Normal file
57
Harmonia.WinUI/Views/PlaylistView.xaml.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
using Harmonia.Core.Playlists;
|
||||||
|
using Harmonia.WinUI.ViewModels;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Input;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Harmonia.WinUI.Views;
|
||||||
|
|
||||||
|
public sealed partial class PlaylistView : UserControl
|
||||||
|
{
|
||||||
|
private readonly PlaylistViewModel _viewModel;
|
||||||
|
|
||||||
|
public PlaylistView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
_viewModel = (PlaylistViewModel)DataContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Image_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
//Image? image = sender as Image;
|
||||||
|
|
||||||
|
//if (image == null)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
//image.DataContextChanged += Image_DataContextChanged;
|
||||||
|
|
||||||
|
//var song = (PlaylistSong)image.DataContext;
|
||||||
|
|
||||||
|
//if (song == null)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
//Task.Run(async () => await FetchImage(song.Song, image));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Image_Unloaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
//Image? image = sender as Image;
|
||||||
|
|
||||||
|
//if (image == null)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
//image.DataContextChanged -= Image_DataContextChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void PlaylistListViewItem_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is not FrameworkElement element)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (element == null || element.DataContext is not PlaylistSong playlistSong)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await _viewModel.PlaySongAsync(playlistSong);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user