From 097e9b88e67120ad4408166f651700e036fc57f6 Mon Sep 17 00:00:00 2001
From: Difegue <8237712+Difegue@users.noreply.github.com>
Date: Sun, 18 Sep 2022 01:29:51 +0200
Subject: [PATCH 01/56] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 6e1cebe..79a5d07 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ Stylophone
[**Music Player Daemon**](https://www.musicpd.org/) Client for UWP and iOS/iPadOS.
Based on [MpcNET](https://github.com/Difegue/MpcNET), my own fork of the original .NET Client Library for MPD. (now on NuGet!)
-
+[](https://www.microsoft.com/store/apps/9NCB693428T8?cid=storebadge&ocid=badge) [](https://apps.apple.com/us/app/stylophone/id1644672889?itsct=apps_box_link&itscg=30200)
[Buy a sticker if you want!](https://ko-fi.com/s/9fcf421b6e)
From 971a5174299cb684c6f9419f774f8584c9703795 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Sun, 25 Sep 2022 21:38:56 +0200
Subject: [PATCH 02/56] (#58) Fix theme preference not saving + misc. AppCenter
bugfixes
---
.../ViewModels/PlaylistViewModel.cs | 7 ++++++-
.../ViewModels/QueueViewModel.cs | 17 ++++++++---------
.../ViewModels/SettingsViewModel.cs | 6 +-----
Sources/Stylophone/Package.appxmanifest | 2 +-
Sources/Stylophone/Package.tt | 2 +-
5 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs b/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
index 917e1a1..0b60563 100644
--- a/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
@@ -248,7 +248,12 @@ await Task.Run(async () =>
DominantColor = (art?.DominantColor?.Color).GetValueOrDefault();
if (DominantColor == default(SKColor))
- DominantColor = _interop.GetAccentColor();
+ {
+ await _dispatcherService.ExecuteOnUIThreadAsync(() =>
+ {
+ DominantColor = _interop.GetAccentColor();
+ });
+ }
IsLight = (!art?.DominantColor?.IsDark).GetValueOrDefault();
}
diff --git a/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs b/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
index 53ca64a..4a9b223 100644
--- a/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
@@ -206,18 +206,17 @@ private async void MPDConnectionService_QueueChanged(object sender, EventArgs e)
}
else
{
- // PlChanges gives the full list of files starting from the change, so we delete all existing tracks from the source after that change, and swap the new ones in.
+ // PlChanges gives the full list of files starting from the change,
+ // so we delete all existing tracks from the source after that change, and swap the new ones in.
// If the response is empty, that means the last file in the source was removed.
var initialPosition = response.Count() == 0 ? Source.Count - 1 : response.First().Position;
- while (Source.Count != initialPosition)
- {
- await _dispatcherService.ExecuteOnUIThreadAsync(() => {
- // Make sure
- if (Source.Count != initialPosition)
- Source.RemoveAt(initialPosition);
- });
- }
+ await _dispatcherService.ExecuteOnUIThreadAsync(() => {
+ while (Source.Count > initialPosition)
+ {
+ Source.RemoveAt(initialPosition);
+ }
+ });
var toAdd = new List();
foreach (var item in response)
diff --git a/Sources/Stylophone.Common/ViewModels/SettingsViewModel.cs b/Sources/Stylophone.Common/ViewModels/SettingsViewModel.cs
index 34d07aa..8f4e2f6 100644
--- a/Sources/Stylophone.Common/ViewModels/SettingsViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/SettingsViewModel.cs
@@ -78,11 +78,7 @@ public SettingsViewModel(MPDConnectionService mpdService, IApplicationStorageSer
partial void OnElementThemeChanged(Theme value)
{
Task.Run (async () => await _interop.SetThemeAsync(value));
-
- if (value != _elementTheme)
- {
- _applicationStorageService.SetValue(nameof(ElementTheme), value.ToString());
- }
+ _applicationStorageService.SetValue(nameof(ElementTheme), value.ToString());
}
partial void OnServerHostChanged(string value)
diff --git a/Sources/Stylophone/Package.appxmanifest b/Sources/Stylophone/Package.appxmanifest
index 04666c7..402c962 100644
--- a/Sources/Stylophone/Package.appxmanifest
+++ b/Sources/Stylophone/Package.appxmanifest
@@ -12,7 +12,7 @@
+ Version="2.5.5.0" />
diff --git a/Sources/Stylophone/Package.tt b/Sources/Stylophone/Package.tt
index f796b29..65a9650 100644
--- a/Sources/Stylophone/Package.tt
+++ b/Sources/Stylophone/Package.tt
@@ -2,7 +2,7 @@
<#@ output extension=".appxmanifest" #>
<#@ parameter type="System.String" name="BuildConfiguration" #>
<#
- string version = "2.5.2.0";
+ string version = "2.5.5.0";
// Get configuration name at Build time
string configName = Host.ResolveParameterValue("-", "-", "BuildConfiguration");
From 7afdf574a2ff95b32b4587a9967f43c57a088bb1 Mon Sep 17 00:00:00 2001
From: Difegue <8237712+Difegue@users.noreply.github.com>
Date: Sat, 22 Oct 2022 22:02:32 +0200
Subject: [PATCH 03/56] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 79a5d07..c04b8de 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ Stylophone
[**Music Player Daemon**](https://www.musicpd.org/) Client for UWP and iOS/iPadOS.
Based on [MpcNET](https://github.com/Difegue/MpcNET), my own fork of the original .NET Client Library for MPD. (now on NuGet!)
-[](https://www.microsoft.com/store/apps/9NCB693428T8?cid=storebadge&ocid=badge) [](https://apps.apple.com/us/app/stylophone/id1644672889?itsct=apps_box_link&itscg=30200)
+[](https://www.microsoft.com/store/apps/9NCB693428T8?cid=storebadge&ocid=badge) [](https://apps.apple.com/us/app/stylophone/id1644672889?itsct=apps_box_link&itscg=30200)
[Buy a sticker if you want!](https://ko-fi.com/s/9fcf421b6e)
From 0f5a5b84a7df6214da506c2ca8e945614e25b70e Mon Sep 17 00:00:00 2001
From: Difegue
Date: Sat, 26 Nov 2022 02:21:08 +0100
Subject: [PATCH 04/56] Improve suspend/resume on Windows
not sure if that actually fixes it fully since debugging app lifecycle doesn't work at all
---
.../Services/AlbumArtService.cs | 6 ++-
.../Services/MPDConnectionService.cs | 48 ++++++++++++-------
.../ViewModels/Bases/PlaybackViewModelBase.cs | 5 +-
Sources/Stylophone/App.xaml.cs | 15 ++++++
4 files changed, 53 insertions(+), 21 deletions(-)
diff --git a/Sources/Stylophone.Common/Services/AlbumArtService.cs b/Sources/Stylophone.Common/Services/AlbumArtService.cs
index 25e9df9..7e88da0 100644
--- a/Sources/Stylophone.Common/Services/AlbumArtService.cs
+++ b/Sources/Stylophone.Common/Services/AlbumArtService.cs
@@ -40,7 +40,6 @@ public void Initialize()
{
_queueCanceller?.Cancel();
_queueCanceller = new CancellationTokenSource();
-
var token = _queueCanceller.Token;
_albumArtQueue = new Stack();
@@ -81,6 +80,11 @@ public void Initialize()
}).ConfigureAwait(false);
}
+ public void Stop()
+ {
+ _queueCanceller?.Cancel();
+ }
+
///
/// Check if this file's album art is already stored in the internal Album Art cache.
///
diff --git a/Sources/Stylophone.Common/Services/MPDConnectionService.cs b/Sources/Stylophone.Common/Services/MPDConnectionService.cs
index 4d0acc2..8666aa2 100644
--- a/Sources/Stylophone.Common/Services/MPDConnectionService.cs
+++ b/Sources/Stylophone.Common/Services/MPDConnectionService.cs
@@ -77,13 +77,7 @@ public async Task InitializeAsync(bool withRetry = false)
IsConnecting = true;
CurrentStatus = BOGUS_STATUS; // Reset status
- if (IsConnected)
- {
- IsConnected = false;
- ConnectionChanged?.Invoke(this, new EventArgs());
- }
-
- ClearResources();
+ Disconnect();
var cancelToken = _cancelConnect.Token;
@@ -106,23 +100,31 @@ public async Task InitializeAsync(bool withRetry = false)
_connectionRetryAttempter.Start();
}
}
-
+
IsConnecting = false;
}
- private void ClearResources()
+ public void Disconnect()
{
- _idleConnection?.SendAsync(new NoIdleCommand());
- _idleConnection?.DisconnectAsync();
- _statusConnection?.DisconnectAsync();
+
+ if (IsConnected)
+ {
+ System.Diagnostics.Debug.WriteLine($"Terminating MPD connections");
+ IsConnected = false;
+ ConnectionChanged?.Invoke(this, new EventArgs());
+ }
+
+ // Stop the idle connection first
+ _cancelIdle?.Cancel();
_connectionRetryAttempter?.Stop();
_connectionRetryAttempter?.Dispose();
+ // Stop the status timer before killing the matching connection
_statusUpdater?.Stop();
_statusUpdater?.Dispose();
+ _statusConnection?.DisconnectAsync();
- _cancelIdle?.Cancel();
_cancelIdle = new CancellationTokenSource();
_cancelConnect?.Cancel();
@@ -270,15 +272,25 @@ private void InitializeStatusUpdater(CancellationToken token = default)
try
{
+ // Run the idleConnection in a wrapper task since MpcNET isn't fully async and will block here
+ var idleChangesTask = Task.Run(async () => await _idleConnection.SendAsync(new IdleCommand("stored_playlist playlist player mixer output options update")));
+
+ // Wait for the idle command to finish or for the token to be cancelled
+ await Task.WhenAny(idleChangesTask, Task.Delay(-1, token));
+
if (token.IsCancellationRequested || _idleConnection == null || !_idleConnection.IsConnected)
+ {
+ //_idleConnection?.SendAsync(new NoIdleCommand());
+ _idleConnection?.DisconnectAsync();
break;
+ }
+
+ var message = idleChangesTask.Result;
- var idleChanges = await _idleConnection.SendAsync(new IdleCommand("stored_playlist playlist player mixer output options update"));
-
- if (idleChanges.IsResponseValid)
- await HandleIdleResponseAsync(idleChanges.Response.Content);
+ if (message.IsResponseValid)
+ await HandleIdleResponseAsync(message.Response.Content);
else
- throw new Exception(idleChanges.Response?.Content);
+ throw new Exception(message.Response?.Content);
}
catch (Exception e)
{
diff --git a/Sources/Stylophone.Common/ViewModels/Bases/PlaybackViewModelBase.cs b/Sources/Stylophone.Common/ViewModels/Bases/PlaybackViewModelBase.cs
index d717b56..77160da 100644
--- a/Sources/Stylophone.Common/ViewModels/Bases/PlaybackViewModelBase.cs
+++ b/Sources/Stylophone.Common/ViewModels/Bases/PlaybackViewModelBase.cs
@@ -61,10 +61,9 @@ public PlaybackViewModelBase(INavigationService navigationService, INotification
_internalVolume = _mpdService.CurrentStatus.Volume;
- // Bind timer methods and start it
+ // Bind timer methods
_updateInformationTimer = new System.Timers.Timer(500);
_updateInformationTimer.Elapsed += UpdateInformation;
- _updateInformationTimer.Start();
// Update info to current track
_mpdService.ConnectionChanged += OnConnectionChanged;
@@ -82,6 +81,7 @@ private void OnConnectionChanged(object sender, EventArgs e)
else
{
IsTrackInfoAvailable = false;
+ _updateInformationTimer?.Stop();
}
}
@@ -90,6 +90,7 @@ private void Initialize()
OnTrackChange(this, new SongChangedEventArgs { NewSongId = -1 });
CurrentTimeValue = _mpdService.CurrentStatus.Elapsed.TotalSeconds;
+ _updateInformationTimer.Start();
OnStateChange(this, null);
}
diff --git a/Sources/Stylophone/App.xaml.cs b/Sources/Stylophone/App.xaml.cs
index 04fafed..4e675b1 100644
--- a/Sources/Stylophone/App.xaml.cs
+++ b/Sources/Stylophone/App.xaml.cs
@@ -16,6 +16,7 @@
using Microsoft.Toolkit.Uwp.Helpers;
using Windows.Foundation;
using Microsoft.Services.Store.Engagement;
+using Windows.ApplicationModel;
#if DEBUG
#else
using System.Collections.Generic;
@@ -40,6 +41,8 @@ public App()
InitializeComponent();
UnhandledException += OnAppUnhandledException;
+ Suspending += OnAppSuspending;
+ Resuming += OnAppResuming;
// Deferred execution until used. Check https://msdn.microsoft.com/library/dd642331(v=vs.110).aspx for further info on Lazy class.
_activationService = new Lazy(CreateActivationService);
@@ -119,6 +122,18 @@ private void OnAppUnhandledException(object sender, Windows.UI.Xaml.UnhandledExc
e.Handled = true;
}
+ private async void OnAppResuming(object sender, object e)
+ {
+ await Ioc.Default.GetRequiredService().InitializeAsync(true);
+ Ioc.Default.GetRequiredService().Initialize();
+ }
+
+ private void OnAppSuspending(object sender, SuspendingEventArgs e)
+ {
+ Ioc.Default.GetRequiredService().Disconnect();
+ Ioc.Default.GetRequiredService().Stop();
+ }
+
private ActivationService CreateActivationService()
{
return new ActivationService(this, typeof(QueueViewModel), new Lazy(CreateShell));
From cc25b3af852ec60c69ba9836f8484ed9c451ec23 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Sat, 26 Nov 2022 02:52:03 +0100
Subject: [PATCH 05/56] Rework queue again + fix small bugs
---
.../ViewModels/QueueViewModel.cs | 7 +++---
.../ViewModels/SettingsViewModel.cs | 2 +-
.../Stylophone/Views/ServerQueuePage.xaml.cs | 22 +++++++++----------
3 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs b/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
index 4a9b223..6aad672 100644
--- a/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
@@ -211,11 +211,10 @@ private async void MPDConnectionService_QueueChanged(object sender, EventArgs e)
// If the response is empty, that means the last file in the source was removed.
var initialPosition = response.Count() == 0 ? Source.Count - 1 : response.First().Position;
+ // Get all the tracks between initialPosition and the end of the Source
+ var tracksToRemove = Source.Skip(initialPosition).ToList();
await _dispatcherService.ExecuteOnUIThreadAsync(() => {
- while (Source.Count > initialPosition)
- {
- Source.RemoveAt(initialPosition);
- }
+ Source.RemoveRange(tracksToRemove);
});
var toAdd = new List();
diff --git a/Sources/Stylophone.Common/ViewModels/SettingsViewModel.cs b/Sources/Stylophone.Common/ViewModels/SettingsViewModel.cs
index 8f4e2f6..85f2852 100644
--- a/Sources/Stylophone.Common/ViewModels/SettingsViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/SettingsViewModel.cs
@@ -238,7 +238,7 @@ private async Task UpdateServerVersionAsync()
var songs = response.ContainsKey("songs") ? response["songs"] : "??";
var albums = response.ContainsKey("albums") ? response["albums"] : "??";
- if (outputs != null)
+ if (outputs != null && outputs.Count() > 0)
{
var outputString = outputs.Select(o => o.Plugin).Aggregate((s, s2) => $"{s}, {s2}");
diff --git a/Sources/Stylophone/Views/ServerQueuePage.xaml.cs b/Sources/Stylophone/Views/ServerQueuePage.xaml.cs
index 3004bb0..79d6da7 100644
--- a/Sources/Stylophone/Views/ServerQueuePage.xaml.cs
+++ b/Sources/Stylophone/Views/ServerQueuePage.xaml.cs
@@ -7,6 +7,7 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
+using System.Collections.Specialized;
namespace Stylophone.Views
{
@@ -31,7 +32,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
- ViewModel.PropertyChanged += ViewModel_PropertyChanged;
+ ViewModel.Source.CollectionChanged += ScrollToPlayingSong;
_mpdService.SongChanged += MPDConnectionService_SongChanged;
@@ -58,19 +59,16 @@ private void MPDConnectionService_SongChanged(object sender, SongChangedEventArg
});
}
- private void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ private void ScrollToPlayingSong(object sender, NotifyCollectionChangedEventArgs e)
{
- if (e.PropertyName == nameof(ViewModel.Source))
- {
- if (QueueList.Items.Count == 0)
- return;
+ if (QueueList.Items.Count == 0)
+ return;
- var playing = ViewModel.Source.Where(t => t.IsPlaying && t.File.Id != manualSongId).FirstOrDefault();
- if (playing != null)
- {
- playing.UpdatePlayingStatus();
- QueueList.ScrollIntoView(playing, ScrollIntoViewAlignment.Leading);
- }
+ var playing = ViewModel.Source.Where(t => t.IsPlaying && t.File.Id != manualSongId).FirstOrDefault();
+ if (playing != null)
+ {
+ playing.UpdatePlayingStatus();
+ QueueList.ScrollIntoView(playing, ScrollIntoViewAlignment.Leading);
}
}
From 4121f2241480cd03530dbcb07f27d53ed0e9d207 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 29 Nov 2022 21:29:55 +0100
Subject: [PATCH 06/56] Better MPD error tracking
---
.../Stylophone.Common/Services/MPDConnectionService.cs | 8 ++++++--
Sources/Stylophone/Package.tt | 2 +-
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/Sources/Stylophone.Common/Services/MPDConnectionService.cs b/Sources/Stylophone.Common/Services/MPDConnectionService.cs
index 8666aa2..c038388 100644
--- a/Sources/Stylophone.Common/Services/MPDConnectionService.cs
+++ b/Sources/Stylophone.Common/Services/MPDConnectionService.cs
@@ -225,8 +225,12 @@ public async Task SafelySendCommandAsync(IMpcCommand command, bool show
{
var dict = new Dictionary();
dict.Add("command", command.Serialize());
- dict.Add("exception", e.ToString());
- Analytics.TrackEvent("MPDError", dict);
+ dict.Add("exception", e.InnerException?.ToString());
+ dict.Add("source", e.Source);
+ dict.Add("message", e.Message);
+ dict.Add("stacktrace", e.StackTrace);
+
+ Analytics.TrackEvent("MPDError", dict);
}
#endif
}
diff --git a/Sources/Stylophone/Package.tt b/Sources/Stylophone/Package.tt
index 65a9650..8060ae6 100644
--- a/Sources/Stylophone/Package.tt
+++ b/Sources/Stylophone/Package.tt
@@ -2,7 +2,7 @@
<#@ output extension=".appxmanifest" #>
<#@ parameter type="System.String" name="BuildConfiguration" #>
<#
- string version = "2.5.5.0";
+ string version = "2.5.6.0";
// Get configuration name at Build time
string configName = Host.ResolveParameterValue("-", "-", "BuildConfiguration");
From 105d18432360d04a051a8c710eb2be19772038b0 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 14 Mar 2023 21:10:36 +0100
Subject: [PATCH 07/56] cleaner LocalizedLabel implementation
---
Sources/Stylophone.iOS/Helpers/LocalizedLabel.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Sources/Stylophone.iOS/Helpers/LocalizedLabel.cs b/Sources/Stylophone.iOS/Helpers/LocalizedLabel.cs
index 34151f9..9825ae3 100644
--- a/Sources/Stylophone.iOS/Helpers/LocalizedLabel.cs
+++ b/Sources/Stylophone.iOS/Helpers/LocalizedLabel.cs
@@ -26,10 +26,10 @@ public override void AwakeFromNib()
// Use the text set in IB to find the matching property.
// Set the identifier in "User Defined Runtime Attributes".
- var prop = typeof(Resources).GetProperty(stringIdentifier ?? "AppDisplayName");
+ var identifier = stringIdentifier ?? "AppDisplayName";
// Get the property value to have the localized string.
- Text = prop.GetValue(null, null).ToString();
+ Text = Resources.ResourceManager.GetString(identifier);
}
}
}
From 596f8c45880ed9007d8766a990076d0e160ab135 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Mon, 17 Apr 2023 20:56:41 +0200
Subject: [PATCH 08/56] Try/catch potential NRE in doubletap to play
(from appcenter)
---
Sources/Stylophone/Package.appxmanifest | 2 +-
.../Stylophone/Views/ServerQueuePage.xaml.cs | 24 ++++++++++++-------
2 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/Sources/Stylophone/Package.appxmanifest b/Sources/Stylophone/Package.appxmanifest
index 402c962..a5a1ff2 100644
--- a/Sources/Stylophone/Package.appxmanifest
+++ b/Sources/Stylophone/Package.appxmanifest
@@ -12,7 +12,7 @@
+ Version="2.5.6.0" />
diff --git a/Sources/Stylophone/Views/ServerQueuePage.xaml.cs b/Sources/Stylophone/Views/ServerQueuePage.xaml.cs
index 79d6da7..4b27f81 100644
--- a/Sources/Stylophone/Views/ServerQueuePage.xaml.cs
+++ b/Sources/Stylophone/Views/ServerQueuePage.xaml.cs
@@ -1,4 +1,5 @@
-using System.Linq;
+using System;
+using System.Linq;
using Stylophone.Helpers;
using CommunityToolkit.Mvvm.DependencyInjection;
using Stylophone.Common.Interfaces;
@@ -74,13 +75,20 @@ private void ScrollToPlayingSong(object sender, NotifyCollectionChangedEventArgs
private void Play_Track(object sender, RoutedEventArgs e)
{
- var listView = sender as ListView;
- var trackVm = listView.SelectedItem as TrackViewModel;
- // Set this ID as manually played by the user to prevent unnecessary autoscrolling.
- // Kind of a duct tape fix for now
- // TODO: Apply to context menu as well, maybe main playbar buttons if the queue is showing?
- manualSongId = trackVm.File.Id;
- trackVm.PlayTrackCommand.Execute(trackVm.File);
+ try
+ {
+ var listView = sender as ListView;
+ var trackVm = listView.SelectedItem as TrackViewModel;
+ // Set this ID as manually played by the user to prevent unnecessary autoscrolling.
+ // Kind of a duct tape fix for now
+ // TODO: Apply to context menu as well, maybe main playbar buttons if the queue is showing?
+ manualSongId = trackVm.File.Id;
+ trackVm.PlayTrackCommand.Execute(trackVm.File);
+ }
+ catch (Exception ex)
+ {
+ Ioc.Default.GetRequiredService().ShowErrorNotification(ex);
+ }
}
private void Select_Item(object sender, Windows.UI.Xaml.Input.RightTappedRoutedEventArgs e) => UWPHelpers.SelectItemOnFlyoutRightClick(QueueList, e);
From 99045fd9d5a6a7fff6d5cc259a2286cdaa99c9ae Mon Sep 17 00:00:00 2001
From: Difegue
Date: Fri, 16 Jun 2023 01:33:30 +0200
Subject: [PATCH 09/56] (#75) Fix potential failure in GetColor crashing the
album display
---
Sources/Stylophone.Common/Helpers/ColorThief.Skia.cs | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Sources/Stylophone.Common/Helpers/ColorThief.Skia.cs b/Sources/Stylophone.Common/Helpers/ColorThief.Skia.cs
index c1ca7f7..72e3e67 100644
--- a/Sources/Stylophone.Common/Helpers/ColorThief.Skia.cs
+++ b/Sources/Stylophone.Common/Helpers/ColorThief.Skia.cs
@@ -93,6 +93,12 @@ public QuantizedColor GetColor(SKBitmap sourceImage, int quality = DefaultQualit
{
var palette = GetPalette(sourceImage, 3, quality, ignoreWhite);
+ // Handle case where GetPalette returns an empty list (because GetColorMap failed?)
+ if (palette.Count == 0)
+ {
+ return new QuantizedColor(SKColors.Black, 1);
+ }
+
var avgR = Convert.ToByte(palette.Average(a => a.Color.Red));
var avgG = Convert.ToByte(palette.Average(a => a.Color.Green));
var avgB = Convert.ToByte(palette.Average(a => a.Color.Blue));
From c957a84bdd87f803b4a9d4ea090fb99c933edc4b Mon Sep 17 00:00:00 2001
From: Difegue
Date: Mon, 11 Sep 2023 23:40:10 +0200
Subject: [PATCH 10/56] Migrate to Toolkit v8
---
.../Services/MPDConnectionService.cs | 5 -
.../Stylophone.Common.csproj | 8 +-
Sources/Stylophone.iOS/Stylophone.iOS.csproj | 6 +-
.../Behaviors/StackedNotificationsBehavior.cs | 322 ------------------
.../Controls/SettingsBlockControl.xaml | 2 +-
.../Controls/SettingsDisplayControl.xaml | 2 +-
Sources/Stylophone/Services/DialogService.cs | 2 +-
.../Stylophone/Services/DispatcherService.cs | 3 +-
.../Stylophone/Services/NavigationService.cs | 2 +-
.../Services/NotificationService.cs | 5 +-
.../Services/SystemMediaControlsService.cs | 3 +-
Sources/Stylophone/Styles/StyloResources.xaml | 5 +-
Sources/Stylophone/Stylophone.csproj | 44 +--
.../ViewModels/PlaybackViewModel.cs | 2 +-
.../Stylophone/ViewModels/ShellViewModel.cs | 2 +-
Sources/Stylophone/Views/FoldersPage.xaml | 4 +-
.../Stylophone/Views/LibraryDetailPage.xaml | 15 +-
.../Views/LibraryDetailPage.xaml.cs | 2 +-
Sources/Stylophone/Views/LibraryPage.xaml | 17 +-
.../Views/Playback/NowPlayingBar.xaml | 15 +-
.../Views/Playback/OverlayView.xaml | 2 +-
.../Views/Playback/OverlayView.xaml.cs | 2 +-
.../Views/Playback/PlaybackView.xaml | 15 +-
Sources/Stylophone/Views/PlaylistPage.xaml | 45 +--
.../Stylophone/Views/SearchResultsPage.xaml | 2 +-
Sources/Stylophone/Views/ServerQueuePage.xaml | 4 +-
Sources/Stylophone/Views/SettingsPage.xaml | 2 +-
Sources/Stylophone/Views/ShellPage.xaml | 6 +-
28 files changed, 85 insertions(+), 459 deletions(-)
delete mode 100644 Sources/Stylophone/Behaviors/StackedNotificationsBehavior.cs
diff --git a/Sources/Stylophone.Common/Services/MPDConnectionService.cs b/Sources/Stylophone.Common/Services/MPDConnectionService.cs
index c038388..475f67b 100644
--- a/Sources/Stylophone.Common/Services/MPDConnectionService.cs
+++ b/Sources/Stylophone.Common/Services/MPDConnectionService.cs
@@ -11,11 +11,6 @@
using Stylophone.Common.Interfaces;
using MpcNET.Commands.Reflection;
using Stylophone.Localization.Strings;
-using CommunityToolkit.Mvvm.DependencyInjection;
-using Stylophone.Common.ViewModels;
-using Microsoft.AppCenter.Analytics;
-using Microsoft.AppCenter;
-using System.Drawing;
namespace Stylophone.Common.Services
{
diff --git a/Sources/Stylophone.Common/Stylophone.Common.csproj b/Sources/Stylophone.Common/Stylophone.Common.csproj
index 84d56ce..acff074 100644
--- a/Sources/Stylophone.Common/Stylophone.Common.csproj
+++ b/Sources/Stylophone.Common/Stylophone.Common.csproj
@@ -7,14 +7,14 @@
-
-
+
+
-
+
-
+
diff --git a/Sources/Stylophone.iOS/Stylophone.iOS.csproj b/Sources/Stylophone.iOS/Stylophone.iOS.csproj
index 87fcb18..d959dd3 100644
--- a/Sources/Stylophone.iOS/Stylophone.iOS.csproj
+++ b/Sources/Stylophone.iOS/Stylophone.iOS.csproj
@@ -216,13 +216,13 @@
2.88.1
- 6.0.0
+ 7.0.0
- 4.5.3
+ 5.0.2
- 4.5.3
+ 5.0.2
0.0.1
diff --git a/Sources/Stylophone/Behaviors/StackedNotificationsBehavior.cs b/Sources/Stylophone/Behaviors/StackedNotificationsBehavior.cs
deleted file mode 100644
index af7efe3..0000000
--- a/Sources/Stylophone/Behaviors/StackedNotificationsBehavior.cs
+++ /dev/null
@@ -1,322 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-// TODO: Remove this when StackedNotificationsBehavior lands in Toolkit
-
-using Microsoft.Toolkit.Uwp.UI.Behaviors;
-using Microsoft.UI.Xaml.Controls;
-using System;
-using System.Collections.Generic;
-using Windows.System;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Controls.Primitives;
-using Windows.UI.Xaml.Input;
-using DQ = Windows.System.DispatcherQueue;
-
-namespace CommunityToolkit.Labs.WinUI
-{
- ///
- /// The content of a notification to display in .
- /// The , , and values will
- /// always be applied to the targeted .
- /// The , , and values
- /// will be applied only if set.
- ///
- public class Notification
- {
- private NotificationOverrides _overrides;
- private bool _isIconVisible;
- private object? _content;
- private DataTemplate? _contentTemplate;
- private ButtonBase? _actionButton;
-
- ///
- /// Gets or sets the notification title.
- ///
- public string? Title { get; set; }
-
- ///
- /// Gets or sets the notification message.
- ///
- public string? Message { get; set; }
-
- ///
- /// Gets or sets the duration of the notification.
- /// Set to null for persistent notification.
- ///
- public TimeSpan? Duration { get; set; }
-
- ///
- /// Gets or sets the type of the to apply consistent status color, icon,
- /// and assistive technology settings dependent on the criticality of the notification.
- ///
- public InfoBarSeverity Severity { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the icon is visible or not.
- /// True if the icon is visible; otherwise, false. The default is true.
- ///
- public bool IsIconVisible
- {
- get => _isIconVisible;
- set
- {
- _isIconVisible = value;
- _overrides |= NotificationOverrides.Icon;
- }
- }
-
- ///
- /// Gets or sets the XAML Content that is displayed below the title and message in
- /// the InfoBar.
- ///
- public object? Content
- {
- get => _content;
- set
- {
- _content = value;
- _overrides |= NotificationOverrides.Content;
- }
- }
-
- ///
- /// Gets or sets the data template for the .
- ///
- public DataTemplate? ContentTemplate
- {
- get => _contentTemplate;
- set
- {
- _contentTemplate = value;
- _overrides |= NotificationOverrides.ContentTemplate;
- }
- }
-
- ///
- /// Gets or sets the action button of the InfoBar.
- ///
- public ButtonBase? ActionButton
- {
- get => _actionButton;
- set
- {
- _actionButton = value;
- _overrides |= NotificationOverrides.ActionButton;
- }
- }
-
- internal NotificationOverrides Overrides => _overrides;
- }
-
- ///
- /// The overrides which should be set on the notification.
- ///
- [Flags]
- internal enum NotificationOverrides
- {
- None,
- Icon,
- Content,
- ContentTemplate,
- ActionButton,
- }
-
- ///
- /// A behavior to add the stacked notification support to .
- ///
- public class StackedNotificationsBehavior : BehaviorBase
- {
- private readonly LinkedList _stackedNotifications;
- private readonly DispatcherQueueTimer _dismissTimer;
- private Notification? _currentNotification;
- private bool _initialIconVisible;
- private object? _initialContent;
- private DataTemplate? _initialContentTemplate;
- private ButtonBase? _initialActionButton;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public StackedNotificationsBehavior()
- {
- _stackedNotifications = new LinkedList();
-
- // TODO: On WinUI 3 we can use the local DispatcherQueue, so we need to abstract better for UWP
- var dispatcherQueue = DQ.GetForCurrentThread();
- _dismissTimer = dispatcherQueue.CreateTimer();
- _dismissTimer.Tick += OnTimerTick;
- }
-
- ///
- /// Show .
- ///
- /// The notification to display.
- public void Show(Notification notification)
- {
- if (notification is null)
- {
- throw new ArgumentNullException(nameof(notification));
- }
-
- _stackedNotifications.AddLast(notification);
- ShowNext();
- }
-
- ///
- /// Remove the .
- /// If the notification is displayed, it will be closed.
- /// If the notification is still in the queue, it will be removed.
- ///
- /// The notification to remove.
- public void Remove(Notification notification)
- {
- if (notification is null)
- {
- throw new ArgumentNullException(nameof(notification));
- }
-
- if (notification == _currentNotification)
- {
- // We close the notification. This will trigger the display of the next one.
- // See OnInfoBarClosed.
- AssociatedObject.IsOpen = false;
- return;
- }
-
- _stackedNotifications.Remove(notification);
- }
-
- ///
- protected override bool Initialize()
- {
- AssociatedObject.Closed += OnInfoBarClosed;
- AssociatedObject.PointerEntered += OnPointerEntered;
- AssociatedObject.PointerExited += OnPointedExited;
- return true;
- }
-
- ///
- protected override bool Uninitialize()
- {
- AssociatedObject.Closed -= OnInfoBarClosed;
- AssociatedObject.PointerEntered -= OnPointerEntered;
- AssociatedObject.PointerExited -= OnPointedExited;
- return true;
- }
-
- private void OnInfoBarClosed(InfoBar sender, InfoBarClosedEventArgs args)
- {
- // We display the next notification.
- ShowNext();
- }
-
- private void ShowNext()
- {
- if (AssociatedObject.IsOpen)
- {
- // One notification is already displayed. We wait for it to close
- return;
- }
-
- StopTimer();
- AssociatedObject.IsOpen = false;
- RestoreOverridenProperties();
-
- if (_stackedNotifications.Count == 0)
- {
- _currentNotification = null;
- return;
- }
-
- var notificationToDisplay = _stackedNotifications!.First!.Value;
- _stackedNotifications.RemoveFirst();
-
- _currentNotification = notificationToDisplay;
- SetNotification(notificationToDisplay);
- AssociatedObject.IsOpen = true;
-
- StartTimer(notificationToDisplay.Duration);
- }
-
- private void SetNotification(Notification notification)
- {
- AssociatedObject.Title = notification.Title ?? string.Empty;
- AssociatedObject.Message = notification.Message ?? string.Empty;
- AssociatedObject.Severity = notification.Severity;
-
- if (notification.Overrides.HasFlag(NotificationOverrides.Icon))
- {
- _initialIconVisible = AssociatedObject.IsIconVisible;
- AssociatedObject.IsIconVisible = notification.IsIconVisible;
- }
-
- if (notification.Overrides.HasFlag(NotificationOverrides.Content))
- {
- _initialContent = AssociatedObject.Content;
- AssociatedObject.Content = notification.Content!;
- }
-
- if (notification.Overrides.HasFlag(NotificationOverrides.ContentTemplate))
- {
- _initialContentTemplate = AssociatedObject.ContentTemplate;
- AssociatedObject.ContentTemplate = notification.ContentTemplate!;
- }
-
- if (notification.Overrides.HasFlag(NotificationOverrides.ActionButton))
- {
- _initialActionButton = AssociatedObject.ActionButton;
- AssociatedObject.ActionButton = notification.ActionButton!;
- }
- }
-
- private void RestoreOverridenProperties()
- {
- if (_currentNotification is null)
- {
- return;
- }
-
- if (_currentNotification.Overrides.HasFlag(NotificationOverrides.Icon))
- {
- AssociatedObject.IsIconVisible = _initialIconVisible;
- }
-
- if (_currentNotification.Overrides.HasFlag(NotificationOverrides.Content))
- {
- AssociatedObject.Content = _initialContent!;
- }
-
- if (_currentNotification.Overrides.HasFlag(NotificationOverrides.ContentTemplate))
- {
- AssociatedObject.ContentTemplate = _initialContentTemplate!;
- }
-
- if (_currentNotification.Overrides.HasFlag(NotificationOverrides.ActionButton))
- {
- AssociatedObject.ActionButton = _initialActionButton!;
- }
- }
-
- private void StartTimer(TimeSpan? duration)
- {
- if (duration is null)
- {
- return;
- }
-
- _dismissTimer.Interval = duration.Value;
- _dismissTimer.Start();
- }
-
- private void StopTimer() => _dismissTimer.Stop();
-
- private void OnTimerTick(DispatcherQueueTimer sender, object args) => AssociatedObject.IsOpen = false;
-
- private void OnPointedExited(object sender, PointerRoutedEventArgs e) => StartTimer(_currentNotification?.Duration);
-
- private void OnPointerEntered(object sender, PointerRoutedEventArgs e) => StopTimer();
- }
-
-}
-
diff --git a/Sources/Stylophone/Controls/SettingsBlockControl.xaml b/Sources/Stylophone/Controls/SettingsBlockControl.xaml
index 1f58b7e..d59f9e0 100644
--- a/Sources/Stylophone/Controls/SettingsBlockControl.xaml
+++ b/Sources/Stylophone/Controls/SettingsBlockControl.xaml
@@ -3,7 +3,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Stylophone.Controls"
- xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
+ xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
diff --git a/Sources/Stylophone/Controls/SettingsDisplayControl.xaml b/Sources/Stylophone/Controls/SettingsDisplayControl.xaml
index b8d4a26..8929217 100644
--- a/Sources/Stylophone/Controls/SettingsDisplayControl.xaml
+++ b/Sources/Stylophone/Controls/SettingsDisplayControl.xaml
@@ -2,7 +2,7 @@
x:Class="Stylophone.Controls.SettingsDisplayControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
+ xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
diff --git a/Sources/Stylophone/Services/DialogService.cs b/Sources/Stylophone/Services/DialogService.cs
index fd78844..ffbf5a1 100644
--- a/Sources/Stylophone/Services/DialogService.cs
+++ b/Sources/Stylophone/Services/DialogService.cs
@@ -2,7 +2,6 @@
using System.Threading.Tasks;
using Stylophone.Views;
-using Microsoft.Toolkit.Uwp.Helpers;
using Stylophone.Common.Interfaces;
using Stylophone.Common.Services;
using Stylophone.Common.ViewModels;
@@ -12,6 +11,7 @@
using Windows.Services.Store;
using Windows.UI.Xaml.Media;
using System.Linq;
+using Microsoft.Toolkit.Uwp.Helpers;
namespace Stylophone.Services
{
diff --git a/Sources/Stylophone/Services/DispatcherService.cs b/Sources/Stylophone/Services/DispatcherService.cs
index fa5c076..054b100 100644
--- a/Sources/Stylophone/Services/DispatcherService.cs
+++ b/Sources/Stylophone/Services/DispatcherService.cs
@@ -1,4 +1,5 @@
-using Microsoft.Toolkit.Uwp;
+using CommunityToolkit;
+using CommunityToolkit.WinUI;
using Stylophone.Common.Interfaces;
using System;
using System.Threading.Tasks;
diff --git a/Sources/Stylophone/Services/NavigationService.cs b/Sources/Stylophone/Services/NavigationService.cs
index 43e4976..5bf1737 100644
--- a/Sources/Stylophone/Services/NavigationService.cs
+++ b/Sources/Stylophone/Services/NavigationService.cs
@@ -1,7 +1,7 @@
using Stylophone.ViewModels;
using Stylophone.Views;
using CommunityToolkit.Mvvm.ComponentModel;
-using Microsoft.Toolkit.Uwp.UI.Animations;
+using CommunityToolkit.WinUI.Animations;
using Stylophone.Common.Interfaces;
using Stylophone.Common.ViewModels;
using System;
diff --git a/Sources/Stylophone/Services/NotificationService.cs b/Sources/Stylophone/Services/NotificationService.cs
index ddec931..311e652 100644
--- a/Sources/Stylophone/Services/NotificationService.cs
+++ b/Sources/Stylophone/Services/NotificationService.cs
@@ -1,5 +1,4 @@
using System;
-using CommunityToolkit.Mvvm.Messaging.Messages;
using Microsoft.Toolkit.Uwp.Notifications;
using Windows.UI.Notifications;
using Stylophone.Common.Interfaces;
@@ -21,7 +20,7 @@ public override void ShowBasicToastNotification(string title, string description
// Create the toast content
var content = new ToastContent()
{
- // More about the Launch property at https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.notifications.toastcontent
+ // More about the Launch property at https://docs.microsoft.com/dotnet/api/CommunityToolkit.notifications.toastcontent
Launch = "ToastContentActivationParams",
Visual = new ToastVisual()
@@ -47,7 +46,7 @@ public override void ShowBasicToastNotification(string title, string description
{
Buttons =
{
- // More about Toast Buttons at https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.notifications.toastbutton
+ // More about Toast Buttons at https://docs.microsoft.com/dotnet/api/CommunityToolkit.notifications.toastbutton
new ToastButton("OK", "ToastButtonActivationArguments")
{
ActivationType = ToastActivationType.Foreground
diff --git a/Sources/Stylophone/Services/SystemMediaControlsService.cs b/Sources/Stylophone/Services/SystemMediaControlsService.cs
index 2d501e1..a4ad2d5 100644
--- a/Sources/Stylophone/Services/SystemMediaControlsService.cs
+++ b/Sources/Stylophone/Services/SystemMediaControlsService.cs
@@ -1,7 +1,5 @@
using System;
using System.Threading.Tasks;
-using Stylophone.Helpers;
-using Microsoft.Toolkit.Uwp.Helpers;
using MpcNET;
using MpcNET.Commands.Playback;
using Stylophone.Common.Helpers;
@@ -10,6 +8,7 @@
using Windows.Media;
using Windows.Storage;
using Windows.Storage.Streams;
+using Microsoft.Toolkit.Uwp.Helpers;
namespace Stylophone.Services
{
diff --git a/Sources/Stylophone/Styles/StyloResources.xaml b/Sources/Stylophone/Styles/StyloResources.xaml
index aa34e0c..ed16f68 100644
--- a/Sources/Stylophone/Styles/StyloResources.xaml
+++ b/Sources/Stylophone/Styles/StyloResources.xaml
@@ -3,10 +3,11 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Stylophone="using:Stylophone.Helpers"
- xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
+ xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:Stylophone.Common.ViewModels"
+ xmlns:media="using:CommunityToolkit.WinUI.Media"
mc:Ignorable="d">
@@ -30,7 +31,7 @@
-
+
diff --git a/Sources/Stylophone/Stylophone.csproj b/Sources/Stylophone/Stylophone.csproj
index 89186d5..93f2d3a 100644
--- a/Sources/Stylophone/Stylophone.csproj
+++ b/Sources/Stylophone/Stylophone.csproj
@@ -139,36 +139,27 @@
PackageReference
-
- 4.5.3
-
-
- 4.5.3
-
-
- 6.0.0
-
+
+
+
6.2.14
10.1901.28001
-
- 7.1.2
-
-
- 7.1.2
-
-
- 7.1.2
-
-
- 7.1.2
-
-
- 7.1.2
-
+
+
+
+
+
+
+
+
+
+
+
+
2.7.3
@@ -181,9 +172,7 @@
2.88.1
-
- 3.3.2
-
+
1.1.0
@@ -194,7 +183,6 @@
-
SettingsBlockControl.xaml
diff --git a/Sources/Stylophone/ViewModels/PlaybackViewModel.cs b/Sources/Stylophone/ViewModels/PlaybackViewModel.cs
index c6eecac..2d7b62c 100644
--- a/Sources/Stylophone/ViewModels/PlaybackViewModel.cs
+++ b/Sources/Stylophone/ViewModels/PlaybackViewModel.cs
@@ -1,6 +1,6 @@
using Stylophone.Services;
using Stylophone.Views;
-using Microsoft.Toolkit.Uwp;
+using CommunityToolkit;
using Stylophone.Common.Interfaces;
using Stylophone.Common.Services;
using Stylophone.Common.ViewModels;
diff --git a/Sources/Stylophone/ViewModels/ShellViewModel.cs b/Sources/Stylophone/ViewModels/ShellViewModel.cs
index 3f7ec30..15d0e32 100644
--- a/Sources/Stylophone/ViewModels/ShellViewModel.cs
+++ b/Sources/Stylophone/ViewModels/ShellViewModel.cs
@@ -14,9 +14,9 @@
using Stylophone.Services;
using Windows.Foundation;
using MpcNET.Commands.Playback;
-using CommunityToolkit.Labs.WinUI;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.UI.Xaml.Controls;
+using CommunityToolkit.WinUI.Behaviors;
namespace Stylophone.ViewModels
{
diff --git a/Sources/Stylophone/Views/FoldersPage.xaml b/Sources/Stylophone/Views/FoldersPage.xaml
index 01cc0c8..804a7f6 100644
--- a/Sources/Stylophone/Views/FoldersPage.xaml
+++ b/Sources/Stylophone/Views/FoldersPage.xaml
@@ -3,12 +3,12 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="using:Stylophone.Behaviors"
- xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
+ xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:strings="using:Stylophone.Localization.Strings"
- xmlns:ui="using:Microsoft.Toolkit.Uwp.UI"
+ xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:vm="using:Stylophone.Common.ViewModels"
xmlns:winui="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
diff --git a/Sources/Stylophone/Views/LibraryDetailPage.xaml b/Sources/Stylophone/Views/LibraryDetailPage.xaml
index 4506db2..61dab23 100644
--- a/Sources/Stylophone/Views/LibraryDetailPage.xaml
+++ b/Sources/Stylophone/Views/LibraryDetailPage.xaml
@@ -2,12 +2,12 @@
x:Class="Stylophone.Views.LibraryDetailPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
+ xmlns:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:strings="using:Stylophone.Localization.Strings"
xmlns:stylophone="using:Stylophone.Helpers"
- xmlns:ui="using:Microsoft.Toolkit.Uwp.UI"
+ xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:winui="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
@@ -57,18 +57,15 @@
-
+ ui:Effects.Shadow="{StaticResource CommonShadow}"
+ >
-
+
-
+ ui:Effects.Shadow="{StaticResource CommonShadow}">
@@ -96,7 +93,7 @@
-
+
diff --git a/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml b/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml
index 0265fe1..00ee6c7 100644
--- a/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml
+++ b/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml
@@ -3,11 +3,11 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WindowsStateTriggers="using:WindowsStateTriggers"
- xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
- xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
+ xmlns:controls="using:CommunityToolkit.WinUI.Converters"
+ xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:ui="using:Microsoft.Toolkit.Uwp.UI"
+ xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:strings="using:Stylophone.Localization.Strings"
d:DesignHeight="96"
mc:Ignorable="d">
@@ -115,16 +115,13 @@
-
+ ui:Effects.Shadow="{StaticResource CommonShadow}">
-
+
-
+ ui:Effects.Shadow="{StaticResource CommonShadow}">
-
+
@@ -57,22 +57,16 @@
-
+ ui:Effects.Shadow="{StaticResource CommonShadow}">
-
+
-
+ ui:Effects.Shadow="{StaticResource CommonShadow}">
-
+
-
+ ui:Effects.Shadow="{StaticResource CommonShadow}">
-
+
-
-
-
-
-
diff --git a/Sources/Stylophone/Views/SearchResultsPage.xaml b/Sources/Stylophone/Views/SearchResultsPage.xaml
index 08eb1c4..636c958 100644
--- a/Sources/Stylophone/Views/SearchResultsPage.xaml
+++ b/Sources/Stylophone/Views/SearchResultsPage.xaml
@@ -6,7 +6,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:strings="using:Stylophone.Localization.Strings"
- xmlns:ui="using:Microsoft.Toolkit.Uwp.UI"
+ xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:winui="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
diff --git a/Sources/Stylophone/Views/ServerQueuePage.xaml b/Sources/Stylophone/Views/ServerQueuePage.xaml
index c17b827..dcdd0ff 100644
--- a/Sources/Stylophone/Views/ServerQueuePage.xaml
+++ b/Sources/Stylophone/Views/ServerQueuePage.xaml
@@ -3,11 +3,11 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Stylophone="using:Stylophone.Helpers"
- xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
+ xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:strings="using:Stylophone.Localization.Strings"
- xmlns:ui="using:Microsoft.Toolkit.Uwp.UI"
+ xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:vm="using:Stylophone.Common.ViewModels"
NavigationCacheMode="Required"
mc:Ignorable="d">
diff --git a/Sources/Stylophone/Views/SettingsPage.xaml b/Sources/Stylophone/Views/SettingsPage.xaml
index a6e1384..be6ecb8 100644
--- a/Sources/Stylophone/Views/SettingsPage.xaml
+++ b/Sources/Stylophone/Views/SettingsPage.xaml
@@ -3,7 +3,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.UI.Xaml.Controls"
- xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
+ xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Stylophone.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
diff --git a/Sources/Stylophone/Views/ShellPage.xaml b/Sources/Stylophone/Views/ShellPage.xaml
index 5ab3dd5..cc3de41 100644
--- a/Sources/Stylophone/Views/ShellPage.xaml
+++ b/Sources/Stylophone/Views/ShellPage.xaml
@@ -2,8 +2,8 @@
x:Class="Stylophone.Views.ShellPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
- xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
+ xmlns:controls="using:CommunityToolkit.WinUI.Converters"
+ xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helpers="using:Stylophone.Helpers"
xmlns:i="using:Microsoft.Xaml.Interactivity"
@@ -14,7 +14,7 @@
xmlns:strings="using:Stylophone.Localization.Strings"
xmlns:stylophone="using:Stylophone.Common.ViewModels"
xmlns:viewmodels="using:Stylophone.ViewModels"
- xmlns:views="using:Stylophone.Views" xmlns:behaviors="using:CommunityToolkit.Labs.WinUI"
+ xmlns:views="using:Stylophone.Views" xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors"
muxc:BackdropMaterial.ApplyToRootOrPageBackground="True"
PreviewKeyDown="GlobalPlayPauseShortcut"
mc:Ignorable="d">
From ae077a07c308b438a8f10cce5feb3aeaef61ad9f Mon Sep 17 00:00:00 2001
From: Difegue
Date: Mon, 11 Sep 2023 23:57:54 +0200
Subject: [PATCH 11/56] Add unported MiddleClick extension + take advantage of
the namespace mess to add hotfixed AlternateRows
---
.../ListViewExtensions.AlternateRows.cs | 258 +++++++++++
...llViewerExtensions.MiddleClickScrolling.cs | 400 ++++++++++++++++++
Sources/Stylophone/Stylophone.csproj | 14 +-
.../Stylophone/Views/LibraryDetailPage.xaml | 5 +-
Sources/Stylophone/Views/LibraryPage.xaml | 3 +-
Sources/Stylophone/Views/PlaylistPage.xaml | 5 +-
.../Stylophone/Views/SearchResultsPage.xaml | 5 +-
Sources/Stylophone/Views/ServerQueuePage.xaml | 5 +-
8 files changed, 677 insertions(+), 18 deletions(-)
create mode 100644 Sources/Stylophone/Helpers/ListViewExtensions.AlternateRows.cs
create mode 100644 Sources/Stylophone/Helpers/ScrollViewerExtensions.MiddleClickScrolling.cs
diff --git a/Sources/Stylophone/Helpers/ListViewExtensions.AlternateRows.cs b/Sources/Stylophone/Helpers/ListViewExtensions.AlternateRows.cs
new file mode 100644
index 0000000..f10e557
--- /dev/null
+++ b/Sources/Stylophone/Helpers/ListViewExtensions.AlternateRows.cs
@@ -0,0 +1,258 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using CommunityToolkit.WinUI;
+using System.Collections.Generic;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Media;
+
+namespace Microsoft.Toolkit.Uwp.UI
+{
+ ///
+ /// Provides attached dependency properties for the
+ ///
+ public static partial class ListViewExtensions
+ {
+ ///
+ /// Attached for setting the container content stretch direction on the
+ ///
+ public static readonly DependencyProperty ItemContainerStretchDirectionProperty = DependencyProperty.RegisterAttached("ItemContainerStretchDirection", typeof(ItemContainerStretchDirection), typeof(ListViewExtensions), new PropertyMetadata(null, OnItemContainerStretchDirectionPropertyChanged));
+
+ ///
+ /// Gets the stretch associated with the specified
+ ///
+ /// The to get the associated from
+ /// The associated with the
+ public static ItemContainerStretchDirection GetItemContainerStretchDirection(Windows.UI.Xaml.Controls.ListViewBase obj)
+ {
+ return (ItemContainerStretchDirection)obj.GetValue(ItemContainerStretchDirectionProperty);
+ }
+
+ ///
+ /// Sets the stretch associated with the specified
+ ///
+ /// The to associate the with
+ /// The for binding to the
+ public static void SetItemContainerStretchDirection(Windows.UI.Xaml.Controls.ListViewBase obj, ItemContainerStretchDirection value)
+ {
+ obj.SetValue(ItemContainerStretchDirectionProperty, value);
+ }
+
+ private static Dictionary, Windows.UI.Xaml.Controls.ListViewBase> _itemsForList = new Dictionary, Windows.UI.Xaml.Controls.ListViewBase>();
+
+ ///
+ /// Attached for binding a as an alternate background color to a
+ ///
+ public static readonly DependencyProperty AlternateColorProperty = DependencyProperty.RegisterAttached("AlternateColor", typeof(Brush), typeof(ListViewExtensions), new PropertyMetadata(null, OnAlternateColorPropertyChanged));
+
+ ///
+ /// Attached for binding a as an alternate template to a
+ ///
+ public static readonly DependencyProperty AlternateItemTemplateProperty = DependencyProperty.RegisterAttached("AlternateItemTemplate", typeof(DataTemplate), typeof(ListViewExtensions), new PropertyMetadata(null, OnAlternateItemTemplatePropertyChanged));
+
+ ///
+ /// Gets the alternate associated with the specified
+ ///
+ /// The to get the associated from
+ /// The associated with the
+ public static Brush GetAlternateColor(Windows.UI.Xaml.Controls.ListViewBase obj)
+ {
+ return (Brush)obj.GetValue(AlternateColorProperty);
+ }
+
+ ///
+ /// Sets the alternate associated with the specified
+ ///
+ /// The to associate the with
+ /// The for binding to the
+ public static void SetAlternateColor(Windows.UI.Xaml.Controls.ListViewBase obj, Brush value)
+ {
+ obj.SetValue(AlternateColorProperty, value);
+ }
+
+ ///
+ /// Gets the associated with the specified
+ ///
+ /// The to get the associated from
+ /// The associated with the
+ public static DataTemplate GetAlternateItemTemplate(Windows.UI.Xaml.Controls.ListViewBase obj)
+ {
+ return (DataTemplate)obj.GetValue(AlternateItemTemplateProperty);
+ }
+
+ ///
+ /// Sets the associated with the specified
+ ///
+ /// The to associate the with
+ /// The for binding to the
+ public static void SetAlternateItemTemplate(Windows.UI.Xaml.Controls.ListViewBase obj, DataTemplate value)
+ {
+ obj.SetValue(AlternateItemTemplateProperty, value);
+ }
+
+ private static void OnAlternateColorPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
+ {
+ Windows.UI.Xaml.Controls.ListViewBase listViewBase = sender as Windows.UI.Xaml.Controls.ListViewBase;
+
+ if (listViewBase == null)
+ {
+ return;
+ }
+
+ listViewBase.ContainerContentChanging -= ColorContainerContentChanging;
+ listViewBase.Items.VectorChanged -= ColorItemsVectorChanged;
+ listViewBase.Unloaded -= OnListViewBaseUnloaded;
+
+ _itemsForList[listViewBase.Items] = listViewBase;
+ if (AlternateColorProperty != null)
+ {
+ listViewBase.ContainerContentChanging += ColorContainerContentChanging;
+ listViewBase.Items.VectorChanged += ColorItemsVectorChanged;
+ listViewBase.Unloaded += OnListViewBaseUnloaded;
+ }
+ }
+
+ private static void ColorContainerContentChanging(Windows.UI.Xaml.Controls.ListViewBase sender, ContainerContentChangingEventArgs args)
+ {
+ var itemContainer = args.ItemContainer as Control;
+ SetItemContainerBackground(sender, itemContainer, args.ItemIndex);
+ }
+
+ private static void OnAlternateItemTemplatePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
+ {
+ Windows.UI.Xaml.Controls.ListViewBase listViewBase = sender as Windows.UI.Xaml.Controls.ListViewBase;
+
+ if (listViewBase == null)
+ {
+ return;
+ }
+
+ listViewBase.ContainerContentChanging -= ItemTemplateContainerContentChanging;
+ listViewBase.Unloaded -= OnListViewBaseUnloaded;
+
+ if (AlternateItemTemplateProperty != null)
+ {
+ listViewBase.ContainerContentChanging += ItemTemplateContainerContentChanging;
+ listViewBase.Unloaded += OnListViewBaseUnloaded;
+ }
+ }
+
+ private static void ItemTemplateContainerContentChanging(Windows.UI.Xaml.Controls.ListViewBase sender, ContainerContentChangingEventArgs args)
+ {
+ var itemContainer = args.ItemContainer as SelectorItem;
+
+ if (args.ItemIndex % 2 == 0)
+ {
+ itemContainer.ContentTemplate = GetAlternateItemTemplate(sender);
+ }
+ else
+ {
+ itemContainer.ContentTemplate = sender.ItemTemplate;
+ }
+ }
+
+ private static void OnItemContainerStretchDirectionPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
+ {
+ Windows.UI.Xaml.Controls.ListViewBase listViewBase = sender as Windows.UI.Xaml.Controls.ListViewBase;
+
+ if (listViewBase == null)
+ {
+ return;
+ }
+
+ listViewBase.ContainerContentChanging -= ItemContainerStretchDirectionChanging;
+ listViewBase.Unloaded -= OnListViewBaseUnloaded;
+
+ if (ItemContainerStretchDirectionProperty != null)
+ {
+ listViewBase.ContainerContentChanging += ItemContainerStretchDirectionChanging;
+ listViewBase.Unloaded += OnListViewBaseUnloaded;
+ }
+ }
+
+ private static void ItemContainerStretchDirectionChanging(Windows.UI.Xaml.Controls.ListViewBase sender, ContainerContentChangingEventArgs args)
+ {
+ var itemContainer = args.ItemContainer as SelectorItem;
+ var stretchDirection = GetItemContainerStretchDirection(sender);
+
+ if (stretchDirection == ItemContainerStretchDirection.Vertical || stretchDirection == ItemContainerStretchDirection.Both)
+ {
+ itemContainer.VerticalContentAlignment = VerticalAlignment.Stretch;
+ }
+
+ if (stretchDirection == ItemContainerStretchDirection.Horizontal || stretchDirection == ItemContainerStretchDirection.Both)
+ {
+ itemContainer.HorizontalContentAlignment = HorizontalAlignment.Stretch;
+ }
+ }
+
+ private static void OnListViewBaseUnloaded(object sender, RoutedEventArgs e)
+ {
+ Windows.UI.Xaml.Controls.ListViewBase listViewBase = sender as Windows.UI.Xaml.Controls.ListViewBase;
+ _itemsForList.Remove(listViewBase.Items);
+
+ listViewBase.ContainerContentChanging -= ItemContainerStretchDirectionChanging;
+ listViewBase.ContainerContentChanging -= ItemTemplateContainerContentChanging;
+ listViewBase.ContainerContentChanging -= ColorContainerContentChanging;
+ listViewBase.Items.VectorChanged -= ColorItemsVectorChanged;
+ listViewBase.Unloaded -= OnListViewBaseUnloaded;
+ }
+
+ private static void ColorItemsVectorChanged(IObservableVector
-
- MSBuild:Compile
- Designer
-
-
- MSBuild:Compile
- Designer
-
Designer
MSBuild:Compile
diff --git a/Sources/Stylophone/Views/SettingsPage.xaml b/Sources/Stylophone/Views/SettingsPage.xaml
index be6ecb8..0e4057c 100644
--- a/Sources/Stylophone/Views/SettingsPage.xaml
+++ b/Sources/Stylophone/Views/SettingsPage.xaml
@@ -9,6 +9,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:strings="using:Stylophone.Localization.Strings"
xmlns:helpers="using:Stylophone.Helpers"
+ xmlns:toolkit="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
@@ -33,37 +34,25 @@
-
+ HeaderIcon="{x:Bind ViewModel.IsServerValid, Converter={StaticResource IconConverter}, Mode=OneWay}">
-
-
-
+
-
-
-
-
-
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
+
-
+
-
-
-
-
+
+
-
-
-
+
+
+
+
+
+
-
-
+
-
-
-
+
+
-
-
+
@@ -123,42 +105,40 @@
Style="{ThemeResource BaseTextBlockStyle}"
Text="{x:Bind strings:Resources.SettingsDatabase}" />
-
-
+
-
+
-
+
-
-
+
-
-
-
+
-
-
-
-
+
+
+
-
+
-
-
-
+
+
+
@@ -167,34 +147,31 @@
Style="{ThemeResource BaseTextBlockStyle}"
Text="{x:Bind strings:Resources.SettingsCustomization}" />
-
-
+
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
-
+
-
-
+
+
-
+
-
-
-
-
-
-
+
+
+
+
-
+
@@ -203,21 +180,18 @@
Style="{ThemeResource BaseTextBlockStyle}"
Text="{x:Bind strings:Resources.SettingsAnalytics}" />
-
-
+
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
From 74fc65861990a4561350f73a8bc41479590de233 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 12 Sep 2023 01:00:54 +0200
Subject: [PATCH 13/56] Fix Library shadows + use Segmented in SearchResults
---
Sources/Stylophone/Views/LibraryPage.xaml | 22 +++++-------
.../Stylophone/Views/SearchResultsPage.xaml | 36 +++++++++----------
2 files changed, 26 insertions(+), 32 deletions(-)
diff --git a/Sources/Stylophone/Views/LibraryPage.xaml b/Sources/Stylophone/Views/LibraryPage.xaml
index 55d69b1..06e1cfc 100644
--- a/Sources/Stylophone/Views/LibraryPage.xaml
+++ b/Sources/Stylophone/Views/LibraryPage.xaml
@@ -4,16 +4,14 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
xmlns:behaviors="using:Stylophone.Behaviors"
- xmlns:controls="using:CommunityToolkit.WinUI.Converters"
- xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:strings="using:Stylophone.Localization.Strings"
- xmlns:stylophone="using:Stylophone.Helpers"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:ui7="using:Microsoft.Toolkit.Uwp.UI"
xmlns:vm="using:Stylophone.Common.ViewModels"
xmlns:winui="using:Microsoft.UI.Xaml.Controls"
+ xmlns:media="using:CommunityToolkit.WinUI.Media"
NavigationCacheMode="Required"
mc:Ignorable="d">
@@ -49,37 +47,37 @@
-
+ VerticalAlignment="Center">
+
+
+
+
-
+
-
-
+
-
@@ -106,7 +104,7 @@
diff --git a/Sources/Stylophone.iOS/Properties/AssemblyInfo.cs b/Sources/Stylophone.iOS/Properties/AssemblyInfo.cs
deleted file mode 100644
index 63e95fb..0000000
--- a/Sources/Stylophone.iOS/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Stylophone.iOS")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Stylophone.iOS")]
-[assembly: AssemblyCopyright("Copyright © 2017")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("50c7b8c9-e664-45af-b88e-0c9b8b9c1be1")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Sources/Stylophone.iOS/Stylophone.iOS.csproj b/Sources/Stylophone.iOS/Stylophone.iOS.csproj
index 8c538a2..ada7666 100644
--- a/Sources/Stylophone.iOS/Stylophone.iOS.csproj
+++ b/Sources/Stylophone.iOS/Stylophone.iOS.csproj
@@ -1,11 +1,17 @@
- net6.0-ios
+ net7.0-ios
Exe
enable
true
15.0
+
+ false
+
+
+ false
+
SidebarViewController.cs
@@ -49,23 +55,17 @@
PlaylistViewController.cs
-
-
-
+
SymbolUIButton.cs
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/Sources/Stylophone.sln b/Sources/Stylophone.sln
index 14a645d..6f9bc7f 100644
--- a/Sources/Stylophone.sln
+++ b/Sources/Stylophone.sln
@@ -9,7 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stylophone.Common", "Stylop
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stylophone.Localization", "Stylophone.Localization\Stylophone.Localization.csproj", "{3DEDF3EF-8DD2-4E20-B057-21DF5E342230}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylophone.iOS", "Stylophone.iOS\Stylophone.iOS.csproj", "{A437E83D-67F2-410A-99DB-6B6D03AA4130}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylophone.iOS", "Stylophone.iOS\Stylophone.iOS.csproj", "{EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -179,48 +179,48 @@ Global
{3DEDF3EF-8DD2-4E20-B057-21DF5E342230}.Release-Stable|x64.Build.0 = Release|Any CPU
{3DEDF3EF-8DD2-4E20-B057-21DF5E342230}.Release-Stable|x86.ActiveCfg = Release|Any CPU
{3DEDF3EF-8DD2-4E20-B057-21DF5E342230}.Release-Stable|x86.Build.0 = Release|Any CPU
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|ARM.ActiveCfg = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|ARM.Build.0 = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|ARM64.ActiveCfg = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|ARM64.Build.0 = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|iPhone.ActiveCfg = Debug|iPhone
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|iPhone.Build.0 = Debug|iPhone
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|x64.ActiveCfg = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|x64.Build.0 = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|x86.ActiveCfg = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Debug|x86.Build.0 = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|ARM.ActiveCfg = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|ARM.Build.0 = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|ARM64.ActiveCfg = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|ARM64.Build.0 = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|iPhone.ActiveCfg = Release|iPhone
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|iPhone.Build.0 = Release|iPhone
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|x64.ActiveCfg = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|x64.Build.0 = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|x86.ActiveCfg = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release|x86.Build.0 = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|Any CPU.ActiveCfg = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|Any CPU.Build.0 = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|ARM.ActiveCfg = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|ARM.Build.0 = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|ARM64.ActiveCfg = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|ARM64.Build.0 = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|iPhone.ActiveCfg = Release|iPhone
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|iPhone.Build.0 = Release|iPhone
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|x64.ActiveCfg = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|x64.Build.0 = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|x86.ActiveCfg = Debug|iPhoneSimulator
- {A437E83D-67F2-410A-99DB-6B6D03AA4130}.Release-Stable|x86.Build.0 = Debug|iPhoneSimulator
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|ARM.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|ARM64.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|x64.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Debug|x86.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|ARM.ActiveCfg = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|ARM.Build.0 = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|ARM64.ActiveCfg = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|ARM64.Build.0 = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|iPhone.Build.0 = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|x64.ActiveCfg = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|x64.Build.0 = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|x86.ActiveCfg = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release|x86.Build.0 = Release|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|Any CPU.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|Any CPU.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|ARM.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|ARM.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|ARM64.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|ARM64.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|iPhone.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|iPhone.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|x64.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|x64.Build.0 = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|x86.ActiveCfg = Debug|Any CPU
+ {EF817BEC-A839-4BAD-8E48-75B42A3EDAC4}.Release-Stable|x86.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
From f7ebcaddc26d6a6ccf67b1a566065c75a4c38115 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 12 Sep 2023 22:15:24 +0200
Subject: [PATCH 17/56] Use a custom size detent for addToPlaylistDialog so
it's not half empty space
---
Sources/Stylophone.iOS/Services/DialogService.cs | 6 ++++--
.../ViewControllers/AddToPlaylistViewController.cs | 14 +++++++++-----
2 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/Sources/Stylophone.iOS/Services/DialogService.cs b/Sources/Stylophone.iOS/Services/DialogService.cs
index aad8b33..55d3ee3 100644
--- a/Sources/Stylophone.iOS/Services/DialogService.cs
+++ b/Sources/Stylophone.iOS/Services/DialogService.cs
@@ -39,9 +39,11 @@ public async Task ShowAddToPlaylistDialog(bool allowExistingPlaylists =
var dialog = new AddToPlaylistViewController(_mpdService, allowExistingPlaylists);
var navigationController = new UINavigationController(dialog);
- // Specify medium detent for the NavigationController's presentation
+ // Custom size detent since the addToPlaylist view is quite small
UISheetPresentationController uspc = (UISheetPresentationController)navigationController.PresentationController;
- uspc.Detents = new [] { UISheetPresentationControllerDetent.CreateMediumDetent() };
+
+ var detent = UISheetPresentationControllerDetent.Create(null, (context) => 240);
+ uspc.Detents = new [] { detent };
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(navigationController, true, null);
diff --git a/Sources/Stylophone.iOS/ViewControllers/AddToPlaylistViewController.cs b/Sources/Stylophone.iOS/ViewControllers/AddToPlaylistViewController.cs
index 40c9fb2..dca177a 100644
--- a/Sources/Stylophone.iOS/ViewControllers/AddToPlaylistViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/AddToPlaylistViewController.cs
@@ -58,7 +58,7 @@ public override void LoadView()
{
base.LoadView();
- PreferredContentSize = new CGSize(512, 368);
+ PreferredContentSize = new CGSize(512, 196);
var stackView = new UIStackView {
BackgroundColor = UIColor.SystemBackground,
@@ -70,7 +70,10 @@ public override void LoadView()
var playlistPicker = new UIPickerView();
playlistPicker.DataSource = this;
- playlistPicker.Delegate = this;
+ playlistPicker.Delegate = this;
+
+ var newPlaylistLabel = new UILabel { Text = Strings.AddToPlaylistText, Font = UIFont.PreferredTitle2 };
+ newPlaylistLabel.Hidden = AllowExistingPlaylists;
var newPlaylistTextField = new UITextField { Placeholder = Strings.AddToPlaylistNewPlaylistName, BorderStyle = UITextBorderStyle.RoundedRect };
newPlaylistTextField.EditingChanged += (s, e) => PlaylistName = newPlaylistTextField.Text;
@@ -85,16 +88,16 @@ public override void LoadView()
AddNewPlaylist = playlistSwitch.SelectedSegment == 1;
playlistPicker.Hidden = AddNewPlaylist;
newPlaylistTextField.Hidden = !AddNewPlaylist;
+ newPlaylistLabel.Hidden = !AddNewPlaylist;
};
if (AllowExistingPlaylists)
stackView.AddArrangedSubview(playlistSwitch);
- //stackView.AddArrangedSubview(new UILabel { Text = Strings.AddToPlaylistText, Font = UIFont.PreferredTitle2 });
-
if (AllowExistingPlaylists)
stackView.AddArrangedSubview(playlistPicker);
-
+
+ stackView.AddArrangedSubview(newPlaylistLabel);
stackView.AddArrangedSubview(newPlaylistTextField);
var spacerView = new UIView();
@@ -104,6 +107,7 @@ public override void LoadView()
var constraints = new List();
constraints.Add(newPlaylistTextField.WidthAnchor.ConstraintEqualTo(View.WidthAnchor, 0.8F));
+ constraints.Add(playlistPicker.HeightAnchor.ConstraintLessThanOrEqualTo(196));
NSLayoutConstraint.ActivateConstraints(constraints.ToArray());
}
From f154c460220bd7f0062c5862e4bb24dc874e472e Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 12 Sep 2023 23:17:35 +0200
Subject: [PATCH 18/56] Replace ARSPopover with native implementation
welp that wasn't too hard
---
.../ViewControllers/PlaybackViewController.cs | 50 +++++++++++++------
1 file changed, 36 insertions(+), 14 deletions(-)
diff --git a/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs b/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
index 7f54035..08f1461 100644
--- a/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
@@ -10,11 +10,9 @@
using Stylophone.Common.ViewModels;
using Stylophone.iOS.Helpers;
using Stylophone.iOS.ViewModels;
-using UIKit;
-// using Pop = ARSPopover.iOS;
-using static Xamarin.Essentials.Permissions;
using CommunityToolkit.Mvvm.Input;
using CoreGraphics;
+using UIKit;
namespace Stylophone.iOS.ViewControllers
{
@@ -271,22 +269,46 @@ private UIBarButtonItem CreateSettingsButton()
public void ShowVolumePopover(UIButton sourceButton, UIViewController sourceVc = null)
{
var sourceBounds = sourceButton.ImageView.Bounds;
+ var size = ViewModel.LocalPlayback.IsEnabled ? new CGSize(276, 176) : new CGSize(276, 96);
- /*var popover = new Pop.ARSPopover
- {
- SourceView = sourceButton.ImageView,
- SourceRect = new CoreGraphics.CGRect(sourceBounds.Width/2, -4, 0, 0),
- ContentSize = ViewModel.LocalPlayback.IsEnabled ?
- new CoreGraphics.CGSize(276, 176) : new CoreGraphics.CGSize(276, 96),
- ArrowDirection = UIPopoverArrowDirection.Down
- };
-
- popover.View.AddSubview(VolumePopover);
+ var popover = new VolumePopoverViewController(VolumePopover, sourceButton, sourceBounds, size);
if (sourceVc == null)
sourceVc = this;
- sourceVc.PresentViewController(popover, true, null);*/
+ sourceVc.PresentViewController(popover, true, null);
+ }
+ }
+
+ public class VolumePopoverViewController: UIViewController, IUIPopoverPresentationControllerDelegate
+ {
+ private UIView _volumeView;
+
+ public VolumePopoverViewController(UIView view, UIButton sourceButton, CGRect sourceBounds, CGSize contentSize)
+ {
+ _volumeView = view;
+
+ ModalPresentationStyle = UIModalPresentationStyle.Popover;
+ PopoverPresentationController.SourceItem = sourceButton.ImageView;
+ PopoverPresentationController.Delegate = this;
+ PopoverPresentationController.PermittedArrowDirections = UIPopoverArrowDirection.Down;
+ PopoverPresentationController.SourceRect = new CGRect(sourceBounds.Width / 2, -4, 0, 0);
+
+ PreferredContentSize = contentSize;
+ }
+
+ [Export("adaptivePresentationStyleForPresentationController:traitCollection:")]
+ public UIModalPresentationStyle GetAdaptivePresentationStyle(UIPresentationController controller, UITraitCollection traitCollection)
+ {
+ // Prevent popover from being adaptive fullscreen on phones
+ // (https://pspdfkit.com/blog/2022/presenting-popovers-on-iphone-with-swiftui/)
+ return UIModalPresentationStyle.None;
+ }
+
+ public override void ViewDidLoad()
+ {
+ base.ViewDidLoad();
+ View.AddSubview(_volumeView);
}
}
}
From bcfca5c53f6757ddb3aaec26181290855619092a Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 12 Sep 2023 23:58:08 +0200
Subject: [PATCH 19/56] Cheaply use alerts for inapp notis
because I'm too lazy to roll something custom while tipkit will be out soon
---
.../Services/NotificationService.cs | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/Sources/Stylophone.iOS/Services/NotificationService.cs b/Sources/Stylophone.iOS/Services/NotificationService.cs
index 00e58de..7c66e7f 100644
--- a/Sources/Stylophone.iOS/Services/NotificationService.cs
+++ b/Sources/Stylophone.iOS/Services/NotificationService.cs
@@ -2,7 +2,6 @@
using UserNotifications;
using Stylophone.Common.Interfaces;
using UIKit;
-//using Xam.RMessage;
namespace Stylophone.iOS.Services
{
@@ -22,16 +21,12 @@ public override void ShowInAppNotification(InAppNotification notification)
if (UIApplication.SharedApplication.ApplicationState != UIApplicationState.Active)
return;
- /*RMessageType type = notification.NotificationType switch
- {
- NotificationType.Info => RMessageType.Normal,
- NotificationType.Warning => RMessageType.Warning,
- NotificationType.Error => RMessageType.Error,
- _ => RMessageType.Normal
- };
-
- RMessage.ShowNotificationWithTitle(notification.NotificationTitle, notification.NotificationText, type, "",
- notification.NotificationType == NotificationType.Error ? 300000 : 2, () => { }); */
+ // Let's just use alerts until TipKit is available... This is cheap but w/e
+ var alert = new UIAlertView(notification.NotificationTitle, notification.NotificationText, null, "Ok");
+
+ if (notification.NotificationType == NotificationType.Error)
+ alert.Show();
+
});
}
From 6377fbe7c3900eb1de4d654c4d9eebbd28e23907 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Wed, 13 Sep 2023 23:22:17 +0200
Subject: [PATCH 20/56] Copy RangedObservableCollection and hack it to fix
range removals with TableViews
---
.../Helpers/RangedObservableCollection.cs | 170 ++++++++++++++++++
.../Stylophone.Common.csproj | 1 -
.../Helpers/TrackTableViewDataSource.cs | 4 +-
3 files changed, 173 insertions(+), 2 deletions(-)
create mode 100644 Sources/Stylophone.Common/Helpers/RangedObservableCollection.cs
diff --git a/Sources/Stylophone.Common/Helpers/RangedObservableCollection.cs b/Sources/Stylophone.Common/Helpers/RangedObservableCollection.cs
new file mode 100644
index 0000000..6136281
--- /dev/null
+++ b/Sources/Stylophone.Common/Helpers/RangedObservableCollection.cs
@@ -0,0 +1,170 @@
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+
+namespace System.Collections.ObjectModel
+{
+ ///
+ /// Implementation of a dynamic data collection based on generic Collection<T>,
+ /// implementing INotifyCollectionChanged to notify listeners
+ /// when items get added, removed or the whole list is refreshed.
+ ///
+ public class RangedObservableCollection : ObservableCollection
+ {
+ private const string CountName = "Count";
+ private const string IndexerName = "Item[]";
+
+ ///
+ /// Initializes a new instance of RangedObservableCollection that is empty and has default initial capacity.
+ ///
+ public RangedObservableCollection()
+ : base()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the RangedObservableCollection class that contains
+ /// elements copied from the specified collection and has sufficient capacity
+ /// to accommodate the number of elements copied.
+ ///
+ /// The collection whose elements are copied to the new list.
+ ///
+ /// The elements are copied onto the RangedObservableCollection in the
+ /// same order they are read by the enumerator of the collection.
+ ///
+ /// collection is a null reference
+ public RangedObservableCollection(IEnumerable collection)
+ : base(collection)
+ {
+ }
+
+ ///
+ /// Adds the elements of the specified collection to the end of the RangedObservableCollection.
+ ///
+ /// The collection whose elements are added to the list.
+ ///
+ /// The elements are copied onto the RangedObservableCollection in the
+ /// same order they are read by the enumerator of the collection.
+ ///
+ /// collection is a null reference
+ public void AddRange(IEnumerable collection)
+ {
+ if (collection == null)
+ throw new ArgumentNullException(nameof(collection));
+
+ CheckReentrancy();
+
+ var startIndex = Count;
+ var changedItems = new List(collection);
+
+ foreach (var i in changedItems)
+ Items.Add(i);
+
+ OnCountPropertyChanged();
+ OnIndexerPropertyChanged();
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, changedItems, startIndex));
+ }
+
+ ///
+ /// Clears the current RangedObservableCollection and replaces the elements with the elements of specified collection.
+ ///
+ /// The collection whose elements are added to the list.
+ ///
+ /// The elements are copied onto the RangedObservableCollection in the
+ /// same order they are read by the enumerator of the collection.
+ ///
+ /// collection is a null reference
+ public void ReplaceRange(IEnumerable collection)
+ {
+ if (collection == null)
+ throw new ArgumentNullException(nameof(collection));
+
+ CheckReentrancy();
+
+ Items.Clear();
+ foreach (var i in collection)
+ Items.Add(i);
+
+ OnCountPropertyChanged();
+ OnIndexerPropertyChanged();
+ OnCollectionReset();
+ }
+
+ ///
+ /// Removes the first occurence of each item in the specified collection.
+ ///
+ /// The collection whose elements are removed from list.
+ ///
+ /// The elements are copied onto the RangedObservableCollection in the
+ /// same order they are read by the enumerator of the collection.
+ ///
+ /// collection is a null reference
+ public void RemoveRange(IEnumerable collection)
+ {
+ if (collection == null)
+ throw new ArgumentNullException(nameof(collection));
+
+ CheckReentrancy();
+
+ // HACK ATTACK: normally, since this method can remove items from multiple different spaces in the collection, this'd be incorrect...
+ // but since we only use it for ranged deletions of queue items, which are always sequential, it should be fine(tm)
+ var index = Items.IndexOf(collection.First());
+
+ var changedItems = new List(collection);
+ for (int i = 0; i < changedItems.Count; i++)
+ {
+ if (!Items.Remove(changedItems[i]))
+ {
+ changedItems.RemoveAt(i);
+ i--;
+ }
+ }
+
+ if (changedItems.Count > 0)
+ {
+ OnCountPropertyChanged();
+ OnIndexerPropertyChanged();
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, changedItems, index));
+ }
+ }
+
+ ///
+ /// Clears the current RangedObservableCollection and replaces the elements with the specified element.
+ ///
+ /// The element which is added to the list.
+ public void Replace(T item)
+ {
+ CheckReentrancy();
+
+ Items.Clear();
+ Items.Add(item);
+
+ OnCountPropertyChanged();
+ OnIndexerPropertyChanged();
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+
+ private void OnCountPropertyChanged()
+ {
+ OnPropertyChanged(EventArgsCache.CountPropertyChanged);
+ }
+
+ private void OnIndexerPropertyChanged()
+ {
+ OnPropertyChanged(EventArgsCache.IndexerPropertyChanged);
+ }
+
+ private void OnCollectionReset()
+ {
+ OnCollectionChanged(EventArgsCache.ResetCollectionChanged);
+ }
+
+ private static class EventArgsCache
+ {
+ internal static readonly PropertyChangedEventArgs CountPropertyChanged = new PropertyChangedEventArgs(CountName);
+ internal static readonly PropertyChangedEventArgs IndexerPropertyChanged = new PropertyChangedEventArgs(IndexerName);
+ internal static readonly NotifyCollectionChangedEventArgs ResetCollectionChanged = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Sources/Stylophone.Common/Stylophone.Common.csproj b/Sources/Stylophone.Common/Stylophone.Common.csproj
index a8ca8d9..6c1e1ee 100644
--- a/Sources/Stylophone.Common/Stylophone.Common.csproj
+++ b/Sources/Stylophone.Common/Stylophone.Common.csproj
@@ -11,7 +11,6 @@
-
diff --git a/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs b/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs
index d0a8de7..4e631cc 100644
--- a/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs
+++ b/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs
@@ -74,7 +74,9 @@ private void UpdateUITableView(object sender, NotifyCollectionChangedEventArgs e
if (e.Action == NotifyCollectionChangedAction.Remove)
{
- for (var i = e.OldStartingIndex; i < e.OldStartingIndex + e.OldItems.Count; i++)
+ var startIndex = e.OldStartingIndex;
+
+ for (var i = startIndex; i < startIndex + e.OldItems.Count; i++)
indexPaths.Add(NSIndexPath.FromItemSection(i, 0));
_tableView.DeleteRows(indexPaths.ToArray(), UITableViewRowAnimation.Right);
From 9826cc9d4b0032404f6b7c897c7105e99b71d118 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Thu, 14 Sep 2023 00:18:52 +0200
Subject: [PATCH 21/56] Rework NowPlaying View to take into account safe insets
properly
---
.../Views/NowPlaying.storyboard | 658 +++++++++---------
1 file changed, 333 insertions(+), 325 deletions(-)
diff --git a/Sources/Stylophone.iOS/Views/NowPlaying.storyboard b/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
index 03699eb..6da640e 100644
--- a/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
+++ b/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
@@ -1,8 +1,11 @@
-
-
+
+
+
+
-
+
+
@@ -16,332 +19,340 @@
-
-
+
+
-
+
-
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
+
+
+
-
+
+
-
+
+
-
+
-
-
+
+
-
+
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -367,11 +378,11 @@
-
+
-
+
@@ -384,19 +395,19 @@
-
-
+
-
+
@@ -768,22 +779,19 @@
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
From 09dae25b9dbdf8ca53e79b6df24f44ab1ba0dc6f Mon Sep 17 00:00:00 2001
From: Difegue
Date: Thu, 14 Sep 2023 01:58:01 +0200
Subject: [PATCH 22/56] Fix playlist sizing issues, safe insets and tableview
resizing
the power of ios16....
---
.../Stylophone.iOS/Views/Playlist.storyboard | 119 ++++++++++--------
1 file changed, 65 insertions(+), 54 deletions(-)
diff --git a/Sources/Stylophone.iOS/Views/Playlist.storyboard b/Sources/Stylophone.iOS/Views/Playlist.storyboard
index 4ead2be..6a9ebd6 100644
--- a/Sources/Stylophone.iOS/Views/Playlist.storyboard
+++ b/Sources/Stylophone.iOS/Views/Playlist.storyboard
@@ -1,8 +1,8 @@
-
-
+
+
-
+
@@ -12,25 +12,25 @@
-
-
+
+
-
+
-
+
-
+
-
+
-
-
+
+
+
@@ -157,11 +161,10 @@
-
-
-
-
+
+
+
@@ -178,19 +181,15 @@
-
-
+
+
-
-
-
-
@@ -199,7 +198,6 @@
-
@@ -219,7 +217,6 @@
-
@@ -236,7 +233,7 @@
-
+
@@ -247,11 +244,11 @@
-
+
-
+
@@ -262,17 +259,17 @@
-
+
-
+
-
+
-
-
+
+
@@ -282,31 +279,35 @@
-
+
-
+
-
+
+
+
-
+
-
+
+
+
-
+
@@ -317,8 +318,18 @@
-
+
+
+
+
+
+
+
+
+
+
+
@@ -359,16 +370,16 @@
-
+
-
+
-
-
+
+
From 49f2a05abcf0fc666e9b05f0407ea53ea4b50a6e Mon Sep 17 00:00:00 2001
From: Difegue
Date: Thu, 14 Sep 2023 01:58:22 +0200
Subject: [PATCH 23/56] Add autoshrink to compactplayback track title
---
Sources/Stylophone.iOS/Views/NowPlaying.storyboard | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/Sources/Stylophone.iOS/Views/NowPlaying.storyboard b/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
index 6da640e..c2bda56 100644
--- a/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
+++ b/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
@@ -4,7 +4,6 @@
-
@@ -394,7 +393,7 @@
-
+
From 03f4ff3c3a14aee3c7b3f6a7992945a48bf29161 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Thu, 14 Sep 2023 02:03:36 +0200
Subject: [PATCH 24/56] Allow compact height for queue lines as well
---
Sources/Stylophone.iOS/Views/Queue.storyboard | 54 +++++++++++--------
1 file changed, 33 insertions(+), 21 deletions(-)
diff --git a/Sources/Stylophone.iOS/Views/Queue.storyboard b/Sources/Stylophone.iOS/Views/Queue.storyboard
index ed9a204..18edfbf 100644
--- a/Sources/Stylophone.iOS/Views/Queue.storyboard
+++ b/Sources/Stylophone.iOS/Views/Queue.storyboard
@@ -1,8 +1,8 @@
-
-
+
+
-
+
@@ -12,21 +12,21 @@
-
+
-
+
-
+
-
+
@@ -35,7 +35,7 @@
-
+
@@ -56,17 +56,17 @@
-
+
-
+
-
+
-
-
+
+
@@ -76,14 +76,14 @@
-
+
-
+
@@ -94,15 +94,17 @@
-
+
-
+
+
+
-
+
@@ -113,8 +115,18 @@
-
+
+
+
+
+
+
+
+
+
+
+
@@ -149,8 +161,8 @@
-
-
+
+
From b75b055c54f3b0c3c1382983b243660fb481acb5 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Thu, 14 Sep 2023 02:30:22 +0200
Subject: [PATCH 25/56] Fix AlbumDetail and SearchResults as well
---
.../Views/AlbumDetail.storyboard | 105 +++++++++++-------
.../Views/NowPlaying.storyboard | 100 ++++++++---------
.../Views/SearchResults.storyboard | 32 ++++--
3 files changed, 135 insertions(+), 102 deletions(-)
diff --git a/Sources/Stylophone.iOS/Views/AlbumDetail.storyboard b/Sources/Stylophone.iOS/Views/AlbumDetail.storyboard
index 2b5092c..122955b 100644
--- a/Sources/Stylophone.iOS/Views/AlbumDetail.storyboard
+++ b/Sources/Stylophone.iOS/Views/AlbumDetail.storyboard
@@ -1,8 +1,8 @@
-
-
+
+
-
+
@@ -12,25 +12,25 @@
-
-
+
+
-
+
-
+
-
+
-
+
-
-
+
+
@@ -42,13 +42,13 @@
-
+
-
-
+
+
@@ -72,7 +72,7 @@
-
+
@@ -85,7 +85,7 @@
-
+
@@ -98,10 +98,10 @@
-
+
-
+
@@ -124,14 +124,14 @@
-
-
+
+
-
+
@@ -145,7 +145,7 @@
-
+
@@ -163,10 +163,11 @@
-
+
+
@@ -174,19 +175,17 @@
+
-
-
+
+
-
-
-
@@ -247,11 +246,11 @@
-
+
-
+
@@ -262,17 +261,17 @@
-
+
-
+
-
+
-
-
+
+
@@ -282,23 +281,35 @@
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -309,8 +320,18 @@
-
+
+
+
+
+
+
+
+
+
+
+
@@ -357,9 +378,9 @@
-
+
-
+
diff --git a/Sources/Stylophone.iOS/Views/NowPlaying.storyboard b/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
index c2bda56..b49bbd1 100644
--- a/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
+++ b/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
@@ -1,6 +1,6 @@
-
+
@@ -18,53 +18,53 @@
-
-
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
@@ -72,7 +72,7 @@
-
+
@@ -81,7 +81,7 @@
-
+
@@ -89,7 +89,7 @@
-
+
@@ -100,7 +100,7 @@
-
+
@@ -111,7 +111,7 @@
-
+
@@ -122,7 +122,7 @@
-
+
@@ -133,7 +133,7 @@
-
+
@@ -144,7 +144,7 @@
-
+
@@ -155,7 +155,7 @@
-
+
@@ -361,27 +361,27 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -393,20 +393,20 @@
-
-
+
+
-
+
-
+
@@ -423,7 +423,7 @@
-
+
@@ -440,7 +440,7 @@
-
+
@@ -457,17 +457,17 @@
-
+
-
+
-
+
@@ -482,7 +482,7 @@
-
+
@@ -677,7 +677,7 @@
-
+
@@ -686,10 +686,10 @@
-
+
-
+
@@ -699,7 +699,7 @@
-
+
@@ -725,7 +725,7 @@
-
+
@@ -734,10 +734,10 @@
-
+
-
+
@@ -747,7 +747,7 @@
-
+
diff --git a/Sources/Stylophone.iOS/Views/SearchResults.storyboard b/Sources/Stylophone.iOS/Views/SearchResults.storyboard
index fe48b87..098df16 100644
--- a/Sources/Stylophone.iOS/Views/SearchResults.storyboard
+++ b/Sources/Stylophone.iOS/Views/SearchResults.storyboard
@@ -1,8 +1,8 @@
-
+
-
+
@@ -37,14 +37,14 @@
-
+
-
+
@@ -107,7 +107,7 @@
-
+
@@ -127,7 +127,7 @@
-
+
@@ -147,7 +147,9 @@
-
+
+
+
@@ -164,8 +166,18 @@
-
+
+
+
+
+
+
+
+
+
+
+
@@ -202,8 +214,8 @@
-
-
+
+
From c6a53c2bbc66bed7f0a2eb353ca3ca3bb9b8bbf5 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Thu, 14 Sep 2023 02:42:59 +0200
Subject: [PATCH 26/56] woops
---
.../Stylophone.Common/Helpers/RangedObservableCollection.cs | 2 +-
.../ViewControllers/AlbumDetailViewController.cs | 3 ++-
Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs | 1 +
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/Sources/Stylophone.Common/Helpers/RangedObservableCollection.cs b/Sources/Stylophone.Common/Helpers/RangedObservableCollection.cs
index 6136281..97bb61e 100644
--- a/Sources/Stylophone.Common/Helpers/RangedObservableCollection.cs
+++ b/Sources/Stylophone.Common/Helpers/RangedObservableCollection.cs
@@ -109,7 +109,7 @@ public void RemoveRange(IEnumerable collection)
// HACK ATTACK: normally, since this method can remove items from multiple different spaces in the collection, this'd be incorrect...
// but since we only use it for ranged deletions of queue items, which are always sequential, it should be fine(tm)
- var index = Items.IndexOf(collection.First());
+ var index = Items.IndexOf(collection.FirstOrDefault());
var changedItems = new List(collection);
for (int i = 0; i < changedItems.Count; i++)
diff --git a/Sources/Stylophone.iOS/ViewControllers/AlbumDetailViewController.cs b/Sources/Stylophone.iOS/ViewControllers/AlbumDetailViewController.cs
index 0f19bab..8eeff0b 100644
--- a/Sources/Stylophone.iOS/ViewControllers/AlbumDetailViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/AlbumDetailViewController.cs
@@ -37,8 +37,9 @@ public override void AwakeFromNib()
var trackDataSource = new TrackTableViewDataSource(TableView, ViewModel.Source, GetRowContextMenu, GetRowSwipeActions, true, OnScroll);
TableView.DataSource = trackDataSource;
TableView.Delegate = trackDataSource;
+ TableView.SelfSizingInvalidation = UITableViewSelfSizingInvalidation.EnabledIncludingConstraints;
- Binder.Bind(EmptyView, "hidden", nameof(ViewModel.IsSourceEmpty),
+ Binder.Bind(EmptyView, "hidden", nameof(ViewModel.IsSourceEmpty),
valueTransformer: NSValueTransformer.GetValueTransformer(nameof(ReverseBoolValueTransformer)));
Binder.Bind(AlbumTrackInfo, "text", nameof(ViewModel.PlaylistInfo));
}
diff --git a/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs b/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
index ec61bf5..d397e12 100644
--- a/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
@@ -57,6 +57,7 @@ public override void ViewDidLoad()
var trackDataSource = new TrackTableViewDataSource(TableView, ViewModel.Source, GetRowContextMenu, GetRowSwipeActions);
TableView.DataSource = trackDataSource;
TableView.Delegate = trackDataSource;
+ TableView.SelfSizingInvalidation = UITableViewSelfSizingInvalidation.EnabledIncludingConstraints;
_mpdService.SongChanged += ScrollToPlayingSong;
}
From 54fa67f843efb80f605bcf2e4ee5265241ef6748 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Thu, 14 Sep 2023 21:34:35 +0200
Subject: [PATCH 27/56] Fix PropertyBinder bug where visiting multiple album
pages would stack button event subscriptions
---
Sources/Stylophone.iOS/Helpers/PropertyBinder.cs | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/Sources/Stylophone.iOS/Helpers/PropertyBinder.cs b/Sources/Stylophone.iOS/Helpers/PropertyBinder.cs
index 2d11df3..4ab0e17 100644
--- a/Sources/Stylophone.iOS/Helpers/PropertyBinder.cs
+++ b/Sources/Stylophone.iOS/Helpers/PropertyBinder.cs
@@ -13,8 +13,9 @@ namespace Stylophone.iOS.Helpers
public class PropertyBinder: IDisposable
where TObservable : ObservableObject
{
- private readonly Dictionary> _bindings = new Dictionary>();
- private readonly Dictionary _observers = new Dictionary();
+ private readonly Dictionary> _bindings = new();
+ private readonly Dictionary _observers = new();
+ private readonly Dictionary _buttonBindings = new();
private TObservable _observableObject;
public PropertyBinder(TObservable viewModel)
@@ -31,13 +32,22 @@ public void Dispose()
// Dispose our observers
foreach (IDisposable observer in _observers.Values)
observer.Dispose();
+
+ // Unregister our button bindings
+ foreach (var kvp in _buttonBindings)
+ kvp.Key.PrimaryActionTriggered -= kvp.Value;
}
// Shorthand method to attach a command to a UIButton.
public void BindButton(UIButton button, string buttonText, ICommand command, object parameter = null)
{
button.SetTitle(buttonText, UIControlState.Normal);
- button.PrimaryActionTriggered += (s, e) => command.Execute(parameter);
+
+ // Record button/eventhandler association so we can unregister them when the binder is disposed
+ var evtHandler = new EventHandler((s, e) => command.Execute(parameter));
+ button.PrimaryActionTriggered += evtHandler;
+
+ _buttonBindings.Add(button, evtHandler);
}
public UIAction GetCommandAction(string actionText, string systemImage, ICommand command, object parameter = null)
From 92bdeccab798b45495d18a1976a796d1c39bce73 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Thu, 14 Sep 2023 22:20:03 +0200
Subject: [PATCH 28/56] hook up basic tap to play/addqueue in all tableviews
Disable multiselect for now
---
.../Stylophone.iOS/Helpers/TrackTableViewDataSource.cs | 6 +++++-
.../ViewControllers/AlbumDetailViewController.cs | 8 ++++++--
.../ViewControllers/PlaylistViewController.cs | 6 +++++-
.../ViewControllers/QueueViewController.cs | 9 +++++++--
.../ViewControllers/SearchResultsViewController.cs | 6 +++++-
5 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs b/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs
index 4e631cc..60d7170 100644
--- a/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs
+++ b/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs
@@ -21,6 +21,7 @@ public class TrackTableViewDataSource : UITableViewDelegate, IUITableViewDataSou
private Func _menuFactory;
private Func _swipeFactory;
private Action _scrollHandler;
+ private Action _tapHandler;
private ObservableCollection _sourceCollection;
public TrackTableViewDataSource(IntPtr handle) : base(handle)
@@ -38,13 +39,14 @@ public TrackTableViewDataSource(IntPtr handle) : base(handle)
/// Optional scrollHandler
public TrackTableViewDataSource(UITableView tableView, ObservableCollection source,
Func contextMenuFactory, Func swipeActionFactory,
- bool canSelectRows = false, Action scrollHandler = null)
+ bool canSelectRows = false, Action scrollHandler = null, Action tapHandler = null)
{
_tableView = tableView;
_sourceCollection = source;
_menuFactory = contextMenuFactory;
_swipeFactory = swipeActionFactory;
_scrollHandler = scrollHandler;
+ _tapHandler = tapHandler;
_sourceCollection.CollectionChanged += (s,e) => UIApplication.SharedApplication.InvokeOnMainThread(
() => UpdateUITableView(s,e));
@@ -128,6 +130,8 @@ public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
if (tableView.AllowsMultipleSelection)
tableView.CellAt(indexPath).Accessory = UITableViewCellAccessory.Checkmark;
+ else
+ _tapHandler?.Invoke(indexPath);
}
public override void RowDeselected(UITableView tableView, NSIndexPath indexPath)
diff --git a/Sources/Stylophone.iOS/ViewControllers/AlbumDetailViewController.cs b/Sources/Stylophone.iOS/ViewControllers/AlbumDetailViewController.cs
index 8eeff0b..1c49a15 100644
--- a/Sources/Stylophone.iOS/ViewControllers/AlbumDetailViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/AlbumDetailViewController.cs
@@ -34,7 +34,8 @@ public override void AwakeFromNib()
TraitCollectionDidChange(null);
NavigationItem.LargeTitleDisplayMode = UINavigationItemLargeTitleDisplayMode.Never;
- var trackDataSource = new TrackTableViewDataSource(TableView, ViewModel.Source, GetRowContextMenu, GetRowSwipeActions, true, OnScroll);
+ var trackDataSource = new TrackTableViewDataSource(TableView, ViewModel.Source,
+ GetRowContextMenu, GetRowSwipeActions, false, OnScroll, OnTap);
TableView.DataSource = trackDataSource;
TableView.Delegate = trackDataSource;
TableView.SelfSizingInvalidation = UITableViewSelfSizingInvalidation.EnabledIncludingConstraints;
@@ -44,7 +45,10 @@ public override void AwakeFromNib()
Binder.Bind(AlbumTrackInfo, "text", nameof(ViewModel.PlaylistInfo));
}
- private void OnScroll(UIScrollView scrollView)
+ private void OnTap(NSIndexPath indexPath) =>
+ ViewModel.AddToQueueCommand.Execute(new List
+
-
@@ -318,6 +318,7 @@
+
From 202423070239d49fccdb454ec608157fcbb97faf Mon Sep 17 00:00:00 2001
From: Difegue
Date: Sat, 16 Sep 2023 01:29:02 +0200
Subject: [PATCH 36/56] Bump versions to 2.6
---
Sources/Stylophone.iOS/Info.plist | 4 ++--
Sources/Stylophone/Package.appxmanifest | 2 +-
Sources/Stylophone/Package.tt | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Sources/Stylophone.iOS/Info.plist b/Sources/Stylophone.iOS/Info.plist
index a804213..8140f19 100644
--- a/Sources/Stylophone.iOS/Info.plist
+++ b/Sources/Stylophone.iOS/Info.plist
@@ -16,9 +16,9 @@
zh
CFBundleShortVersionString
- 2.5.4
+ 2.6.0
CFBundleVersion
- 2.5.4
+ 2.6.0
LSRequiresIPhoneOS
MinimumOSVersion
diff --git a/Sources/Stylophone/Package.appxmanifest b/Sources/Stylophone/Package.appxmanifest
index a5a1ff2..16a5808 100644
--- a/Sources/Stylophone/Package.appxmanifest
+++ b/Sources/Stylophone/Package.appxmanifest
@@ -12,7 +12,7 @@
+ Version="2.6.0.0" />
diff --git a/Sources/Stylophone/Package.tt b/Sources/Stylophone/Package.tt
index 8060ae6..9dcdfd2 100644
--- a/Sources/Stylophone/Package.tt
+++ b/Sources/Stylophone/Package.tt
@@ -2,7 +2,7 @@
<#@ output extension=".appxmanifest" #>
<#@ parameter type="System.String" name="BuildConfiguration" #>
<#
- string version = "2.5.6.0";
+ string version = "2.6.0.0";
// Get configuration name at Build time
string configName = Host.ResolveParameterValue("-", "-", "BuildConfiguration");
From c5099cdf733580ea8ad13b7531fe4286cec45c32 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Sun, 17 Sep 2023 00:34:34 +0200
Subject: [PATCH 37/56] Use new playlistdelete range feature
---
.../ViewModels/PlaylistViewModel.cs | 23 +++++++------------
1 file changed, 8 insertions(+), 15 deletions(-)
diff --git a/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs b/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
index 0b60563..b11edfc 100644
--- a/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
@@ -175,23 +175,16 @@ private async void RemoveTrackFromPlaylist(object list)
{
// Cast the received __ComObject
var selectedTracks = (IList)list;
-
- if (selectedTracks?.Count > 0)
+ var trackCount = selectedTracks?.Count;
+ if (trackCount > 0)
{
- var commandList = new CommandList();
-
- // We can't batch PlaylistDeleteCommands cleanly, since they're index-based and logically, said indexes will shift as we remove stuff from the playlist.
- // To simulate this behavior, we copy our Source list and incrementally remove the affected tracks from it to get the valid indexes as we move down the commandList.
- IList copy = Source.ToList();
-
- foreach (var f in selectedTracks)
- {
- var trackVM = f as TrackViewModel;
- commandList.Add(new PlaylistDeleteCommand(Name, copy.IndexOf(trackVM)));
- copy.Remove(trackVM);
- }
+ var command = new PlaylistDeleteCommand(Name, Source.IndexOf(selectedTracks.First() as TrackViewModel));
+
+ // Use new ranged variant if necessary
+ if (trackCount > 1)
+ command = new PlaylistDeleteCommand(Name, Source.IndexOf(selectedTracks.First() as TrackViewModel), Source.IndexOf(selectedTracks.Last() as TrackViewModel));
- var r = await _mpdService.SafelySendCommandAsync(commandList);
+ var r = await _mpdService.SafelySendCommandAsync(command);
if (r != null) // Reload playlist
await LoadDataAsync(Name);
}
From b01cb98e64bed3efaf3c3309871718f9f3e74147 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Sun, 17 Sep 2023 01:38:13 +0200
Subject: [PATCH 38/56] (#60) Use albumartist if available
---
Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs b/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs
index b3115af..e584576 100644
--- a/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs
@@ -208,7 +208,8 @@ public async Task LoadAlbumDataAsync(MpcConnection c)
if (Files.Count == 0)
Files.AddRange(findReq.Response.Content);
- Artist = Files.Select(f => f.Artist).Distinct().Where(f => f != "").Aggregate((f1, f2) => $"{f1}, {f2}");
+ Artist = Files.Any(f => f.HasAlbumArtist) ? Files.First(f => f.HasAlbumArtist).AlbumArtist :
+ Files.Select(f => f.Artist).Distinct().Where(f => f != "").Aggregate((f1, f2) => $"{f1}, {f2}");
// If we've already generated album art, don't use the queue and directly grab it
if (await _albumArtService.IsAlbumArtCachedAsync(Files[0]))
From e29fe71b1939bb9a9708faf2f191ba4c9bc77e42 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Sun, 17 Sep 2023 02:09:36 +0200
Subject: [PATCH 39/56] MpcNET update
---
Sources/Stylophone.Common/Stylophone.Common.csproj | 2 +-
Sources/Stylophone.iOS/Stylophone.iOS.csproj | 2 +-
Sources/Stylophone/Stylophone.csproj | 4 +---
3 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/Sources/Stylophone.Common/Stylophone.Common.csproj b/Sources/Stylophone.Common/Stylophone.Common.csproj
index 6c1e1ee..082c9c6 100644
--- a/Sources/Stylophone.Common/Stylophone.Common.csproj
+++ b/Sources/Stylophone.Common/Stylophone.Common.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/Sources/Stylophone.iOS/Stylophone.iOS.csproj b/Sources/Stylophone.iOS/Stylophone.iOS.csproj
index ada7666..e566ac5 100644
--- a/Sources/Stylophone.iOS/Stylophone.iOS.csproj
+++ b/Sources/Stylophone.iOS/Stylophone.iOS.csproj
@@ -66,7 +66,7 @@
-
+
diff --git a/Sources/Stylophone/Stylophone.csproj b/Sources/Stylophone/Stylophone.csproj
index f2ddc8a..50b8b46 100644
--- a/Sources/Stylophone/Stylophone.csproj
+++ b/Sources/Stylophone/Stylophone.csproj
@@ -162,9 +162,7 @@
-
- 1.4.0
-
+
From fc2a1deab1b86707d8f4163af2096e045da14cc1 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Mon, 18 Sep 2023 00:59:54 +0200
Subject: [PATCH 40/56] Bump to iOS16 minreq
---
Sources/Stylophone.iOS/Info.plist | 2 +-
Sources/Stylophone.iOS/Stylophone.iOS.csproj | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Sources/Stylophone.iOS/Info.plist b/Sources/Stylophone.iOS/Info.plist
index 8140f19..eeebfbe 100644
--- a/Sources/Stylophone.iOS/Info.plist
+++ b/Sources/Stylophone.iOS/Info.plist
@@ -22,7 +22,7 @@
LSRequiresIPhoneOS
MinimumOSVersion
- 15.0
+ 16.0
UIBackgroundModes
audio
diff --git a/Sources/Stylophone.iOS/Stylophone.iOS.csproj b/Sources/Stylophone.iOS/Stylophone.iOS.csproj
index e566ac5..3889d5c 100644
--- a/Sources/Stylophone.iOS/Stylophone.iOS.csproj
+++ b/Sources/Stylophone.iOS/Stylophone.iOS.csproj
@@ -4,7 +4,7 @@
Exe
enable
true
- 15.0
+ 16.0
false
From 8791276a179169d94f77a42b4c028b123b666e9d Mon Sep 17 00:00:00 2001
From: Difegue
Date: Mon, 18 Sep 2023 01:02:20 +0200
Subject: [PATCH 41/56] Rework plchanges handling (again)
And implement reorder for iOS
---
.../ViewModels/QueueViewModel.cs | 58 +++++++++++--------
.../Helpers/TrackTableViewDataSource.cs | 34 ++++++++---
.../ViewControllers/QueueViewController.cs | 2 +-
Sources/Stylophone.iOS/Views/Queue.storyboard | 2 +-
4 files changed, 62 insertions(+), 34 deletions(-)
diff --git a/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs b/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
index 6aad672..bd1a7d3 100644
--- a/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
@@ -162,12 +162,21 @@ private async Task ClearQueue()
///
private async void Source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
+ // iOS uses move
+ if (e.Action == NotifyCollectionChangedAction.Move)
+ {
+ _oldId = e.OldItems.Count > 0 ? (e.OldItems[0] as TrackViewModel).File.Id : -1;
+ await _mpdService.SafelySendCommandAsync(new MoveIdCommand(_oldId, e.NewStartingIndex));
+ return;
+ }
+
if (e.Action == NotifyCollectionChangedAction.Add && _previousAction == NotifyCollectionChangedAction.Remove)
{
// One Remove->Add Pair means one MoveIdCommand
- await _mpdService.SafelySendCommandAsync(new MoveIdCommand(_oldId, e.NewStartingIndex));
_previousAction = NotifyCollectionChangedAction.Move;
+ await _mpdService.SafelySendCommandAsync(new MoveIdCommand(_oldId, e.NewStartingIndex));
}
+
if (e.Action == NotifyCollectionChangedAction.Remove)
{
_previousAction = e.Action;
@@ -199,35 +208,36 @@ private async void MPDConnectionService_QueueChanged(object sender, EventArgs e)
{
Source.CollectionChanged -= Source_CollectionChanged;
- // If the queue was cleared, PlaylistLength is 0.
- if (status.PlaylistLength == 0)
+ // PlChanges gives the full list of files affected by the change.
+ foreach (var f in response)
{
- await _dispatcherService.ExecuteOnUIThreadAsync(() => Source.Clear());
- }
- else
- {
- // PlChanges gives the full list of files starting from the change,
- // so we delete all existing tracks from the source after that change, and swap the new ones in.
- // If the response is empty, that means the last file in the source was removed.
- var initialPosition = response.Count() == 0 ? Source.Count - 1 : response.First().Position;
-
- // Get all the tracks between initialPosition and the end of the Source
- var tracksToRemove = Source.Skip(initialPosition).ToList();
- await _dispatcherService.ExecuteOnUIThreadAsync(() => {
- Source.RemoveRange(tracksToRemove);
- });
-
- var toAdd = new List();
- foreach (var item in response)
+ var trackVm = Source.Where(tvm => tvm.File.Id == f.Id).FirstOrDefault();
+
+ // We might already be up to date
+ if (Source.IndexOf(trackVm) == f.Position)
+ continue;
+
+ // Nw track
+ if (trackVm == default)
{
- var trackVm = _trackVmFactory.GetTrackViewModel(item);
- toAdd.Add(trackVm);
+ trackVm = _trackVmFactory.GetTrackViewModel(f);
+ }
+ else
+ {
+ Source.Remove(trackVm);
}
- if (toAdd.Count > 0)
- await _dispatcherService.ExecuteOnUIThreadAsync(() => Source.AddRange(toAdd));
+ Source.Insert(f.Position, trackVm);
}
+ // To detect songs that were deleted at the end of the playlist, use playlistlength returned by status command.
+ // (If the queue was cleared, PlaylistLength is 0.)
+ var tracksToRemove = Source.Skip(status.PlaylistLength).ToList();
+
+ await _dispatcherService.ExecuteOnUIThreadAsync(() => {
+ Source.RemoveRange(tracksToRemove);
+ });
+
Source.CollectionChanged += Source_CollectionChanged;
// Update internal playlist version
diff --git a/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs b/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs
index 86e11f7..3bd0759 100644
--- a/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs
+++ b/Sources/Stylophone.iOS/Helpers/TrackTableViewDataSource.cs
@@ -23,6 +23,7 @@ public class TrackTableViewDataSource : UITableViewDelegate, IUITableViewDataSou
private Action _scrollHandler;
private Action _primaryAction;
private ObservableCollection _sourceCollection;
+ private bool _canReorder;
public TrackTableViewDataSource(IntPtr handle) : base(handle)
{
@@ -35,23 +36,26 @@ public TrackTableViewDataSource(IntPtr handle) : base(handle)
/// The source TrackViewModels
/// A factory for row context menus
/// A factory for row swipe actions
- /// Whether you can select multiple rows
+ /// Whether you can reorder items
/// Optional scrollHandler
/// Optional primary action
public TrackTableViewDataSource(UITableView tableView, ObservableCollection source,
Func contextMenuFactory, Func swipeActionFactory,
- bool canSelectRows = false, Action scrollHandler = null, Action primaryAction = null)
+ bool canReorder = false, Action scrollHandler = null, Action primaryAction = null)
{
_tableView = tableView;
_sourceCollection = source;
_menuFactory = contextMenuFactory;
_swipeFactory = swipeActionFactory;
+ _canReorder = canReorder;
_scrollHandler = scrollHandler;
_primaryAction = primaryAction;
_sourceCollection.CollectionChanged += (s,e) => UIApplication.SharedApplication.InvokeOnMainThread(
() => UpdateUITableView(s,e));
- _tableView.AllowsMultipleSelection = canSelectRows;
+
+ //_tableView.AllowsMultipleSelectionDuringEditing = _canReorder;
+ //_tableView.AllowsMultipleSelection = canSelectRows;
}
private void UpdateUITableView(object sender, NotifyCollectionChangedEventArgs e)
@@ -91,6 +95,9 @@ private void UpdateUITableView(object sender, NotifyCollectionChangedEventArgs e
#region DataSource
+ [Export("tableView:canMoveRowAtIndexPath:")]
+ public bool CanMoveRow(UITableView tableView, NSIndexPath indexPath) => _canReorder;
+
public nint RowsInSection(UITableView tableView, nint section)
{
return _sourceCollection.Count;
@@ -118,10 +125,20 @@ public UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
return cell;
}
+ [Export("tableView:moveRowAtIndexPath:toIndexPath:")]
+ public void MoveRow(UITableView tableView, NSIndexPath sourceIndexPath, NSIndexPath destinationIndexPath)
+ {
+ _sourceCollection.Move(sourceIndexPath.Row, destinationIndexPath.Row);
+ }
+
#endregion
#region Delegate
+ // If multiselect isn't enabled, this will show a delete icon on the left side of the cells
+ public override UITableViewCellEditingStyle EditingStyleForRow(UITableView tableView, NSIndexPath indexPath)
+ => UITableViewCellEditingStyle.Delete;
+
public override void Scrolled(UIScrollView scrollView)
{
_scrollHandler?.Invoke(scrollView);
@@ -129,19 +146,20 @@ public override void Scrolled(UIScrollView scrollView)
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
- if (tableView.AllowsMultipleSelection)
- tableView.CellAt(indexPath).Accessory = UITableViewCellAccessory.Checkmark;
+ //if (tableView.Editing)
+ // tableView.CellAt(indexPath).Accessory = UITableViewCellAccessory.Checkmark;
}
public override void RowDeselected(UITableView tableView, NSIndexPath indexPath)
{
- if (tableView.AllowsMultipleSelection)
- tableView.CellAt(indexPath).Accessory = UITableViewCellAccessory.None;
+ //if (tableView.Editing)
+ // tableView.CellAt(indexPath).Accessory = UITableViewCellAccessory.None;
}
public override void PerformPrimaryAction(UITableView tableView, NSIndexPath rowIndexPath)
{
- _primaryAction?.Invoke(rowIndexPath);
+ if (!tableView.Editing)
+ _primaryAction?.Invoke(rowIndexPath);
}
public override UIContextMenuConfiguration GetContextMenuConfiguration(UITableView tableView, NSIndexPath indexPath, CoreGraphics.CGPoint point)
diff --git a/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs b/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
index a983936..467e362 100644
--- a/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
@@ -51,7 +51,7 @@ public override void ViewDidLoad()
Binder.Bind(EmptyView, "hidden", nameof(ViewModel.IsSourceEmpty),
valueTransformer: negateBoolTransformer);
- NavigationItem.RightBarButtonItem = CreateSettingsButton();
+ NavigationItem.RightBarButtonItems = new UIBarButtonItem[] { CreateSettingsButton(), EditButtonItem };
var trackDataSource = new TrackTableViewDataSource(TableView, ViewModel.Source,
GetRowContextMenu, GetRowSwipeActions, true, primaryAction:OnTap);
diff --git a/Sources/Stylophone.iOS/Views/Queue.storyboard b/Sources/Stylophone.iOS/Views/Queue.storyboard
index 18edfbf..42036a5 100644
--- a/Sources/Stylophone.iOS/Views/Queue.storyboard
+++ b/Sources/Stylophone.iOS/Views/Queue.storyboard
@@ -55,7 +55,7 @@
-
+
From 9fba011c8c43829736311375d3730751f65dc00a Mon Sep 17 00:00:00 2001
From: Difegue
Date: Mon, 18 Sep 2023 01:53:40 +0200
Subject: [PATCH 42/56] Add edit mode to playlists on iOS too
---
Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs | 7 +++++++
.../ViewControllers/PlaylistViewController.cs | 6 +++---
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs b/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
index b11edfc..9635b28 100644
--- a/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
@@ -272,6 +272,13 @@ await _dispatcherService.ExecuteOnUIThreadAsync(() =>
private async void Source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
+ // iOS uses move
+ if (e.Action == NotifyCollectionChangedAction.Move)
+ {
+ await _mpdService.SafelySendCommandAsync(new PlaylistMoveCommand(Name, e.OldStartingIndex, e.NewStartingIndex));
+ return;
+ }
+
if (e.Action == NotifyCollectionChangedAction.Add && _previousAction == NotifyCollectionChangedAction.Remove)
{
// User reordered tracks, send matching command
diff --git a/Sources/Stylophone.iOS/ViewControllers/PlaylistViewController.cs b/Sources/Stylophone.iOS/ViewControllers/PlaylistViewController.cs
index ccd9110..8b7effb 100644
--- a/Sources/Stylophone.iOS/ViewControllers/PlaylistViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/PlaylistViewController.cs
@@ -60,7 +60,7 @@ public override void AwakeFromNib()
_settingsBtn = CreateSettingsButton();
var trackDataSource = new TrackTableViewDataSource(TableView, ViewModel.Source,
- GetRowContextMenu, GetRowSwipeActions, false, OnScroll, OnTap);
+ GetRowContextMenu, GetRowSwipeActions, true, OnScroll, OnTap);
TableView.DataSource = trackDataSource;
TableView.Delegate = trackDataSource;
@@ -112,12 +112,12 @@ private void OnScroll(UIScrollView scrollView)
if (scrollView.ContentOffset.Y > 192)
{
Title = ViewModel?.Name;
- NavigationItem.RightBarButtonItem = _settingsBtn;
+ NavigationItem.RightBarButtonItems = new UIBarButtonItem[] { _settingsBtn, EditButtonItem };
}
else
{
Title = "";
- NavigationItem.RightBarButtonItem = null;
+ NavigationItem.RightBarButtonItems = new UIBarButtonItem[] { EditButtonItem };
}
}
From faba364190accd63aba0f7aec2f84db99af6c666 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Sun, 17 Sep 2023 22:12:31 +0200
Subject: [PATCH 43/56] Clean up code a bit
---
.../ViewModels/AlbumDetailViewModel.cs | 4 ++--
.../ViewModels/Items/AlbumViewModel.cs | 6 +++---
.../ViewModels/Items/FilePathViewModel.cs | 21 ++++++++++---------
.../ViewModels/Items/TrackViewModel.cs | 8 +++----
.../ViewModels/PlaylistViewModel.cs | 14 ++++++-------
.../ViewModels/SearchResultsViewModel.cs | 4 ++--
6 files changed, 29 insertions(+), 28 deletions(-)
diff --git a/Sources/Stylophone.Common/ViewModels/AlbumDetailViewModel.cs b/Sources/Stylophone.Common/ViewModels/AlbumDetailViewModel.cs
index f67add3..d852b8a 100644
--- a/Sources/Stylophone.Common/ViewModels/AlbumDetailViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/AlbumDetailViewModel.cs
@@ -46,7 +46,7 @@ public AlbumDetailViewModel(IDialogService dialogService, INotificationService n
public bool IsSourceEmpty => Source.Count == 0;
[RelayCommand]
- private async void AddToQueue(object list)
+ private async Task AddToQueue(object list)
{
var selectedTracks = (IList)list;
@@ -67,7 +67,7 @@ private async void AddToQueue(object list)
}
[RelayCommand]
- private async void AddToPlaylist(object list)
+ private async Task AddToPlaylist(object list)
{
var playlistName = await _dialogService.ShowAddToPlaylistDialog();
if (playlistName == null) return;
diff --git a/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs b/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs
index e584576..0a85e31 100644
--- a/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs
@@ -113,7 +113,7 @@ internal void SetAlbumArt(AlbumArt art)
}
[RelayCommand]
- private async void AddToPlaylist()
+ private async Task AddToPlaylist()
{
var playlistName = await _dialogService.ShowAddToPlaylistDialog();
if (playlistName == null || Files.Count == 0) return;
@@ -132,7 +132,7 @@ private async void AddToPlaylist()
}
[RelayCommand]
- private async void AddAlbum()
+ private async Task AddAlbum()
{
var commandList = new CommandList();
@@ -152,7 +152,7 @@ private async void AddAlbum()
}
[RelayCommand]
- private async void PlayAlbum()
+ private async Task PlayAlbum()
{
if (Files.Count == 0)
{
diff --git a/Sources/Stylophone.Common/ViewModels/Items/FilePathViewModel.cs b/Sources/Stylophone.Common/ViewModels/Items/FilePathViewModel.cs
index b323e15..b6a3cb3 100644
--- a/Sources/Stylophone.Common/ViewModels/Items/FilePathViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/Items/FilePathViewModel.cs
@@ -66,10 +66,11 @@ internal FilePathViewModel(FilePathViewModelFactory factory, IMpdFilePath file,
if (file is MpdDirectory)
{
IsDirectory = true;
- _children = new RangedObservableCollection();
-
- // Add a bogus child that'll be replaced when the list is loaded
- _children.Add(new FilePathViewModel(Resources.FoldersLoadingTreeItem, this, _dispatcherService));
+ _children = new RangedObservableCollection
+ {
+ // Add a bogus child that'll be replaced when the list is loaded
+ new FilePathViewModel(Resources.FoldersLoadingTreeItem, this, _dispatcherService)
+ };
}
}
@@ -99,7 +100,7 @@ public FilePathViewModel(string name, FilePathViewModel parent, IDispatcherServi
private bool _isLoadingChildren;
public async Task LoadChildrenAsync()
{
- if (IsLoaded || _isLoadingChildren || IsDirectory == false || _children == null || Path == null) return;
+ if (IsLoaded || _isLoadingChildren || IsDirectory == false || Children == null || Path == null) return;
_isLoadingChildren = true;
try
@@ -118,8 +119,8 @@ public async Task LoadChildrenAsync()
await _dispatcherService.ExecuteOnUIThreadAsync(() =>
{
- _children.AddRange(newChildren);
- _children.RemoveAt(0); // Remove the placeholder after adding the new items, otherwise the treeitem can close back up
+ Children.AddRange(newChildren);
+ Children.RemoveAt(0); // Remove the placeholder after adding the new items, otherwise the treeitem can close back up
IsLoaded = true;
});
}
@@ -131,7 +132,7 @@ await _dispatcherService.ExecuteOnUIThreadAsync(() =>
[RelayCommand]
- private async void Play()
+ private async Task Play()
{
// Clear queue, add path and play
var commandList = new CommandList(new IMpcCommand[] { new ClearCommand(), new AddCommand(Path), new PlayCommand(0) });
@@ -143,7 +144,7 @@ private async void Play()
}
[RelayCommand]
- private async void AddToQueue()
+ private async Task AddToQueue()
{
// AddCommand adds either the full directory or the song, depending on the path given.
var response = await _mpdService.SafelySendCommandAsync(new AddCommand(Path));
@@ -153,7 +154,7 @@ private async void AddToQueue()
}
[RelayCommand]
- private async void AddToPlaylist()
+ private async Task AddToPlaylist()
{
var playlistName = await _dialogService.ShowAddToPlaylistDialog();
if (playlistName == null) return;
diff --git a/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs b/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs
index 76371ee..aff7145 100644
--- a/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs
@@ -90,13 +90,13 @@ internal TrackViewModel(TrackViewModelFactory factory, IMpdFile file): base(fact
private bool _isLight;
[RelayCommand]
- private async void PlayTrack(IMpdFile file) => await _mpdService.SafelySendCommandAsync(new PlayIdCommand(file.Id));
+ private async Task PlayTrack(IMpdFile file) => await _mpdService.SafelySendCommandAsync(new PlayIdCommand(file.Id));
[RelayCommand]
- private async void RemoveFromQueue(IMpdFile file) => await _mpdService.SafelySendCommandAsync(new DeleteIdCommand(file.Id));
+ private async Task RemoveFromQueue(IMpdFile file) => await _mpdService.SafelySendCommandAsync(new DeleteIdCommand(file.Id));
[RelayCommand]
- private async void AddToQueue(IMpdFile file)
+ private async Task AddToQueue(IMpdFile file)
{
var response = await _mpdService.SafelySendCommandAsync(new AddIdCommand(file.Path));
@@ -105,7 +105,7 @@ private async void AddToQueue(IMpdFile file)
}
[RelayCommand]
- private async void AddToPlaylist(IMpdFile file)
+ private async Task AddToPlaylist(IMpdFile file)
{
var playlistName = await _dialogService.ShowAddToPlaylistDialog();
if (playlistName == null) return;
diff --git a/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs b/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
index 9635b28..9f4be25 100644
--- a/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/PlaylistViewModel.cs
@@ -95,7 +95,7 @@ private bool IsSingleTrackSelected(object list)
}
[RelayCommand]
- private async void RemovePlaylist()
+ private async Task RemovePlaylist()
{
var result = await _dialogService.ShowConfirmDialogAsync(Resources.DeletePlaylistContentDialog, "", Resources.OKButtonText, Resources.CancelButtonText);
@@ -112,7 +112,7 @@ private async void RemovePlaylist()
}
[RelayCommand]
- private async void LoadPlaylist()
+ private async Task LoadPlaylist()
{
var res = await _mpdService.SafelySendCommandAsync(new LoadCommand(Name));
@@ -121,7 +121,7 @@ private async void LoadPlaylist()
}
[RelayCommand]
- private async void PlayPlaylist()
+ private async Task PlayPlaylist()
{
// Clear queue, add playlist and play
var commandList = new CommandList(new IMpcCommand[] { new ClearCommand() , new LoadCommand(Name), new PlayCommand(0) });
@@ -135,7 +135,7 @@ private async void PlayPlaylist()
[RelayCommand]
- private async void AddToQueue(object list)
+ private async Task AddToQueue(object list)
{
// Cast the received __ComObject
var selectedTracks = (IList)list;
@@ -171,7 +171,7 @@ private void ViewAlbum(object list)
[RelayCommand]
- private async void RemoveTrackFromPlaylist(object list)
+ private async Task RemoveTrackFromPlaylist(object list)
{
// Cast the received __ComObject
var selectedTracks = (IList)list;
@@ -230,7 +230,7 @@ public async Task LoadDataAsync(string playlistName)
await Task.Run(async () =>
{
// Get album art for three albums to display in the playlist view
- Random r = new Random();
+ Random r = new();
var distinctAlbums = Source.GroupBy(tr => tr.File.Album).Select(tr => tr.First()).OrderBy((item) => r.Next()).ToList();
if (distinctAlbums.Count > 1)
@@ -240,7 +240,7 @@ await Task.Run(async () =>
DominantColor = (art?.DominantColor?.Color).GetValueOrDefault();
- if (DominantColor == default(SKColor))
+ if (DominantColor == default)
{
await _dispatcherService.ExecuteOnUIThreadAsync(() =>
{
diff --git a/Sources/Stylophone.Common/ViewModels/SearchResultsViewModel.cs b/Sources/Stylophone.Common/ViewModels/SearchResultsViewModel.cs
index 6b38247..e5768e8 100644
--- a/Sources/Stylophone.Common/ViewModels/SearchResultsViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/SearchResultsViewModel.cs
@@ -105,7 +105,7 @@ private bool IsSingleTrackSelected(object list)
}
[RelayCommand]
- private async void AddToQueue(object list)
+ private async Task AddToQueue(object list)
{
var selectedTracks = (IList)list;
@@ -126,7 +126,7 @@ private async void AddToQueue(object list)
}
[RelayCommand]
- private async void AddToPlaylist(object list)
+ private async Task AddToPlaylist(object list)
{
var playlistName = await _dialogService.ShowAddToPlaylistDialog();
if (playlistName == null) return;
From b896537baa1b8eba5b2e747941b79fd0ac162682 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Mon, 18 Sep 2023 01:54:19 +0200
Subject: [PATCH 44/56] Add missing release mode usings
---
Sources/Stylophone.Common/Services/MPDConnectionService.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Sources/Stylophone.Common/Services/MPDConnectionService.cs b/Sources/Stylophone.Common/Services/MPDConnectionService.cs
index 2e8d4bd..1f6f6db 100644
--- a/Sources/Stylophone.Common/Services/MPDConnectionService.cs
+++ b/Sources/Stylophone.Common/Services/MPDConnectionService.cs
@@ -12,6 +12,9 @@
using MpcNET.Commands.Reflection;
using Stylophone.Localization.Strings;
using Stylophone.Common.Helpers;
+using CommunityToolkit.Mvvm.DependencyInjection;
+using Microsoft.AppCenter.Analytics;
+using Stylophone.Common.ViewModels;
namespace Stylophone.Common.Services
{
From 417953717b0087b3493c1a68e0f2e61e6c2d8c2b Mon Sep 17 00:00:00 2001
From: Difegue
Date: Mon, 18 Sep 2023 02:17:05 +0200
Subject: [PATCH 45/56] misc fixes
---
.../Stylophone.iOS/ViewControllers/PlaylistViewController.cs | 2 ++
.../Stylophone.iOS/ViewControllers/QueueViewController.cs | 5 ++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/Sources/Stylophone.iOS/ViewControllers/PlaylistViewController.cs b/Sources/Stylophone.iOS/ViewControllers/PlaylistViewController.cs
index 8b7effb..3ddbfde 100644
--- a/Sources/Stylophone.iOS/ViewControllers/PlaylistViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/PlaylistViewController.cs
@@ -96,6 +96,8 @@ public override void AwakeFromNib()
ArtContainer.Layer.ShadowOpacity = 0.5F;
ArtContainer.Layer.ShadowOffset = new CGSize(0, 0);
ArtContainer.Layer.ShadowRadius = 4;
+
+ NavigationItem.RightBarButtonItems = new UIBarButtonItem[] { EditButtonItem };
}
public override void ViewWillDisappear(bool animated)
diff --git a/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs b/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
index 467e362..a7f6943 100644
--- a/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
@@ -88,11 +88,14 @@ private void ScrollToPlayingSong(object sender = null, SongChangedEventArgs e =
if (tableViewRows >= indexPath.Row)
TableView.ScrollToRow(indexPath, UITableViewScrollPosition.Middle, true);
- } catch (Exception e)
+ }
+ catch (Exception e)
{
System.Diagnostics.Debug.WriteLine($"Error while scrolling to row: {e}");
}
});
+ else // inconsistency, reload source wholesale
+ ViewModel.LoadInitialDataAsync();
}
private UIMenu GetRowContextMenu(NSIndexPath indexPath)
From 1d776a3ab87b2e691b53e2beff16610cfd9a8527 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 19 Sep 2023 02:20:39 +0200
Subject: [PATCH 46/56] Tweak nowplaying again for better margins and multiline
---
.../ViewControllers/PlaybackViewController.cs | 12 +-
.../Views/NowPlaying.storyboard | 149 +++++++++++-------
2 files changed, 91 insertions(+), 70 deletions(-)
diff --git a/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs b/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
index 08f1461..52dd012 100644
--- a/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
@@ -96,23 +96,17 @@ public override void ViewDidLayoutSubviews()
if (!ViewModel.IsFullScreen) return;
- // Don't multi-line for small phones in vertical orientation
+ // Different multi-line behavior depending on size classes
if (TraitCollection.HorizontalSizeClass == UIUserInterfaceSizeClass.Compact &&
TraitCollection.VerticalSizeClass == UIUserInterfaceSizeClass.Regular &&
UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone)
{
TrackTitle.Lines = 2;
- AlbumName.Lines = 1;
-
}
else
{
- TrackTitle.Lines = 3;
-
- if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone)
- AlbumName.Lines = 1;
- else
- AlbumName.Lines = 2;
+ if (UIDevice.CurrentDevice.UserInterfaceIdiom != UIUserInterfaceIdiom.Phone)
+ TrackTitle.Lines = 3;
}
// On compact widths, change the application tintcolor, as that's what is used instead of the navigation bar's
diff --git a/Sources/Stylophone.iOS/Views/NowPlaying.storyboard b/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
index b49bbd1..db4d000 100644
--- a/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
+++ b/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
@@ -1,7 +1,7 @@
-
-
+
+
@@ -19,52 +19,52 @@
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
@@ -72,7 +72,7 @@
-
+
@@ -81,7 +81,7 @@
-
+
@@ -89,7 +89,7 @@
-
+
@@ -100,7 +100,7 @@
-
+
@@ -111,7 +111,7 @@
-
+
@@ -122,7 +122,7 @@
-
+
@@ -133,7 +133,7 @@
-
+
@@ -144,7 +144,7 @@
-
+
@@ -155,7 +155,7 @@
-
+
@@ -196,11 +196,17 @@
-
+
+
+
+
-
-
+
+
+
+
+
@@ -209,30 +215,43 @@
-
+
+
-
+
-
+
+
+
+
-
+
+
-
-
+
+
+
-
-
-
+
+
+
+
+
+
-
+
+
+
+
+
@@ -244,26 +263,30 @@
-
+
-
+
+
+
-
+
-
-
-
+
+
+
+
+
@@ -275,17 +298,19 @@
+
+
+
-
@@ -377,11 +402,11 @@
-
+
-
+
@@ -394,19 +419,19 @@
-
+
-
+
-
+
@@ -423,7 +448,7 @@
-
+
@@ -440,7 +465,7 @@
-
+
@@ -457,17 +482,17 @@
-
+
-
+
-
+
@@ -482,7 +507,7 @@
-
+
@@ -503,7 +528,7 @@
-
+
@@ -521,7 +546,7 @@
-
+
@@ -550,7 +575,9 @@
-
+
+
+
@@ -559,7 +586,6 @@
-
@@ -569,6 +595,7 @@
+
@@ -599,9 +626,9 @@
-
+
@@ -778,7 +805,7 @@
-
+
From 4af8691ae1e2da0b68e46a3d500f1eca25d98dac Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 19 Sep 2023 02:42:15 +0200
Subject: [PATCH 47/56] janky inapp notification popover
---
.../Services/NotificationService.cs | 68 +++++++++++++++++--
1 file changed, 62 insertions(+), 6 deletions(-)
diff --git a/Sources/Stylophone.iOS/Services/NotificationService.cs b/Sources/Stylophone.iOS/Services/NotificationService.cs
index 7c66e7f..a089a52 100644
--- a/Sources/Stylophone.iOS/Services/NotificationService.cs
+++ b/Sources/Stylophone.iOS/Services/NotificationService.cs
@@ -1,13 +1,13 @@
using System;
using UserNotifications;
using Stylophone.Common.Interfaces;
-using UIKit;
namespace Stylophone.iOS.Services
{
public class NotificationService : NotificationServiceBase
{
private IDispatcherService _dispatcherService;
+ private Timer _notificationTimer;
public NotificationService(IDispatcherService dispatcherService)
{
@@ -16,18 +16,30 @@ public NotificationService(IDispatcherService dispatcherService)
public override void ShowInAppNotification(InAppNotification notification)
{
+ if (notification.NotificationType == NotificationType.Error)
+ {
+ // Let's just use alerts until TipKit is available... This is cheap but w/e
+ var alert = new UIAlertView(notification.NotificationTitle, notification.NotificationText, null, "Ok");
+ alert.Show();
+ return;
+ }
+
+ var rootVc = (UIApplication.SharedApplication.Delegate as AppDelegate).RootViewController;
+
UIApplication.SharedApplication.InvokeOnMainThread(() =>
{
if (UIApplication.SharedApplication.ApplicationState != UIApplicationState.Active)
return;
- // Let's just use alerts until TipKit is available... This is cheap but w/e
- var alert = new UIAlertView(notification.NotificationTitle, notification.NotificationText, null, "Ok");
-
- if (notification.NotificationType == NotificationType.Error)
- alert.Show();
+ var popover = new NotificationPopoverViewController(notification.NotificationTitle, rootVc);
+ rootVc.PresentViewController(popover, true, null);
});
+
+ _notificationTimer?.Dispose();
+ _notificationTimer = new Timer((_) => UIApplication.SharedApplication.InvokeOnMainThread(() =>
+ rootVc.DismissViewController(true, null)),
+ null, 1500, Timeout.Infinite);
}
public override void ShowBasicToastNotification(string title, string description)
@@ -46,4 +58,48 @@ public override void ShowBasicToastNotification(string title, string description
});
}
}
+
+ public class NotificationPopoverViewController : UIViewController, IUIPopoverPresentationControllerDelegate
+ {
+ private string _text;
+
+ public NotificationPopoverViewController(string text, UISplitViewController rootVc) //, CGRect sourceBounds, CGSize contentSize)
+ {
+ _text = text;
+
+ ModalPresentationStyle = UIModalPresentationStyle.Popover;
+
+ PopoverPresentationController.SourceView = rootVc.View;
+ PopoverPresentationController.Delegate = this;
+ PopoverPresentationController.PermittedArrowDirections = UIPopoverArrowDirection.Left;
+ PopoverPresentationController.SourceRect = new CGRect(16, 64, 1, 1);
+ }
+
+ public override void LoadView()
+ {
+ base.LoadView();
+
+ PreferredContentSize = new CGSize(196, 54);
+
+ View = new UILabel
+ {
+ Text = _text,
+ Font = UIFont.PreferredHeadline,
+ TextAlignment = UITextAlignment.Center,
+ AdjustsFontSizeToFitWidth = true,
+ Lines = 2,
+ };
+
+ }
+
+ [Export("adaptivePresentationStyleForPresentationController:traitCollection:")]
+ public UIModalPresentationStyle GetAdaptivePresentationStyle(UIPresentationController controller, UITraitCollection traitCollection)
+ {
+ // Prevent popover from being adaptive fullscreen on phones
+ // (https://pspdfkit.com/blog/2022/presenting-popovers-on-iphone-with-swiftui/)
+ return UIModalPresentationStyle.None;
+ }
+
+ }
+
}
From a00704dc0c0b3bd03ccf5b20f67321b8326ebab9 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 19 Sep 2023 21:06:08 +0200
Subject: [PATCH 48/56] Add some strings for voiceover help
+ add missing narrator hints to windows UI
---
.../ViewModels/QueueViewModel.cs | 9 +-
.../Strings/Resources.Designer.cs | 276 ++++++++++--------
.../Strings/Resources.en-US.resx | 6 +
.../Strings/Resources.fr-FR.resx | 6 +
.../Strings/Resources.pt-PT.resx | 6 +
.../Strings/Resources.resx | 6 +
Sources/Stylophone/Styles/StyloResources.xaml | 1 +
Sources/Stylophone/Stylophone.csproj | 6 +-
.../Views/Playback/NowPlayingBar.xaml | 13 +
9 files changed, 194 insertions(+), 135 deletions(-)
diff --git a/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs b/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
index bd1a7d3..6ec853e 100644
--- a/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/QueueViewModel.cs
@@ -222,12 +222,15 @@ private async void MPDConnectionService_QueueChanged(object sender, EventArgs e)
{
trackVm = _trackVmFactory.GetTrackViewModel(f);
}
- else
+ else await _dispatcherService.ExecuteOnUIThreadAsync(() =>
{
Source.Remove(trackVm);
- }
+ });
- Source.Insert(f.Position, trackVm);
+ await _dispatcherService.ExecuteOnUIThreadAsync(() =>
+ {
+ Source.Insert(f.Position, trackVm);
+ });
}
// To detect songs that were deleted at the end of the playlist, use playlistlength returned by status command.
diff --git a/Sources/Stylophone.Localization/Strings/Resources.Designer.cs b/Sources/Stylophone.Localization/Strings/Resources.Designer.cs
index 589217c..dd3195d 100644
--- a/Sources/Stylophone.Localization/Strings/Resources.Designer.cs
+++ b/Sources/Stylophone.Localization/Strings/Resources.Designer.cs
@@ -1,10 +1,10 @@
//------------------------------------------------------------------------------
//
-// Ce code a été généré par un outil.
-// Version du runtime :4.0.30319.42000
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
//
-// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
-// le code est régénéré.
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
//
//------------------------------------------------------------------------------
@@ -13,12 +13,12 @@ namespace Stylophone.Localization.Strings {
///
- /// Une classe de ressource fortement typée destinée, entre autres, à la consultation des chaînes localisées.
+ /// A strongly-typed resource class, for looking up localized strings, etc.
///
- // Cette classe a été générée automatiquement par la classe StronglyTypedResourceBuilder
- // à l'aide d'un outil, tel que ResGen ou Visual Studio.
- // Pour ajouter ou supprimer un membre, modifiez votre fichier .ResX, puis réexécutez ResGen
- // avec l'option /str ou régénérez votre projet VS.
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
@@ -33,7 +33,7 @@ internal Resources() {
}
///
- /// Retourne l'instance ResourceManager mise en cache utilisée par cette classe.
+ /// Returns the cached ResourceManager instance used by this class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
@@ -47,8 +47,8 @@ internal Resources() {
}
///
- /// Remplace la propriété CurrentUICulture du thread actuel pour toutes
- /// les recherches de ressources à l'aide de cette classe de ressource fortement typée.
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
@@ -61,7 +61,7 @@ internal Resources() {
}
///
- /// Recherche une chaîne localisée semblable à Change Volume.
+ /// Looks up a localized string similar to Change Volume.
///
public static string ActionChangeVolume {
get {
@@ -70,7 +70,7 @@ public static string ActionChangeVolume {
}
///
- /// Recherche une chaîne localisée semblable à Show Mini Player.
+ /// Looks up a localized string similar to Show Mini Player.
///
public static string ActionCompactOverlay {
get {
@@ -79,7 +79,16 @@ public static string ActionCompactOverlay {
}
///
- /// Recherche une chaîne localisée semblable à More Actions.
+ /// Looks up a localized string similar to Open Fullscreen Playback.
+ ///
+ public static string ActionFullscreenPlayback {
+ get {
+ return ResourceManager.GetString("ActionFullscreenPlayback", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to More Actions.
///
public static string ActionMore {
get {
@@ -88,7 +97,7 @@ public static string ActionMore {
}
///
- /// Recherche une chaîne localisée semblable à Play/Pause.
+ /// Looks up a localized string similar to Play/Pause.
///
public static string ActionPlayPause {
get {
@@ -97,7 +106,7 @@ public static string ActionPlayPause {
}
///
- /// Recherche une chaîne localisée semblable à Next Track.
+ /// Looks up a localized string similar to Next Track.
///
public static string ActionSkipNext {
get {
@@ -106,7 +115,7 @@ public static string ActionSkipNext {
}
///
- /// Recherche une chaîne localisée semblable à Previous Track.
+ /// Looks up a localized string similar to Previous Track.
///
public static string ActionSkipPrevious {
get {
@@ -115,7 +124,7 @@ public static string ActionSkipPrevious {
}
///
- /// Recherche une chaîne localisée semblable à Toggle Consume.
+ /// Looks up a localized string similar to Toggle Consume.
///
public static string ActionToggleConsume {
get {
@@ -124,7 +133,7 @@ public static string ActionToggleConsume {
}
///
- /// Recherche une chaîne localisée semblable à Toggle Repeat.
+ /// Looks up a localized string similar to Toggle Repeat.
///
public static string ActionToggleRepeat {
get {
@@ -133,7 +142,7 @@ public static string ActionToggleRepeat {
}
///
- /// Recherche une chaîne localisée semblable à Toggle Shuffle.
+ /// Looks up a localized string similar to Toggle Shuffle.
///
public static string ActionToggleShuffle {
get {
@@ -142,7 +151,7 @@ public static string ActionToggleShuffle {
}
///
- /// Recherche une chaîne localisée semblable à Create New Playlist.
+ /// Looks up a localized string similar to Create New Playlist.
///
public static string AddToPlaylistCreateNewPlaylist {
get {
@@ -151,7 +160,7 @@ public static string AddToPlaylistCreateNewPlaylist {
}
///
- /// Recherche une chaîne localisée semblable à Playlist Name.
+ /// Looks up a localized string similar to Playlist Name.
///
public static string AddToPlaylistNewPlaylistName {
get {
@@ -160,7 +169,7 @@ public static string AddToPlaylistNewPlaylistName {
}
///
- /// Recherche une chaîne localisée semblable à Select a Playlist.
+ /// Looks up a localized string similar to Select a Playlist.
///
public static string AddToPlaylistPlaceholder {
get {
@@ -169,7 +178,7 @@ public static string AddToPlaylistPlaceholder {
}
///
- /// Recherche une chaîne localisée semblable à Add.
+ /// Looks up a localized string similar to Add.
///
public static string AddToPlaylistPrimaryButtonText {
get {
@@ -178,7 +187,7 @@ public static string AddToPlaylistPrimaryButtonText {
}
///
- /// Recherche une chaîne localisée semblable à Add track(s) to the following Playlist:.
+ /// Looks up a localized string similar to Add track(s) to the following Playlist:.
///
public static string AddToPlaylistText {
get {
@@ -187,7 +196,7 @@ public static string AddToPlaylistText {
}
///
- /// Recherche une chaîne localisée semblable à Add to Playlist.
+ /// Looks up a localized string similar to Add to Playlist.
///
public static string AddToPlaylistTitle {
get {
@@ -196,7 +205,7 @@ public static string AddToPlaylistTitle {
}
///
- /// Recherche une chaîne localisée semblable à Stylophone.
+ /// Looks up a localized string similar to Stylophone.
///
public static string AppDisplayName {
get {
@@ -205,7 +214,7 @@ public static string AppDisplayName {
}
///
- /// Recherche une chaîne localisée semblable à Cancel.
+ /// Looks up a localized string similar to Cancel.
///
public static string CancelButtonText {
get {
@@ -214,7 +223,7 @@ public static string CancelButtonText {
}
///
- /// Recherche une chaîne localisée semblable à Save Queue as Playlist.
+ /// Looks up a localized string similar to Save Queue as Playlist.
///
public static string ContextMenuAddQueueToPlaylist {
get {
@@ -223,7 +232,7 @@ public static string ContextMenuAddQueueToPlaylist {
}
///
- /// Recherche une chaîne localisée semblable à Add to Playlist.
+ /// Looks up a localized string similar to Add to Playlist.
///
public static string ContextMenuAddToPlaylist {
get {
@@ -232,7 +241,7 @@ public static string ContextMenuAddToPlaylist {
}
///
- /// Recherche une chaîne localisée semblable à Add to Queue.
+ /// Looks up a localized string similar to Add to Queue.
///
public static string ContextMenuAddToQueue {
get {
@@ -241,7 +250,7 @@ public static string ContextMenuAddToQueue {
}
///
- /// Recherche une chaîne localisée semblable à Clear Queue.
+ /// Looks up a localized string similar to Clear Queue.
///
public static string ContextMenuClearQueue {
get {
@@ -250,7 +259,7 @@ public static string ContextMenuClearQueue {
}
///
- /// Recherche une chaîne localisée semblable à Delete Playlist.
+ /// Looks up a localized string similar to Delete Playlist.
///
public static string ContextMenuDeletePlaylist {
get {
@@ -259,7 +268,7 @@ public static string ContextMenuDeletePlaylist {
}
///
- /// Recherche une chaîne localisée semblable à Play.
+ /// Looks up a localized string similar to Play.
///
public static string ContextMenuPlay {
get {
@@ -268,7 +277,7 @@ public static string ContextMenuPlay {
}
///
- /// Recherche une chaîne localisée semblable à Remove from Playlist.
+ /// Looks up a localized string similar to Remove from Playlist.
///
public static string ContextMenuRemoveFromPlaylist {
get {
@@ -277,7 +286,7 @@ public static string ContextMenuRemoveFromPlaylist {
}
///
- /// Recherche une chaîne localisée semblable à Remove from Queue.
+ /// Looks up a localized string similar to Remove from Queue.
///
public static string ContextMenuRemoveFromQueue {
get {
@@ -286,7 +295,7 @@ public static string ContextMenuRemoveFromQueue {
}
///
- /// Recherche une chaîne localisée semblable à View Album.
+ /// Looks up a localized string similar to View Album.
///
public static string ContextMenuViewAlbum {
get {
@@ -295,7 +304,7 @@ public static string ContextMenuViewAlbum {
}
///
- /// Recherche une chaîne localisée semblable à Server Database is Updating.
+ /// Looks up a localized string similar to Server Database is Updating.
///
public static string DatabaseUpdateHeader {
get {
@@ -304,7 +313,7 @@ public static string DatabaseUpdateHeader {
}
///
- /// Recherche une chaîne localisée semblable à Delete Playlist?.
+ /// Looks up a localized string similar to Delete Playlist?.
///
public static string DeletePlaylistContentDialog {
get {
@@ -313,7 +322,7 @@ public static string DeletePlaylistContentDialog {
}
///
- /// Recherche une chaîne localisée semblable à Is your MPD server connected?.
+ /// Looks up a localized string similar to Is your MPD server connected?.
///
public static string EmptyFoldersDesc {
get {
@@ -322,7 +331,7 @@ public static string EmptyFoldersDesc {
}
///
- /// Recherche une chaîne localisée semblable à No folders found on server..
+ /// Looks up a localized string similar to No folders found on server..
///
public static string EmptyFoldersTitle {
get {
@@ -331,7 +340,7 @@ public static string EmptyFoldersTitle {
}
///
- /// Recherche une chaîne localisée semblable à Ain't nothin' like an empty library..
+ /// Looks up a localized string similar to Ain't nothin' like an empty library..
///
public static string EmptyLibraryTitle {
get {
@@ -340,7 +349,7 @@ public static string EmptyLibraryTitle {
}
///
- /// Recherche une chaîne localisée semblable à Get some tracks in there!.
+ /// Looks up a localized string similar to Get some tracks in there!.
///
public static string EmptyPlaylistDesc {
get {
@@ -349,7 +358,7 @@ public static string EmptyPlaylistDesc {
}
///
- /// Recherche une chaîne localisée semblable à I can't jam to this..
+ /// Looks up a localized string similar to I can't jam to this..
///
public static string EmptyPlaylistTitle {
get {
@@ -358,7 +367,7 @@ public static string EmptyPlaylistTitle {
}
///
- /// Recherche une chaîne localisée semblable à Why don't you add some music?.
+ /// Looks up a localized string similar to Why don't you add some music?.
///
public static string EmptyQueueDesc {
get {
@@ -367,7 +376,7 @@ public static string EmptyQueueDesc {
}
///
- /// Recherche une chaîne localisée semblable à All is quiet now..
+ /// Looks up a localized string similar to All is quiet now..
///
public static string EmptyQueueTitle {
get {
@@ -376,7 +385,7 @@ public static string EmptyQueueTitle {
}
///
- /// Recherche une chaîne localisée semblable à No Tracks found on Server..
+ /// Looks up a localized string similar to No Tracks found on Server..
///
public static string EmptySearchDesc {
get {
@@ -385,7 +394,7 @@ public static string EmptySearchDesc {
}
///
- /// Recherche une chaîne localisée semblable à Funky Fresh Search!.
+ /// Looks up a localized string similar to Funky Fresh Search!.
///
public static string EmptySearchTitle {
get {
@@ -394,7 +403,7 @@ public static string EmptySearchTitle {
}
///
- /// Recherche une chaîne localisée semblable à Couldn't add Album: {0}.
+ /// Looks up a localized string similar to Couldn't add Album: {0}.
///
public static string ErrorAddingAlbum {
get {
@@ -403,7 +412,7 @@ public static string ErrorAddingAlbum {
}
///
- /// Recherche une chaîne localisée semblable à Couldn't clear queue!.
+ /// Looks up a localized string similar to Couldn't clear queue!.
///
public static string ErrorCantClearCache {
get {
@@ -412,7 +421,7 @@ public static string ErrorCantClearCache {
}
///
- /// Recherche une chaîne localisée semblable à Error: {0}.
+ /// Looks up a localized string similar to Error: {0}.
///
public static string ErrorGeneric {
get {
@@ -421,7 +430,7 @@ public static string ErrorGeneric {
}
///
- /// Recherche une chaîne localisée semblable à Invalid MPD Response..
+ /// Looks up a localized string similar to Invalid MPD Response..
///
public static string ErrorInvalidMPDResponse {
get {
@@ -430,7 +439,7 @@ public static string ErrorInvalidMPDResponse {
}
///
- /// Recherche une chaîne localisée semblable à This track doesn't have a matching Album..
+ /// Looks up a localized string similar to This track doesn't have a matching Album..
///
public static string ErrorNoMatchingAlbum {
get {
@@ -439,7 +448,7 @@ public static string ErrorNoMatchingAlbum {
}
///
- /// Recherche une chaîne localisée semblable à Invalid password.
+ /// Looks up a localized string similar to Invalid password.
///
public static string ErrorPassword {
get {
@@ -448,7 +457,7 @@ public static string ErrorPassword {
}
///
- /// Recherche une chaîne localisée semblable à Error trying to play the MPD server's httpd stream.
+ /// Looks up a localized string similar to Error trying to play the MPD server's httpd stream.
///
public static string ErrorPlayingMPDStream {
get {
@@ -457,7 +466,7 @@ public static string ErrorPlayingMPDStream {
}
///
- /// Recherche une chaîne localisée semblable à Couldn't play content: {0}.
+ /// Looks up a localized string similar to Couldn't play content: {0}.
///
public static string ErrorPlayingTrack {
get {
@@ -466,7 +475,7 @@ public static string ErrorPlayingTrack {
}
///
- /// Recherche une chaîne localisée semblable à Sending {0} failed.
+ /// Looks up a localized string similar to Sending {0} failed.
///
public static string ErrorSendingMPDCommand {
get {
@@ -475,7 +484,7 @@ public static string ErrorSendingMPDCommand {
}
///
- /// Recherche une chaîne localisée semblable à Updating Playlists failed.
+ /// Looks up a localized string similar to Updating Playlists failed.
///
public static string ErrorUpdatingPlaylist {
get {
@@ -484,7 +493,7 @@ public static string ErrorUpdatingPlaylist {
}
///
- /// Recherche une chaîne localisée semblable à David Bowie is credited with playing the Stylophone on his 1969 debut hit song "Space Oddity" and also for his 2002 album Heathen track titled "Slip Away," as well as on the song "Heathen (The Rays)"..
+ /// Looks up a localized string similar to David Bowie is credited with playing the Stylophone on his 1969 debut hit song "Space Oddity" and also for his 2002 album Heathen track titled "Slip Away," as well as on the song "Heathen (The Rays)"..
///
public static string FirstRunFlavorText {
get {
@@ -493,7 +502,7 @@ public static string FirstRunFlavorText {
}
///
- /// Recherche une chaîne localisée semblable à To get started, please visit the Settings page to key in your MPD server's URL and port.
+ /// Looks up a localized string similar to To get started, please visit the Settings page to key in your MPD server's URL and port.
///Keep in mind Stylophone can send usage data to help diagnose bugs.
///If you're not okay with this, you can disable telemetry in the Settings.
///Hope you enjoy using the application!
@@ -506,7 +515,7 @@ public static string FirstRunText {
}
///
- /// Recherche une chaîne localisée semblable à Welcome to Stylophone!.
+ /// Looks up a localized string similar to Welcome to Stylophone!.
///
public static string FirstRunTitle {
get {
@@ -515,7 +524,7 @@ public static string FirstRunTitle {
}
///
- /// Recherche une chaîne localisée semblable à Close all open folders.
+ /// Looks up a localized string similar to Close all open folders.
///
public static string FoldersCollapseAll {
get {
@@ -524,7 +533,7 @@ public static string FoldersCollapseAll {
}
///
- /// Recherche une chaîne localisée semblable à Folders.
+ /// Looks up a localized string similar to Folders.
///
public static string FoldersHeader {
get {
@@ -533,7 +542,7 @@ public static string FoldersHeader {
}
///
- /// Recherche une chaîne localisée semblable à Loading....
+ /// Looks up a localized string similar to Loading....
///
public static string FoldersLoadingTreeItem {
get {
@@ -542,7 +551,7 @@ public static string FoldersLoadingTreeItem {
}
///
- /// Recherche une chaîne localisée semblable à MPD Filesystem.
+ /// Looks up a localized string similar to MPD Filesystem.
///
public static string FoldersRoot {
get {
@@ -551,7 +560,7 @@ public static string FoldersRoot {
}
///
- /// Recherche une chaîne localisée semblable à Library.
+ /// Looks up a localized string similar to Library.
///
public static string LibraryHeader {
get {
@@ -560,7 +569,7 @@ public static string LibraryHeader {
}
///
- /// Recherche une chaîne localisée semblable à Search.
+ /// Looks up a localized string similar to Search.
///
public static string LibrarySearchPlaceholder {
get {
@@ -569,7 +578,7 @@ public static string LibrarySearchPlaceholder {
}
///
- /// Recherche une chaîne localisée semblable à Local Volume.
+ /// Looks up a localized string similar to Local Volume.
///
public static string LocalVolumeHeader {
get {
@@ -578,7 +587,7 @@ public static string LocalVolumeHeader {
}
///
- /// Recherche une chaîne localisée semblable à No.
+ /// Looks up a localized string similar to No.
///
public static string NoButtonText {
get {
@@ -587,7 +596,7 @@ public static string NoButtonText {
}
///
- /// Recherche une chaîne localisée semblable à Added to Playlist {0}!.
+ /// Looks up a localized string similar to Added to Playlist {0}!.
///
public static string NotificationAddedToPlaylist {
get {
@@ -596,7 +605,7 @@ public static string NotificationAddedToPlaylist {
}
///
- /// Recherche une chaîne localisée semblable à Added to Queue!.
+ /// Looks up a localized string similar to Added to Queue!.
///
public static string NotificationAddedToQueue {
get {
@@ -605,7 +614,7 @@ public static string NotificationAddedToQueue {
}
///
- /// Recherche une chaîne localisée semblable à Album art cache has been deleted..
+ /// Looks up a localized string similar to Album art cache has been deleted..
///
public static string NotificationCacheDeleted {
get {
@@ -614,7 +623,7 @@ public static string NotificationCacheDeleted {
}
///
- /// Recherche une chaîne localisée semblable à The database is already being updated..
+ /// Looks up a localized string similar to The database is already being updated..
///
public static string NotificationDbAlreadyUpdating {
get {
@@ -623,7 +632,7 @@ public static string NotificationDbAlreadyUpdating {
}
///
- /// Recherche une chaîne localisée semblable à Database update started..
+ /// Looks up a localized string similar to Database update started..
///
public static string NotificationDbUpdateStarted {
get {
@@ -632,7 +641,7 @@ public static string NotificationDbUpdateStarted {
}
///
- /// Recherche une chaîne localisée semblable à No Track is currently playing..
+ /// Looks up a localized string similar to No Track is currently playing..
///
public static string NotificationNoTrackPlaying {
get {
@@ -641,7 +650,7 @@ public static string NotificationNoTrackPlaying {
}
///
- /// Recherche une chaîne localisée semblable à No tracks loaded yet..
+ /// Looks up a localized string similar to No tracks loaded yet..
///
public static string NotificationNoTracksLoaded {
get {
@@ -650,7 +659,7 @@ public static string NotificationNoTracksLoaded {
}
///
- /// Recherche une chaîne localisée semblable à Now Playing {0}.
+ /// Looks up a localized string similar to Now Playing {0}.
///
public static string NotificationNowPlayingTrack {
get {
@@ -659,7 +668,7 @@ public static string NotificationNowPlayingTrack {
}
///
- /// Recherche une chaîne localisée semblable à The Playlist has been removed..
+ /// Looks up a localized string similar to The Playlist has been removed..
///
public static string NotificationPlaylistRemoved {
get {
@@ -668,7 +677,7 @@ public static string NotificationPlaylistRemoved {
}
///
- /// Recherche une chaîne localisée semblable à Off.
+ /// Looks up a localized string similar to Off.
///
public static string OffText {
get {
@@ -677,7 +686,7 @@ public static string OffText {
}
///
- /// Recherche une chaîne localisée semblable à OK.
+ /// Looks up a localized string similar to OK.
///
public static string OKButtonText {
get {
@@ -686,7 +695,7 @@ public static string OKButtonText {
}
///
- /// Recherche une chaîne localisée semblable à On.
+ /// Looks up a localized string similar to On.
///
public static string OnText {
get {
@@ -695,7 +704,7 @@ public static string OnText {
}
///
- /// Recherche une chaîne localisée semblable à Up Next:.
+ /// Looks up a localized string similar to Up Next:.
///
public static string PlaybackUpNext {
get {
@@ -704,7 +713,7 @@ public static string PlaybackUpNext {
}
///
- /// Recherche une chaîne localisée semblable à Playlists.
+ /// Looks up a localized string similar to Playlists.
///
public static string PlaylistsHeader {
get {
@@ -713,7 +722,7 @@ public static string PlaylistsHeader {
}
///
- /// Recherche une chaîne localisée semblable à Queue.
+ /// Looks up a localized string similar to Queue.
///
public static string QueueHeader {
get {
@@ -722,7 +731,7 @@ public static string QueueHeader {
}
///
- /// Recherche une chaîne localisée semblable à Pick some Songs.
+ /// Looks up a localized string similar to Pick some Songs.
///
public static string RandomTracksHeader {
get {
@@ -731,7 +740,7 @@ public static string RandomTracksHeader {
}
///
- /// Recherche une chaîne localisée semblable à Shuffling through your library....
+ /// Looks up a localized string similar to Shuffling through your library....
///
public static string RandomTracksInProgress {
get {
@@ -740,7 +749,7 @@ public static string RandomTracksInProgress {
}
///
- /// Recherche une chaîne localisée semblable à Thanks for using Stylophone! Would you like to rate the app on the Store?
+ /// Looks up a localized string similar to Thanks for using Stylophone! Would you like to rate the app on the Store?
///(We won't ask again. 🙏).
///
public static string RateAppPromptText {
@@ -750,7 +759,7 @@ public static string RateAppPromptText {
}
///
- /// Recherche une chaîne localisée semblable à Rate the Application.
+ /// Looks up a localized string similar to Rate the Application.
///
public static string RateAppPromptTitle {
get {
@@ -759,7 +768,7 @@ public static string RateAppPromptTitle {
}
///
- /// Recherche une chaîne localisée semblable à Albums.
+ /// Looks up a localized string similar to Albums.
///
public static string SearchAlbumsToggle {
get {
@@ -768,7 +777,7 @@ public static string SearchAlbumsToggle {
}
///
- /// Recherche une chaîne localisée semblable à Artists.
+ /// Looks up a localized string similar to Artists.
///
public static string SearchArtistsToggle {
get {
@@ -777,7 +786,7 @@ public static string SearchArtistsToggle {
}
///
- /// Recherche une chaîne localisée semblable à Search for "{0}" on the server....
+ /// Looks up a localized string similar to Search for "{0}" on the server....
///
public static string SearchGoToDetail {
get {
@@ -786,7 +795,7 @@ public static string SearchGoToDetail {
}
///
- /// Recherche une chaîne localisée semblable à No Results have been found....
+ /// Looks up a localized string similar to No Results have been found....
///
public static string SearchNoResultsTitle_Text {
get {
@@ -795,7 +804,7 @@ public static string SearchNoResultsTitle_Text {
}
///
- /// Recherche une chaîne localisée semblable à Search Tracks....
+ /// Looks up a localized string similar to Search Tracks....
///
public static string SearchPlaceholderText {
get {
@@ -804,7 +813,7 @@ public static string SearchPlaceholderText {
}
///
- /// Recherche une chaîne localisée semblable à Search Results for "{0}".
+ /// Looks up a localized string similar to Search Results for "{0}".
///
public static string SearchResultsFor {
get {
@@ -813,7 +822,7 @@ public static string SearchResultsFor {
}
///
- /// Recherche une chaîne localisée semblable à Tracks.
+ /// Looks up a localized string similar to Tracks.
///
public static string SearchTracksToggle {
get {
@@ -822,7 +831,7 @@ public static string SearchTracksToggle {
}
///
- /// Recherche une chaîne localisée semblable à About this application.
+ /// Looks up a localized string similar to About this application.
///
public static string SettingsAbout {
get {
@@ -831,7 +840,7 @@ public static string SettingsAbout {
}
///
- /// Recherche une chaîne localisée semblable à A pretty cool MPD Client. Uses MpcNET..
+ /// Looks up a localized string similar to A pretty cool MPD Client. Uses MpcNET..
///
public static string SettingsAboutText {
get {
@@ -840,7 +849,7 @@ public static string SettingsAboutText {
}
///
- /// Recherche une chaîne localisée semblable à Download Album Art from the MPD Server.
+ /// Looks up a localized string similar to Download Album Art from the MPD Server.
///
public static string SettingsAlbumArt {
get {
@@ -849,7 +858,7 @@ public static string SettingsAlbumArt {
}
///
- /// Recherche une chaîne localisée semblable à Stylophone stores album art locally to avoid overloading your MPD Server..
+ /// Looks up a localized string similar to Stylophone stores album art locally to avoid overloading your MPD Server..
///
public static string SettingsAlbumArtText {
get {
@@ -858,7 +867,7 @@ public static string SettingsAlbumArtText {
}
///
- /// Recherche une chaîne localisée semblable à Analytics.
+ /// Looks up a localized string similar to Analytics.
///
public static string SettingsAnalytics {
get {
@@ -867,7 +876,7 @@ public static string SettingsAnalytics {
}
///
- /// Recherche une chaîne localisée semblable à Allow Stylophone to send crash and analytics reports.
+ /// Looks up a localized string similar to Allow Stylophone to send crash and analytics reports.
///
public static string SettingsAnalyticsText {
get {
@@ -876,7 +885,7 @@ public static string SettingsAnalyticsText {
}
///
- /// Recherche une chaîne localisée semblable à This setting will apply after restarting the app..
+ /// Looks up a localized string similar to This setting will apply after restarting the app..
///
public static string SettingsApplyOnRestart {
get {
@@ -885,7 +894,7 @@ public static string SettingsApplyOnRestart {
}
///
- /// Recherche une chaîne localisée semblable à Clear Cache.
+ /// Looks up a localized string similar to Clear Cache.
///
public static string SettingsClearCache {
get {
@@ -894,7 +903,7 @@ public static string SettingsClearCache {
}
///
- /// Recherche une chaîne localisée semblable à Clear the local album art cache.
+ /// Looks up a localized string similar to Clear the local album art cache.
///
public static string SettingsClearCacheDescription {
get {
@@ -903,7 +912,7 @@ public static string SettingsClearCacheDescription {
}
///
- /// Recherche une chaîne localisée semblable à Personalization.
+ /// Looks up a localized string similar to Personalization.
///
public static string SettingsCustomization {
get {
@@ -912,7 +921,7 @@ public static string SettingsCustomization {
}
///
- /// Recherche une chaîne localisée semblable à Database and Album Art.
+ /// Looks up a localized string similar to Database and Album Art.
///
public static string SettingsDatabase {
get {
@@ -921,7 +930,7 @@ public static string SettingsDatabase {
}
///
- /// Recherche une chaîne localisée semblable à Source Code, License and Privacy Statement.
+ /// Looks up a localized string similar to Source Code, License and Privacy Statement.
///
public static string SettingsGithub {
get {
@@ -930,7 +939,7 @@ public static string SettingsGithub {
}
///
- /// Recherche une chaîne localisée semblable à https://github.com/Difegue/Stylophone.
+ /// Looks up a localized string similar to https://github.com/Difegue/Stylophone.
///
public static string SettingsGithubLink {
get {
@@ -939,7 +948,7 @@ public static string SettingsGithubLink {
}
///
- /// Recherche une chaîne localisée semblable à Settings.
+ /// Looks up a localized string similar to Settings.
///
public static string SettingsHeader {
get {
@@ -948,7 +957,7 @@ public static string SettingsHeader {
}
///
- /// Recherche une chaîne localisée semblable à Local Playback available.
+ /// Looks up a localized string similar to Local Playback available.
///
public static string SettingsLocalPlaybackAvailable {
get {
@@ -957,7 +966,7 @@ public static string SettingsLocalPlaybackAvailable {
}
///
- /// Recherche une chaîne localisée semblable à Local Playback.
+ /// Looks up a localized string similar to Local Playback.
///
public static string SettingsLocalPlaybackHeader {
get {
@@ -966,7 +975,7 @@ public static string SettingsLocalPlaybackHeader {
}
///
- /// Recherche une chaîne localisée semblable à Stylophone can play your MPD Server's music stream.
+ /// Looks up a localized string similar to Stylophone can play your MPD Server's music stream.
///Enabling this option will show a second volume slider to control local volume..
///
public static string SettingsLocalPlaybackText {
@@ -976,7 +985,7 @@ public static string SettingsLocalPlaybackText {
}
///
- /// Recherche une chaîne localisée semblable à Couldn't find an MPD server at this address!.
+ /// Looks up a localized string similar to Couldn't find an MPD server at this address!.
///
public static string SettingsNoServerError {
get {
@@ -985,7 +994,7 @@ public static string SettingsNoServerError {
}
///
- /// Recherche une chaîne localisée semblable à MPD Server.
+ /// Looks up a localized string similar to MPD Server.
///
public static string SettingsServer {
get {
@@ -994,7 +1003,7 @@ public static string SettingsServer {
}
///
- /// Recherche une chaîne localisée semblable à Hostname.
+ /// Looks up a localized string similar to Hostname.
///
public static string SettingsServerHost {
get {
@@ -1003,7 +1012,7 @@ public static string SettingsServerHost {
}
///
- /// Recherche une chaîne localisée semblable à Password.
+ /// Looks up a localized string similar to Password.
///
public static string SettingsServerPassword {
get {
@@ -1012,7 +1021,7 @@ public static string SettingsServerPassword {
}
///
- /// Recherche une chaîne localisée semblable à Port.
+ /// Looks up a localized string similar to Port.
///
public static string SettingsServerPort {
get {
@@ -1021,7 +1030,7 @@ public static string SettingsServerPort {
}
///
- /// Recherche une chaîne localisée semblable à Theme.
+ /// Looks up a localized string similar to Theme.
///
public static string SettingsTheme {
get {
@@ -1030,7 +1039,7 @@ public static string SettingsTheme {
}
///
- /// Recherche une chaîne localisée semblable à Dark.
+ /// Looks up a localized string similar to Dark.
///
public static string SettingsThemeDark {
get {
@@ -1039,7 +1048,7 @@ public static string SettingsThemeDark {
}
///
- /// Recherche une chaîne localisée semblable à System default.
+ /// Looks up a localized string similar to System default.
///
public static string SettingsThemeDefault {
get {
@@ -1048,7 +1057,7 @@ public static string SettingsThemeDefault {
}
///
- /// Recherche une chaîne localisée semblable à Light.
+ /// Looks up a localized string similar to Light.
///
public static string SettingsThemeLight {
get {
@@ -1057,7 +1066,7 @@ public static string SettingsThemeLight {
}
///
- /// Recherche une chaîne localisée semblable à UI Density.
+ /// Looks up a localized string similar to UI Density.
///
public static string SettingsUIDensity {
get {
@@ -1066,7 +1075,7 @@ public static string SettingsUIDensity {
}
///
- /// Recherche une chaîne localisée semblable à Compact.
+ /// Looks up a localized string similar to Compact.
///
public static string SettingsUIDensityCompact {
get {
@@ -1075,7 +1084,7 @@ public static string SettingsUIDensityCompact {
}
///
- /// Recherche une chaîne localisée semblable à Normal.
+ /// Looks up a localized string similar to Normal.
///
public static string SettingsUIDensityNormal {
get {
@@ -1084,7 +1093,7 @@ public static string SettingsUIDensityNormal {
}
///
- /// Recherche une chaîne localisée semblable à Update.
+ /// Looks up a localized string similar to Update.
///
public static string SettingsUpdateDatabase {
get {
@@ -1093,7 +1102,7 @@ public static string SettingsUpdateDatabase {
}
///
- /// Recherche une chaîne localisée semblable à This operation might take the server some time to complete..
+ /// Looks up a localized string similar to This operation might take the server some time to complete..
///
public static string SettingsUpdateDbDesc {
get {
@@ -1102,7 +1111,7 @@ public static string SettingsUpdateDbDesc {
}
///
- /// Recherche une chaîne localisée semblable à Update the MPD Server Database.
+ /// Looks up a localized string similar to Update the MPD Server Database.
///
public static string SettingsUpdateDbTitle {
get {
@@ -1111,7 +1120,16 @@ public static string SettingsUpdateDbTitle {
}
///
- /// Recherche une chaîne localisée semblable à Yes.
+ /// Looks up a localized string similar to Song playback.
+ ///
+ public static string SongPlaybackLabel {
+ get {
+ return ResourceManager.GetString("SongPlaybackLabel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Yes.
///
public static string YesButtonText {
get {
diff --git a/Sources/Stylophone.Localization/Strings/Resources.en-US.resx b/Sources/Stylophone.Localization/Strings/Resources.en-US.resx
index b341934..50ac531 100644
--- a/Sources/Stylophone.Localization/Strings/Resources.en-US.resx
+++ b/Sources/Stylophone.Localization/Strings/Resources.en-US.resx
@@ -482,4 +482,10 @@ Enabling this option will show a second volume slider to control local volume.
Updating Playlists failed
+
+ Open Fullscreen Playback
+
+
+ Song playback
+
\ No newline at end of file
diff --git a/Sources/Stylophone.Localization/Strings/Resources.fr-FR.resx b/Sources/Stylophone.Localization/Strings/Resources.fr-FR.resx
index eb9d656..2820b28 100644
--- a/Sources/Stylophone.Localization/Strings/Resources.fr-FR.resx
+++ b/Sources/Stylophone.Localization/Strings/Resources.fr-FR.resx
@@ -481,4 +481,10 @@ L'activation de cette option affichera un second slider pour contrôler le volum
La mise à jour des playlists a échoué
+
+ Ouvrir le lecteur plein écran
+
+
+ Lecture de la piste
+
\ No newline at end of file
diff --git a/Sources/Stylophone.Localization/Strings/Resources.pt-PT.resx b/Sources/Stylophone.Localization/Strings/Resources.pt-PT.resx
index 92c13b3..135d070 100644
--- a/Sources/Stylophone.Localization/Strings/Resources.pt-PT.resx
+++ b/Sources/Stylophone.Localization/Strings/Resources.pt-PT.resx
@@ -478,4 +478,10 @@ Ativando esta opção mostrará um segundo deslizador de volume para controlar o
Não foi possível enviar {0}
+
+ Mostrar Leitor
+
+
+ Leitura da faixa
+
\ No newline at end of file
diff --git a/Sources/Stylophone.Localization/Strings/Resources.resx b/Sources/Stylophone.Localization/Strings/Resources.resx
index a5fe00b..b18cecb 100644
--- a/Sources/Stylophone.Localization/Strings/Resources.resx
+++ b/Sources/Stylophone.Localization/Strings/Resources.resx
@@ -482,4 +482,10 @@ Enabling this option will show a second volume slider to control local volume.
Updating Playlists failed
+
+ Open Fullscreen Playback
+
+
+ Song playback
+
\ No newline at end of file
diff --git a/Sources/Stylophone/Styles/StyloResources.xaml b/Sources/Stylophone/Styles/StyloResources.xaml
index ed16f68..819fb5f 100644
--- a/Sources/Stylophone/Styles/StyloResources.xaml
+++ b/Sources/Stylophone/Styles/StyloResources.xaml
@@ -62,6 +62,7 @@
diff --git a/Sources/Stylophone/Stylophone.csproj b/Sources/Stylophone/Stylophone.csproj
index 50b8b46..0ad7510 100644
--- a/Sources/Stylophone/Stylophone.csproj
+++ b/Sources/Stylophone/Stylophone.csproj
@@ -18,8 +18,7 @@
512
{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
true
-
-
+ Stylophone_TemporaryKey.pfx
MiddleClickScrolling-CursorType.res
False
SHA256
@@ -28,7 +27,8 @@
Always
x86|x64|arm
0
- AC6B4D78B6FC1C9719183572B36F08C049AFFB1E
+
+
True
DXFeatureLevel
diff --git a/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml b/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml
index f6c937d..c773e8a 100644
--- a/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml
+++ b/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml
@@ -110,6 +110,8 @@
Canvas.ZIndex="10"
Click="{x:Bind PlaybackViewModel.NavigateNowPlaying}"
CornerRadius="4"
+ AutomationProperties.Name="{x:Bind strings:Resources.ActionFullscreenPlayback}"
+ AutomationProperties.FullDescription="{x:Bind PlaybackViewModel.CurrentTrack.Name, Mode=OneWay}"
IsEnabled="{x:Bind PlaybackViewModel.IsTrackInfoAvailable, Mode=OneWay}"
Visibility="{x:Bind PlaybackViewModel.ShowTrackName, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
@@ -201,6 +203,8 @@
Click="{x:Bind PlaybackViewModel.ToggleShuffle}"
FontSize="18"
Style="{StaticResource SVButtonStyle}"
+ AutomationProperties.Name="{x:Bind strings:Resources.ActionToggleShuffle}"
+ AutomationProperties.ItemStatus="{x:Bind PlaybackViewModel.IsShuffleEnabled}"
ToolTipService.ToolTip="{x:Bind strings:Resources.ActionToggleShuffle}">
@@ -217,6 +221,7 @@
Click="{x:Bind PlaybackViewModel.SkipPrevious}"
FontSize="22"
Style="{StaticResource SVButtonStyle}"
+ AutomationProperties.Name="{x:Bind strings:Resources.ActionSkipPrevious}"
ToolTipService.ToolTip="{x:Bind strings:Resources.ActionSkipPrevious}">
@@ -232,6 +237,7 @@
Content="{x:Bind PlaybackViewModel.PlayButtonContent, Mode=OneWay}"
FontSize="28"
Style="{StaticResource SVButtonStyle}"
+ AutomationProperties.Name="{x:Bind strings:Resources.ActionPlayPause}"
ToolTipService.ToolTip="{x:Bind strings:Resources.ActionPlayPause}" />
@@ -242,6 +248,7 @@
Click="{x:Bind PlaybackViewModel.SkipNext}"
FontSize="22"
Style="{StaticResource SVButtonStyle}"
+ AutomationProperties.Name="{x:Bind strings:Resources.ActionSkipNext}"
ToolTipService.ToolTip="{x:Bind strings:Resources.ActionSkipNext}">
@@ -266,6 +273,8 @@
Content="{x:Bind PlaybackViewModel.RepeatIcon, Mode=OneWay}"
FontSize="18"
Style="{StaticResource SVButtonStyle}"
+ AutomationProperties.Name="{x:Bind strings:Resources.ActionToggleRepeat}"
+ AutomationProperties.ItemStatus="{x:Bind PlaybackViewModel.IsRepeatEnabled}"
ToolTipService.ToolTip="{x:Bind strings:Resources.ActionToggleRepeat}" />
@@ -304,6 +313,7 @@
Maximum="{x:Bind PlaybackViewModel.MaxTimeValue, Mode=OneWay}"
PointerCaptureLost="{x:Bind PlaybackViewModel.OnPlayingSliderChange}"
ThumbToolTipValueConverter="{StaticResource SliderValueConverter}"
+ AutomationProperties.ItemStatus="{x:Bind PlaybackViewModel.CurrentTimeValue, Converter={StaticResource SliderValueConverter}}"
Visibility="{x:Bind PlaybackViewModel.IsTrackInfoAvailable, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"
Value="{x:Bind PlaybackViewModel.CurrentTimeValue, Mode=TwoWay}" />
@@ -361,6 +371,7 @@
Content="{x:Bind PlaybackViewModel.VolumeIcon, Mode=OneWay}"
FontSize="21"
Style="{StaticResource SVButtonStyle}"
+ AutomationProperties.Name="{x:Bind strings:Resources.ActionChangeVolume}"
ToolTipService.ToolTip="{x:Bind strings:Resources.ActionChangeVolume}" />
@@ -488,6 +500,7 @@
Margin="{StaticResource XSmallLeftMargin}"
FontSize="22"
Style="{StaticResource SVButtonStyle}"
+ AutomationProperties.Name="{x:Bind strings:Resources.ActionMore}"
ToolTipService.ToolTip="{x:Bind strings:Resources.ActionMore}">
From 817b08b955825044b9f2c4d51a2d3b6f95e6641e Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 19 Sep 2023 21:24:47 +0200
Subject: [PATCH 49/56] Make playback slider usable with keyboard navigation as
well
---
Sources/Stylophone/Views/Playback/NowPlayingBar.xaml | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml b/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml
index c773e8a..503ff61 100644
--- a/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml
+++ b/Sources/Stylophone/Views/Playback/NowPlayingBar.xaml
@@ -310,12 +310,15 @@
Margin="16,8,16,0"
ManipulationMode="All"
ManipulationStarting="{x:Bind PlaybackViewModel.OnPlayingSliderMoving}"
- Maximum="{x:Bind PlaybackViewModel.MaxTimeValue, Mode=OneWay}"
+ GettingFocus="{x:Bind PlaybackViewModel.OnPlayingSliderMoving}"
PointerCaptureLost="{x:Bind PlaybackViewModel.OnPlayingSliderChange}"
+ LosingFocus="{x:Bind PlaybackViewModel.OnPlayingSliderChange}"
ThumbToolTipValueConverter="{StaticResource SliderValueConverter}"
- AutomationProperties.ItemStatus="{x:Bind PlaybackViewModel.CurrentTimeValue, Converter={StaticResource SliderValueConverter}}"
+ AutomationProperties.Name="{x:Bind strings:Resources.SongPlaybackLabel}"
+ AutomationProperties.FullDescription="{x:Bind PlaybackViewModel.CurrentTimeValue, Converter={StaticResource SliderValueConverter}}"
Visibility="{x:Bind PlaybackViewModel.IsTrackInfoAvailable, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"
- Value="{x:Bind PlaybackViewModel.CurrentTimeValue, Mode=TwoWay}" />
+ Value="{x:Bind PlaybackViewModel.CurrentTimeValue, Mode=TwoWay}"
+ Maximum="{x:Bind PlaybackViewModel.MaxTimeValue, Mode=OneWay}" />
Date: Tue, 19 Sep 2023 21:26:45 +0200
Subject: [PATCH 50/56] Scrap QueueVC autoreload on scroll
---
.../ViewControllers/QueueViewController.cs | 34 +++++++++----------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs b/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
index a7f6943..e979284 100644
--- a/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/QueueViewController.cs
@@ -78,24 +78,24 @@ private void ScrollToPlayingSong(object sender = null, SongChangedEventArgs e =
// Scroll to currently playing song
var playing = ViewModel.Source.Where(t => t.IsPlaying).FirstOrDefault();
- if (playing != null)
- UIApplication.SharedApplication.BeginInvokeOnMainThread(() =>
+ if (playing == null)
+ return;
+
+ UIApplication.SharedApplication.BeginInvokeOnMainThread(() =>
+ {
+ try
+ {
+ var indexPath = NSIndexPath.FromRowSection(ViewModel.Source.IndexOf(playing), 0);
+ var tableViewRows = TableView.NumberOfRowsInSection(0);
+
+ if (tableViewRows >= indexPath.Row)
+ TableView.ScrollToRow(indexPath, UITableViewScrollPosition.Middle, true);
+ }
+ catch (Exception e)
{
- try
- {
- var indexPath = NSIndexPath.FromRowSection(ViewModel.Source.IndexOf(playing), 0);
- var tableViewRows = TableView.NumberOfRowsInSection(0);
-
- if (tableViewRows >= indexPath.Row)
- TableView.ScrollToRow(indexPath, UITableViewScrollPosition.Middle, true);
- }
- catch (Exception e)
- {
- System.Diagnostics.Debug.WriteLine($"Error while scrolling to row: {e}");
- }
- });
- else // inconsistency, reload source wholesale
- ViewModel.LoadInitialDataAsync();
+ System.Diagnostics.Debug.WriteLine($"Error while scrolling to row: {e}");
+ }
+ });
}
private UIMenu GetRowContextMenu(NSIndexPath indexPath)
From fbc8944de3daf958d5728ae8e83a1d03621c35a1 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 19 Sep 2023 21:55:27 +0200
Subject: [PATCH 51/56] Add voiceover hints to playback view/slider
And tweak nowplaying a bit further still jfc it never ends
---
.../ViewModels/Items/TrackViewModel.cs | 4 +
.../ViewControllers/PlaybackViewController.cs | 5 +
.../Views/NowPlaying.storyboard | 116 +++++++++---------
3 files changed, 68 insertions(+), 57 deletions(-)
diff --git a/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs b/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs
index aff7145..c5b8298 100644
--- a/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs
@@ -168,5 +168,9 @@ public void Dispose()
AlbumArt?.Dispose();
}
+ public override string ToString()
+ {
+ return $"{Name} - {File.Artist} - {File.Album}";
+ }
}
}
diff --git a/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs b/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
index 52dd012..b5ce335 100644
--- a/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
@@ -61,6 +61,8 @@ public override void AwakeFromNib()
CompactView.ShuffleButton.PrimaryActionTriggered += (s, e) => ViewModel.ToggleShuffle();
CompactView.OpenFullScreenButton.PrimaryActionTriggered += (s, e) => ViewModel.NavigateNowPlaying();
+ CompactView.OpenFullScreenButton.AccessibilityLabel = Strings.ActionFullscreenPlayback;
+ Binder.Bind(CompactView.OpenFullScreenButton, "accessibilityValue", nameof(ViewModel.CurrentTrack));
// Volume Popover Binding
LocalPlaybackBinder.Bind(LocalPlaybackView, "hidden", nameof(ViewModel.LocalPlayback.IsEnabled), valueTransformer: negateBoolTransformer);
@@ -128,14 +130,17 @@ public override void ViewDidLoad()
{
base.ViewDidLoad();
+ TrackSlider.AccessibilityLabel = Strings.SongPlaybackLabel;
TrackSlider.TouchDragInside += (s, e) =>
{
ViewModel.TimeListened = Miscellaneous.FormatTimeString(TrackSlider.Value * 1000);
+ TrackSlider.AccessibilityValue = ViewModel.TimeListened;
ViewModel.OnPlayingSliderMoving();
};
TrackSlider.ValueChanged += (s, e) =>
{
ViewModel.OnPlayingSliderChange();
+ TrackSlider.AccessibilityValue = ViewModel.TimeListened;
};
var upNextTransformer = NSValueTransformer.GetValueTransformer(nameof(NextTrackToStringValueTransformer));
diff --git a/Sources/Stylophone.iOS/Views/NowPlaying.storyboard b/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
index db4d000..0cf141e 100644
--- a/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
+++ b/Sources/Stylophone.iOS/Views/NowPlaying.storyboard
@@ -1,6 +1,6 @@
-
+
@@ -19,52 +19,52 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
@@ -72,7 +72,7 @@
-
+
@@ -81,7 +81,7 @@
-
+
@@ -89,7 +89,7 @@
-
+
@@ -100,7 +100,7 @@
-
+
@@ -111,7 +111,7 @@
-
+
@@ -122,7 +122,7 @@
-
+
@@ -133,7 +133,7 @@
-
+
@@ -144,7 +144,7 @@
-
+
@@ -155,12 +155,12 @@
-
+
-
+
-
+
@@ -209,11 +209,11 @@
-
+
-
+
@@ -256,16 +256,16 @@
-
+
-
+
-
+
@@ -279,14 +279,14 @@
-
-
-
+
+
+
@@ -298,7 +298,6 @@
-
@@ -311,6 +310,7 @@
+
@@ -326,9 +326,10 @@
+
+
-
@@ -386,27 +387,27 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -419,19 +420,19 @@
-
+
-
+
-
-
+
+
@@ -448,7 +449,7 @@
-
+
@@ -465,7 +466,7 @@
-
+
@@ -482,17 +483,18 @@
-
+
-
+
+
-
+
@@ -507,7 +509,7 @@
-
+
@@ -528,7 +530,7 @@
-
+
@@ -586,16 +588,16 @@
+
+
-
-
@@ -620,15 +622,15 @@
-
+
+
-
From c9d26a205013c4dc85659fcc0d265a9556c5f35a Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 19 Sep 2023 22:04:54 +0200
Subject: [PATCH 52/56] Turns out a proper ToString() is better than adding
manual accessibility hints for tracks wow!
---
Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs | 2 +-
Sources/Stylophone/Styles/StyloResources.xaml | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs b/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs
index c5b8298..907e746 100644
--- a/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/Items/TrackViewModel.cs
@@ -170,7 +170,7 @@ public void Dispose()
public override string ToString()
{
- return $"{Name} - {File.Artist} - {File.Album}";
+ return $"{Name} - {File.Artist} - {File.Album} - {Miscellaneous.FormatTimeString(File.Time*1000)}";
}
}
}
diff --git a/Sources/Stylophone/Styles/StyloResources.xaml b/Sources/Stylophone/Styles/StyloResources.xaml
index 819fb5f..ed16f68 100644
--- a/Sources/Stylophone/Styles/StyloResources.xaml
+++ b/Sources/Stylophone/Styles/StyloResources.xaml
@@ -62,7 +62,6 @@
From 9be48847695b0acd08b5d6a9dd6999d9bf36e751 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Tue, 19 Sep 2023 23:40:17 +0200
Subject: [PATCH 53/56] Additional VoiceOver improvements to playback views
---
.../Helpers/NSValueConverters.cs | 30 +++++++++++++++++++
.../ViewControllers/PlaybackViewController.cs | 16 ++++++++--
2 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/Sources/Stylophone.iOS/Helpers/NSValueConverters.cs b/Sources/Stylophone.iOS/Helpers/NSValueConverters.cs
index fd85059..039e324 100644
--- a/Sources/Stylophone.iOS/Helpers/NSValueConverters.cs
+++ b/Sources/Stylophone.iOS/Helpers/NSValueConverters.cs
@@ -147,4 +147,34 @@ public override NSObject ReverseTransformedValue(NSObject value)
return NSNumber.FromInt32(result);
}
}
+
+ [Register(nameof(TrackToStringValueTransformer))]
+ public class TrackToStringValueTransformer : NSValueTransformer
+ {
+ public static new Class TransformedValueClass => new NSString().Class;
+ public static new bool AllowsReverseTransformation => false;
+
+ public override NSObject TransformedValue(NSObject value)
+ {
+ var text = "";
+
+ if (value is NSWrapper wrap)
+ {
+ var trackVm = (TrackViewModel)wrap.ManagedObject;
+ text = trackVm.ToString();
+ }
+
+ return new NSString(text);
+ }
+
+ public override NSObject ReverseTransformedValue(NSObject value)
+ {
+ int result = 0;
+
+ if (value is NSString s)
+ int.TryParse(s, out result);
+
+ return NSNumber.FromInt32(result);
+ }
+ }
}
diff --git a/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs b/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
index b5ce335..571e9c5 100644
--- a/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/PlaybackViewController.cs
@@ -51,6 +51,7 @@ public override void AwakeFromNib()
// Bind
var negateBoolTransformer = NSValueTransformer.GetValueTransformer(nameof(ReverseBoolValueTransformer));
var intToStringTransformer = NSValueTransformer.GetValueTransformer(nameof(IntToStringValueTransformer));
+ var trackToStringTransformer = NSValueTransformer.GetValueTransformer(nameof(TrackToStringValueTransformer));
// Compact View Binding
Binder.Bind(CompactView, "hidden", nameof(ViewModel.IsTrackInfoAvailable), valueTransformer: negateBoolTransformer);
@@ -60,9 +61,12 @@ public override void AwakeFromNib()
CompactView.PlayPauseButton.PrimaryActionTriggered += (s, e) => ViewModel.ChangePlaybackState();
CompactView.ShuffleButton.PrimaryActionTriggered += (s, e) => ViewModel.ToggleShuffle();
+ CompactView.VolumeButton.AccessibilityLabel = Strings.ActionChangeVolume;
+ CompactView.ShuffleButton.AccessibilityLabel = Strings.ActionToggleShuffle;
+
CompactView.OpenFullScreenButton.PrimaryActionTriggered += (s, e) => ViewModel.NavigateNowPlaying();
CompactView.OpenFullScreenButton.AccessibilityLabel = Strings.ActionFullscreenPlayback;
- Binder.Bind(CompactView.OpenFullScreenButton, "accessibilityValue", nameof(ViewModel.CurrentTrack));
+ Binder.Bind(CompactView.OpenFullScreenButton, "accessibilityValue", nameof(ViewModel.CurrentTrack), valueTransformer: trackToStringTransformer);
// Volume Popover Binding
LocalPlaybackBinder.Bind(LocalPlaybackView, "hidden", nameof(ViewModel.LocalPlayback.IsEnabled), valueTransformer: negateBoolTransformer);
@@ -70,12 +74,13 @@ public override void AwakeFromNib()
LocalMuteButton.PrimaryActionTriggered += (s, e) => ViewModel.LocalPlayback.ToggleMute();
LocalPlaybackBinder.Bind(LocalVolumeSlider, "value", nameof(ViewModel.LocalPlayback.Volume), true);
LocalPlaybackBinder.Bind(LocalVolume, "text", nameof(ViewModel.LocalPlayback.Volume), valueTransformer: intToStringTransformer);
+ LocalVolumeSlider.AccessibilityLabel = Strings.LocalVolumeHeader;
ServerMuteButton.PrimaryActionTriggered += (s, e) => ViewModel.ToggleMute();
Binder.Bind(ServerVolumeSlider, "value", nameof(ViewModel.MediaVolume), true);
Binder.Bind(ServerVolumeSlider, "enabled", nameof(ViewModel.CanSetVolume));
Binder.Bind(ServerVolume, "text", nameof(ViewModel.MediaVolume), valueTransformer: intToStringTransformer);
-
+ ServerVolumeSlider.AccessibilityLabel = Strings.ActionChangeVolume;
}
public override void ViewWillAppear(bool animated)
@@ -134,7 +139,6 @@ public override void ViewDidLoad()
TrackSlider.TouchDragInside += (s, e) =>
{
ViewModel.TimeListened = Miscellaneous.FormatTimeString(TrackSlider.Value * 1000);
- TrackSlider.AccessibilityValue = ViewModel.TimeListened;
ViewModel.OnPlayingSliderMoving();
};
TrackSlider.ValueChanged += (s, e) =>
@@ -150,6 +154,8 @@ public override void ViewDidLoad()
Binder.Bind(RemainingTime, "text", nameof(ViewModel.TimeRemaining));
Binder.Bind(TrackSlider, "value", nameof(ViewModel.CurrentTimeValue), true);
Binder.Bind(TrackSlider, "maximumValue", nameof(ViewModel.MaxTimeValue));
+ Binder.Bind(TrackSlider, "accessibilityValue", nameof(ViewModel.TimeListened));
+
Binder.Bind(upNextView, "text", nameof(ViewModel.NextTrack), valueTransformer:upNextTransformer);
UpdateFullView(ViewModel.CurrentTrack);
@@ -159,6 +165,10 @@ public override void ViewDidLoad()
UpdateButton(RepeatButton, ViewModel.RepeatIcon);
UpdateButton(ShuffleButton, ViewModel.IsShuffleEnabled ? "shuffle.circle.fill" : "shuffle.circle");
+ VolumeButton.AccessibilityLabel = Strings.ActionChangeVolume;
+ ShuffleButton.AccessibilityLabel = Strings.ActionToggleShuffle;
+ RepeatButton.AccessibilityLabel = Strings.ActionToggleRepeat;
+
SkipPrevButton.PrimaryActionTriggered += (s, e) => ViewModel.SkipPrevious();
SkipNextButton.PrimaryActionTriggered += (s, e) => ViewModel.SkipNext();
PlayPauseButton.PrimaryActionTriggered += (s, e) => ViewModel.ChangePlaybackState();
From 4a9cab0820aa7ab06ea9c319097dd4ec266ac34c Mon Sep 17 00:00:00 2001
From: Difegue
Date: Wed, 20 Sep 2023 00:32:45 +0200
Subject: [PATCH 54/56] Finally find a way to get notifications in UIPopover
with margins good lord
---
.../Services/NotificationService.cs | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/Sources/Stylophone.iOS/Services/NotificationService.cs b/Sources/Stylophone.iOS/Services/NotificationService.cs
index a089a52..3e83d5b 100644
--- a/Sources/Stylophone.iOS/Services/NotificationService.cs
+++ b/Sources/Stylophone.iOS/Services/NotificationService.cs
@@ -39,7 +39,7 @@ public override void ShowInAppNotification(InAppNotification notification)
_notificationTimer?.Dispose();
_notificationTimer = new Timer((_) => UIApplication.SharedApplication.InvokeOnMainThread(() =>
rootVc.DismissViewController(true, null)),
- null, 1500, Timeout.Infinite);
+ null, 2000, Timeout.Infinite);
}
public override void ShowBasicToastNotification(string title, string description)
@@ -81,14 +81,24 @@ public override void LoadView()
PreferredContentSize = new CGSize(196, 54);
- View = new UILabel
+ var stackView = new UIStackView
+ {
+ Axis = UILayoutConstraintAxis.Horizontal,
+ Distribution = UIStackViewDistribution.FillProportionally,
+ Spacing = 32
+ };
+
+ stackView.AddArrangedSubview(new UIView());
+ stackView.AddArrangedSubview(new UILabel
{
Text = _text,
Font = UIFont.PreferredHeadline,
- TextAlignment = UITextAlignment.Center,
AdjustsFontSizeToFitWidth = true,
Lines = 2,
- };
+ });
+ stackView.AddArrangedSubview(new UIView());
+
+ View = stackView;
}
From 3b6ffa720f347d0bcfcb8b5077c0c47b2f300e7d Mon Sep 17 00:00:00 2001
From: Difegue
Date: Wed, 20 Sep 2023 02:09:07 +0200
Subject: [PATCH 55/56] Fix phone navigation always bringing you back to the
queue when using the sidebar
---
.../Stylophone.iOS/Services/NavigationService.cs | 14 +++++++++++---
.../Stylophone.iOS/ViewModels/ShellViewModel.cs | 16 +++++++++++++---
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/Sources/Stylophone.iOS/Services/NavigationService.cs b/Sources/Stylophone.iOS/Services/NavigationService.cs
index 91c00bd..3b7a4db 100644
--- a/Sources/Stylophone.iOS/Services/NavigationService.cs
+++ b/Sources/Stylophone.iOS/Services/NavigationService.cs
@@ -29,7 +29,7 @@ public NavigationService()
_viewControllers = new List();
}
- public override bool CanGoBack => NavigationController.ViewControllers?.Count() > 1;
+ public override bool CanGoBack => NavigationController.ViewControllers?.Length > 1;
public override Type CurrentPageViewModelType => _viewModelToStoryboardDictionary.Keys.Where(
k => _viewModelToStoryboardDictionary[k] == NavigationController.VisibleViewController.Storyboard).FirstOrDefault();
@@ -73,14 +73,22 @@ public override void NavigateImplementation(Type viewmodelType, object parameter
{
viewController = viewControllerLoaded.First();
(viewController as IPreparableViewController)?.Prepare(parameter);
- NavigationController.PushViewController(viewController, true);
+
+ if (NavigationController.ViewControllers.Length == 0)
+ NavigationController.ViewControllers = new UIViewController[] { viewController };
+ else
+ NavigationController.PushViewController(viewController, true);
}
else // This is truly new, load the VC from scratch
{
viewController = storyboard.InstantiateInitialViewController();
(viewController as IPreparableViewController)?.Prepare(parameter);
- NavigationController.PushViewController(viewController, true);
_viewControllers.Add(viewController);
+
+ if (NavigationController.ViewControllers.Length == 0)
+ NavigationController.ViewControllers = new UIViewController[] { viewController };
+ else
+ NavigationController.PushViewController(viewController, true);
}
_lastParamUsed = parameter;
diff --git a/Sources/Stylophone.iOS/ViewModels/ShellViewModel.cs b/Sources/Stylophone.iOS/ViewModels/ShellViewModel.cs
index dd497c6..9e56234 100644
--- a/Sources/Stylophone.iOS/ViewModels/ShellViewModel.cs
+++ b/Sources/Stylophone.iOS/ViewModels/ShellViewModel.cs
@@ -97,7 +97,7 @@ protected override void Navigate(object itemInvoked)
{
if (itemInvoked is string s)
{
- _navigationService.Navigate();
+ Navigate(typeof(SettingsViewModel));
return;
}
@@ -114,11 +114,21 @@ protected override void Navigate(object itemInvoked)
// Playlist items navigate with their name as parameter
if (pageType == typeof(PlaylistViewModel))
- _navigationService.Navigate(pageType, sidebarItem.Title);
+ Navigate(pageType, sidebarItem.Title);
else
- _navigationService.Navigate(pageType);
+ Navigate(pageType);
}
}
}
+
+ private void Navigate(Type viewModel, object parameter = null)
+ {
+ // On phones, since the sidebar is its own screen,
+ // we don't want to keep the root view controller(usually the queue) when navigating from the sidebar.
+ if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone)
+ ((NavigationService)_navigationService).NavigationController.SetViewControllers(new UIViewController[0], false);
+
+ _navigationService.Navigate(viewModel, parameter);
+ }
}
}
From 9e6a6687c1b9dd551650a4e9b71415059e8a4468 Mon Sep 17 00:00:00 2001
From: Difegue
Date: Wed, 20 Sep 2023 02:10:05 +0200
Subject: [PATCH 56/56] Fix the age-old problem of the addtoplaylist selector
ending up in the view...
By _making_ it the Title View! Yeah!
---
.../ViewControllers/AddToPlaylistViewController.cs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Sources/Stylophone.iOS/ViewControllers/AddToPlaylistViewController.cs b/Sources/Stylophone.iOS/ViewControllers/AddToPlaylistViewController.cs
index dca177a..c96149b 100644
--- a/Sources/Stylophone.iOS/ViewControllers/AddToPlaylistViewController.cs
+++ b/Sources/Stylophone.iOS/ViewControllers/AddToPlaylistViewController.cs
@@ -27,7 +27,6 @@ public AddToPlaylistViewController(MPDConnectionService mpdService, bool allowEx
Playlists = new ObservableCollection(mpdService.Playlists);
- Title = Strings.AddToPlaylistTitle;
ModalPresentationStyle = UIModalPresentationStyle.FormSheet;
ModalTransitionStyle = UIModalTransitionStyle.CoverVertical;
@@ -92,7 +91,9 @@ public override void LoadView()
};
if (AllowExistingPlaylists)
- stackView.AddArrangedSubview(playlistSwitch);
+ NavigationItem.TitleView = playlistSwitch;
+ else
+ Title = Strings.AddToPlaylistCreateNewPlaylist;
if (AllowExistingPlaylists)
stackView.AddArrangedSubview(playlistPicker);