Added volume control. Updated styling.

This commit is contained in:
2026-08-13 00:29:35 -04:00
parent 321db65154
commit c8ce4ca7f0
9 changed files with 118 additions and 4 deletions

View File

@@ -1,9 +1,44 @@
using System;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Markup;
using Microsoft.UI.Xaml.Media;
using Harmonia.WinUI.Models;
namespace Harmonia.WinUI.Converters;
public sealed partial class VolumeStateToIconConverter : IValueConverter
{
public object? Convert(object value, Type targetType, object parameter, string language)
{
if (value is not VolumeState volumeState)
return null;
if (Application.Current.Resources[$"Volume{volumeState}Icon2"] is not string pathData)
return null;
return XamlBindingHelper.ConvertValue(typeof(Geometry), pathData.Trim());
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
public sealed partial class VolumeStateToFillConverter : IValueConverter
{
public object? Convert(object value, Type targetType, object parameter, string language)
{
return value is VolumeState.Muted ? parameter : null;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
public sealed partial class VolumeStateConverter : IValueConverter
{
public VolumeStateConverter()

View File

@@ -20,13 +20,19 @@
<Button x:Name="myButton" Click="myButton_Click">Click Me</Button>
</StackPanel>-->
<Grid>
<Grid.Resources>
<LinearGradientBrush x:Key="DarkTitleBarBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#0C0E12" Offset="0"/>
<GradientStop Color="#0A0B0E" Offset="1"/>
</LinearGradientBrush>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<!-- Title Bar -->
<Grid x:Name="AppTitleBar" Grid.Row="0" VerticalAlignment="Center" Padding="10">
<Grid x:Name="AppTitleBar" Grid.Row="0" VerticalAlignment="Center" Padding="10" Background="{StaticResource DarkTitleBarBackgroundBrush}" BorderBrush="#3B332B" BorderThickness="0 0 0 1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>

View File

@@ -11,5 +11,7 @@
<converters:DoubleToPercentConverter x:Key="DoubleToPercent" />
<converters:RepeatStateConverter x:Key="RepeatState" />
<converters:VolumeStateConverter x:Key="VolumeState" />
<converters:VolumeStateToIconConverter x:Key="VolumeStateToIcon" />
<converters:VolumeStateToFillConverter x:Key="VolumeStateToFill" />
</ResourceDictionary>

View File

@@ -79,6 +79,37 @@
M6.717 3.55A.5.5 0 0 1 7 4v8a.5.5 0 0 1-.812.39L3.825 10.5H1.5A.5.5 0 0 1 1 10V6a.5.5 0 0 1 .5-.5h2.325l2.363-1.89a.5.5 0 0 1 .529-.06
</x:String>
<x:String x:Key="VolumeHighIcon2">
M126,192H56a8,8,0,0,0-8,8V312a8,8,0,0,0,8,8h69.65a15.93,15.93,0,0,1,10.14,3.54l91.47,74.89A8,8,0,0,0,240,392V120a8,8,0,0,0-12.74-6.43l-91.47,74.89A15,15,0,0,1,126,192Z
M320,320c9.74-19.38,16-40.84,16-64,0-23.48-6-44.42-16-64
M368,368c19.48-33.92,32-64.06,32-112s-12-77.74-32-112
M416,416c30-46,48-91.43,48-160S446,143,416,96
</x:String>
<x:String x:Key="VolumeMediumIcon2">
M157.65,192H88a8,8,0,0,0-8,8V312a8,8,0,0,0,8,8h69.65a16,16,0,0,1,10.14,3.63l91.47,75A8,8,0,0,0,272,392.17V119.83a8,8,0,0,0-12.74-6.44l-91.47,75A16,16,0,0,1,157.65,192Z
M352,320c9.74-19.41,16-40.81,16-64,0-23.51-6-44.4-16-64
M400,368c19.48-34,32-64,32-112s-12-77.7-32-112
</x:String>
<x:String x:Key="VolumeLowIcon2">
M189.65,192H120a8,8,0,0,0-8,8V312a8,8,0,0,0,8,8h69.65a16,16,0,0,1,10.14,3.63l91.47,75A8,8,0,0,0,304,392.17V119.83a8,8,0,0,0-12.74-6.44l-91.47,75A16,16,0,0,1,189.65,192Z
M384,320c9.74-19.41,16-40.81,16-64,0-23.51-6-44.4-16-64
</x:String>
<x:String x:Key="VolumeOffIcon2">
M237.65,192H168a8,8,0,0,0-8,8V312a8,8,0,0,0,8,8h69.65a16,16,0,0,1,10.14,3.63l91.47,75A8,8,0,0,0,352,392.17V119.83a8,8,0,0,0-12.74-6.44l-91.47,75A16,16,0,0,1,237.65,192Z
</x:String>
<x:String x:Key="VolumeMutedIcon2">
M416,432 64,80
M224,136.92v33.8a4,4,0,0,0,1.17,2.82l24,24a4,4,0,0,0,6.83-2.82V120.57a24.53,24.53,0,0,0-12.67-21.72,23.91,23.91,0,0,0-25.55,1.83,8.27,8.27,0,0,0-.66.51l-31.94,26.15a4,4,0,0,0-.29,5.92l17.05,17.06a4,4,0,0,0,5.37.26Z
M224,375.08l-78.07-63.92A32,32,0,0,0,125.65,304H64V208h50.72a4,4,0,0,0,2.82-6.83l-24-24A4,4,0,0,0,90.72,176H56a24,24,0,0,0-24,24V312a24,24,0,0,0,24,24h69.76l91.36,74.8a8.27,8.27,0,0,0,.66.51A23.93,23.93,0,0,0,243.63,413,24.49,24.49,0,0,0,256,391.45V341.28a4,4,0,0,0-1.17-2.82l-24-24a4,4,0,0,0-6.83,2.82ZM125.82,336Z
M352,256c0-24.56-5.81-47.88-17.75-71.27a16,16,0,0,0-28.5,14.54C315.34,218.06,320,236.62,320,256q0,4-.31,8.13a8,8,0,0,0,2.32,6.25l19.66,19.67a4,4,0,0,0,6.75-2A146.89,146.89,0,0,0,352,256Z
M416,256c0-51.19-13.08-83.89-34.18-120.06a16,16,0,0,0-27.64,16.12C373.07,184.44,384,211.83,384,256c0,23.83-3.29,42.88-9.37,60.65a8,8,0,0,0,1.9,8.26l16.77,16.76a4,4,0,0,0,6.52-1.27C410.09,315.88,416,289.91,416,256Z
M480,256c0-74.26-20.19-121.11-50.51-168.61a16,16,0,1,0-27,17.22C429.82,147.38,448,189.5,448,256c0,47.45-8.9,82.12-23.59,113a4,4,0,0,0,.77,4.55L443,391.39a4,4,0,0,0,6.4-1C470.88,348.22,480,307,480,256Z
</x:String>
<x:String x:Key="ShuffleIcon">
M0 3.5A.5.5 0 0 1 .5 3H1c2.202 0 3.827 1.24 4.874 2.418.49.552.865 1.102 1.126 1.532.26-.43.636-.98 1.126-1.532C9.173 4.24 10.798 3 13 3v1c-1.798 0-3.173 1.01-4.126 2.082A9.6 9.6 0 0 0 7.556 8a9.6 9.6 0 0 0 1.317 1.918C9.828 10.99 11.204 12 13 12v1c-2.202 0-3.827-1.24-4.874-2.418A10.6 10.6 0 0 1 7 9.05c-.26.43-.636.98-1.126 1.532C4.827 11.76 3.202 13 1 13H.5a.5.5 0 0 1 0-1H1c1.798 0 3.173-1.01 4.126-2.082A9.6 9.6 0 0 0 6.444 8a9.6 9.6 0 0 0-1.317-1.918C4.172 5.01 2.796 4 1 4H.5a.5.5 0 0 1-.5-.5
M13 5.466V1.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384l-2.36 1.966a.25.25 0 0 1-.41-.192

View File

@@ -35,6 +35,8 @@ public class SessionRestorer(
private async Task RestoreAudioPlayerAsync()
{
AudioPlayerState audioPlayerState = sessionService.Session.Player;
audioPlayer.Volume = audioPlayerState.Volume;
audioPlayer.IsMuted = audioPlayerState.IsMuted;
if (string.IsNullOrWhiteSpace(audioPlayerState.PlaylistSongUID))
return;

View File

@@ -34,6 +34,8 @@ public class SessionTracker(
audioPlayerState.Position = audioPlayer.Position;
audioPlayerState.PlaybackState = GetSemanticPlaybackState();
audioPlayerState.Volume = audioPlayer.Volume;
audioPlayerState.IsMuted = audioPlayer.IsMuted;
}
private AudioPlaybackState GetSemanticPlaybackState()

View File

@@ -168,5 +168,30 @@
</StackPanel>
</Grid>
<!-- Volume Slider -->
<Grid Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Right">
<StackPanel Orientation="Horizontal" Spacing="8" VerticalAlignment="Center">
<Button Style="{StaticResource FlatButton}" BorderBrush="{StaticResource DarkGradientBrush}" Command="{Binding ToggleMuteCommand}">
<Viewbox Width="24" Height="24">
<Canvas Width="512" Height="512">
<Path Stretch="None" Fill="{Binding VolumeState, Converter={StaticResource VolumeStateToFill}, ConverterParameter={StaticResource DarkGradientBrush}}" Stroke="{StaticResource DarkGradientBrush}" StrokeThickness="32" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Data="{Binding VolumeState, Converter={StaticResource VolumeStateToIcon}}"></Path>
</Canvas>
</Viewbox>
</Button>
<Slider Width="200" Minimum="0.0" Maximum="1.0" StepFrequency="0.01" VerticalAlignment="Center" Value="{Binding Volume, Mode=TwoWay}">
<Slider.Resources>
<!-- Thumb (the "ball") -->
<StaticResource x:Key="SliderThumbBackground" ResourceKey="DarkGradientBrush"/>
<StaticResource x:Key="SliderThumbBackgroundPointerOver" ResourceKey="DarkGradientBrush"/>
<StaticResource x:Key="SliderThumbBackgroundPressed" ResourceKey="DarkGradientBrush"/>
<!-- Filled portion of the track (defaults to system accent on hover/press) -->
<StaticResource x:Key="SliderTrackValueFill" ResourceKey="SliderGradientBrush"/>
<StaticResource x:Key="SliderTrackValueFillPointerOver" ResourceKey="SliderGradientBrush"/>
<StaticResource x:Key="SliderTrackValueFillPressed" ResourceKey="SliderGradientBrush"/>
</Slider.Resources>
</Slider>
</StackPanel>
</Grid>
</Grid>
</UserControl>

View File

@@ -28,6 +28,11 @@
<SolidColorBrush x:Key="SongItemFooterBrush" Color="#888"/>
<SolidColorBrush x:Key="SongItemFooterBrushHighlighted" Color="#aaA2D2F6"/>
<LinearGradientBrush x:Key="DarkBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#101114" Offset="0"/>
<GradientStop Color="#090B0F" Offset="1"/>
</LinearGradientBrush>
<!-- Image Border -->
<Style x:Key="PlaylistSongImageBorder" TargetType="Border">
<Setter Property="Width" Value="60"/> <!-- as 75 -->
@@ -71,10 +76,11 @@
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Style="{StaticResource PlaylistSongImageBorder}">
<Border Grid.Column="0" Style="{StaticResource PlaylistSongImageBorder}" BorderBrush="#2D2930" BorderThickness="1">
<Grid>
<Image Loaded="Image_Loaded" Unloaded="Image_Unloaded"></Image>
<Canvas Background="#19000000"></Canvas>
<!--<Canvas Background="#30000000"></Canvas>-->
</Grid>
</Border>
<Grid Grid.Column="1" Margin="10 0 0 0" VerticalAlignment="Center">
@@ -103,7 +109,7 @@
</Border>
</DataTemplate>
</UserControl.Resources>
<Grid>
<Grid Background="{StaticResource DarkBackgroundBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>

View File

@@ -20,6 +20,11 @@
<SolidColorBrush x:Key="PlaylistItemTitleBrush" Color="#dddddd"/>
<SolidColorBrush x:Key="PlaylistItemSubtitleBrush" Color="#aaaaaa"/>
<LinearGradientBrush x:Key="DarkBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#161719" Offset="0"/>
<GradientStop Color="#0B0D0F" Offset="1"/>
</LinearGradientBrush>
<!-- Playlist Icon Path -->
<Style x:Key="PlaylistIconPath" TargetType="PathIcon">
<Setter Property="Foreground" Value="{StaticResource PlaylistItemIconBrush}"/>
@@ -75,7 +80,7 @@
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid Margin="10">
<Grid Background="{StaticResource DarkBackgroundBrush}" BorderBrush="#3C342F" BorderThickness="1 0 1 0">
<ListView
Name="PlaylistsListView"
ItemsSource="{Binding Playlists, Mode=OneWay}"