diff --git a/Sources/Stylophone.Common/Services/AlbumArtService.cs b/Sources/Stylophone.Common/Services/AlbumArtService.cs
index 7e88da0..0866df0 100644
--- a/Sources/Stylophone.Common/Services/AlbumArtService.cs
+++ b/Sources/Stylophone.Common/Services/AlbumArtService.cs
@@ -91,6 +91,7 @@ public void Stop()
/// MpdFile to check for art
/// True if the art is cached, false otherwise.
public async Task IsAlbumArtCachedAsync(IMpdFile f) => await _applicationStorageService.DoesFileExistAsync(Miscellaneous.GetFileIdentifier(f), "AlbumArt");
+ public async Task IsAlbumArtCachedAsync(string albumName) => await _applicationStorageService.DoesFileExistAsync(albumName, "AlbumArt");
///
/// Queue up an AlbumViewModel for the service to grab its album art.
@@ -224,7 +225,7 @@ private QuantizedColor GetDominantColor(SKBitmap art)
private async Task SaveArtToFileAsync(string fileName, List data) => await _applicationStorageService.SaveDataToFileAsync(fileName, data.ToArray(), "AlbumArt");
- private async Task LoadImageFromFile(string fileName)
+ internal async Task LoadImageFromFile(string fileName)
{
try
{
diff --git a/Sources/Stylophone.Common/Services/MPDConnectionService.cs b/Sources/Stylophone.Common/Services/MPDConnectionService.cs
index 1f6f6db..117af96 100644
--- a/Sources/Stylophone.Common/Services/MPDConnectionService.cs
+++ b/Sources/Stylophone.Common/Services/MPDConnectionService.cs
@@ -88,6 +88,7 @@ public async Task InitializeAsync(bool withRetry = false)
{
System.Diagnostics.Debug.WriteLine($"Error while connecting: {e.Message}");
+ IsConnecting = false;
ConnectionChanged?.Invoke(this, new EventArgs());
if (withRetry && !cancelToken.IsCancellationRequested)
diff --git a/Sources/Stylophone.Common/Stylophone.Common.csproj b/Sources/Stylophone.Common/Stylophone.Common.csproj
index 082c9c6..0c2ffb0 100644
--- a/Sources/Stylophone.Common/Stylophone.Common.csproj
+++ b/Sources/Stylophone.Common/Stylophone.Common.csproj
@@ -7,12 +7,12 @@
-
-
+
+
-
-
-
+
+
+
diff --git a/Sources/Stylophone.Common/ViewModels/Bases/LibraryViewModelBase.cs b/Sources/Stylophone.Common/ViewModels/Bases/LibraryViewModelBase.cs
index 078c979..2d7fec3 100644
--- a/Sources/Stylophone.Common/ViewModels/Bases/LibraryViewModelBase.cs
+++ b/Sources/Stylophone.Common/ViewModels/Bases/LibraryViewModelBase.cs
@@ -13,8 +13,15 @@
namespace Stylophone.Common.ViewModels
{
+
public abstract partial class LibraryViewModelBase : ViewModelBase
{
+ private record Album
+ {
+ public string Name { get; set; }
+ public string SortName { get; set; }
+ }
+
private INavigationService _navigationService;
private MPDConnectionService _mpdService;
private AlbumViewModelFactory _albumVmFactory;
@@ -40,9 +47,13 @@ public async Task LoadDataAsync()
FilteredSource.CollectionChanged += (s, e) => OnPropertyChanged(nameof(IsSourceEmpty));
Source.Clear();
- var response = await _mpdService.SafelySendCommandAsync(new ListCommand(MpdTags.AlbumSort));
+ var albumList = await _mpdService.SafelySendCommandAsync(new ListCommand(MpdTags.Album));
+ var albumSortList = await _mpdService.SafelySendCommandAsync(new ListCommand(MpdTags.AlbumSort));
+
+ // Create a list of tuples
+ var response = albumList.Zip(albumSortList, (album, albumSort) => new Album{ Name = album, SortName = albumSort });
- if (response != null)
+ if (albumSortList != null)
GroupAlbumsByName(response);
if (Source.Count > 0)
@@ -63,10 +74,10 @@ public void FilterLibrary(string text)
AddBack(filtered);
}
- public void GroupAlbumsByName(List albums)
+ private void GroupAlbumsByName(IEnumerable albums)
{
var query = from item in albums
- group item by GetGroupHeader(item) into g
+ group item by GetGroupHeader(item.SortName) into g
orderby g.Key
select new { GroupName = g.Key, Items = g };
@@ -76,9 +87,9 @@ orderby g.Key
//GroupInfosList info = new GroupInfosList();
//info.Key = g.GroupName + " (" + g.Items.Count() + ")";
- foreach (var item in g.Items.OrderBy(s => s.ToLower()))
+ foreach (var item in g.Items.OrderBy(s => s.SortName.ToLower()))
{
- Source.Add(_albumVmFactory.GetAlbumViewModel(item));
+ Source.Add(_albumVmFactory.GetAlbumViewModel(item.Name));
}
}
}
diff --git a/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs b/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs
index 0a85e31..9fa9946 100644
--- a/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs
+++ b/Sources/Stylophone.Common/ViewModels/Items/AlbumViewModel.cs
@@ -9,12 +9,14 @@
using MpcNET.Tags;
using MpcNET.Types;
using SkiaSharp;
+using Stylophone.Common.Helpers;
using Stylophone.Common.Interfaces;
using Stylophone.Common.Services;
using Stylophone.Localization.Strings;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.InteropServices.ComTypes;
using System.Threading.Tasks;
using System.Windows.Input;
@@ -180,6 +182,16 @@ private async Task PlayAlbum()
}
}
+ public async Task LoadAlbumArtFromCacheAsync()
+ {
+ // Try to show album art early if we have it in cache
+ var cacheName = Miscellaneous.EscapeFilename(Name);
+ if (await _albumArtService.IsAlbumArtCachedAsync(cacheName))
+ {
+ AlbumArt = SKImage.FromBitmap(await _albumArtService.LoadImageFromFile(cacheName));
+ }
+ }
+
///
/// Load Album Data. You can either provide a MpcConnection object (for batch loading)
/// or leave as empty to automatically pick up a connection from the datasource.
@@ -196,7 +208,8 @@ public async Task LoadAlbumDataAsync()
public async Task LoadAlbumDataAsync(MpcConnection c)
{
IsDetailLoading = true;
- AlbumArt = await _interop.GetPlaceholderImageAsync();
+ AlbumArt ??= await _interop.GetPlaceholderImageAsync();
+
try
{
var findReq = await c.SendAsync(new FindCommand(MpdTags.Album, Name));
diff --git a/Sources/Stylophone.iOS/Info.plist b/Sources/Stylophone.iOS/Info.plist
index eeebfbe..ca94302 100644
--- a/Sources/Stylophone.iOS/Info.plist
+++ b/Sources/Stylophone.iOS/Info.plist
@@ -16,9 +16,9 @@
zh
CFBundleShortVersionString
- 2.6.0
+ 2.6.1
CFBundleVersion
- 2.6.0
+ 2.6.1
LSRequiresIPhoneOS
MinimumOSVersion
diff --git a/Sources/Stylophone.iOS/Services/NotificationService.cs b/Sources/Stylophone.iOS/Services/NotificationService.cs
index 3e83d5b..1f474e0 100644
--- a/Sources/Stylophone.iOS/Services/NotificationService.cs
+++ b/Sources/Stylophone.iOS/Services/NotificationService.cs
@@ -20,7 +20,7 @@ public override void ShowInAppNotification(InAppNotification notification)
{
// 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();
+ UIApplication.SharedApplication.InvokeOnMainThread(() => alert.Show());
return;
}
diff --git a/Sources/Stylophone.iOS/Stylophone.iOS.csproj b/Sources/Stylophone.iOS/Stylophone.iOS.csproj
index 3889d5c..6277b64 100644
--- a/Sources/Stylophone.iOS/Stylophone.iOS.csproj
+++ b/Sources/Stylophone.iOS/Stylophone.iOS.csproj
@@ -1,6 +1,6 @@
- net7.0-ios
+ net7.0-ios;net7.0-maccatalyst
Exe
enable
true
@@ -61,12 +61,12 @@
-
+
-
+
diff --git a/Sources/Stylophone.iOS/ViewModels/LibraryViewModel.cs b/Sources/Stylophone.iOS/ViewModels/LibraryViewModel.cs
index 6e0c75f..40aa415 100644
--- a/Sources/Stylophone.iOS/ViewModels/LibraryViewModel.cs
+++ b/Sources/Stylophone.iOS/ViewModels/LibraryViewModel.cs
@@ -73,6 +73,13 @@ internal void LoadItems(IEnumerable indexes, CancellationToken token = defa
// Albumart loads still use their own connections.
Task.Run(async () =>
{
+ // Try to show album artwork early if we have it in cache
+ foreach (var i in indexes)
+ {
+ var album = BackingCollection[i];
+ await album.LoadAlbumArtFromCacheAsync();
+ }
+
using (var c = await _mpdService.GetConnectionAsync(token))
foreach (var i in indexes)
{
diff --git a/Sources/Stylophone/Package.appxmanifest b/Sources/Stylophone/Package.appxmanifest
index 16a5808..93e2f24 100644
--- a/Sources/Stylophone/Package.appxmanifest
+++ b/Sources/Stylophone/Package.appxmanifest
@@ -12,7 +12,7 @@
+ Version="2.6.1.0" />
diff --git a/Sources/Stylophone/Package.tt b/Sources/Stylophone/Package.tt
index 9dcdfd2..70ff8db 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.6.0.0";
+ string version = "2.6.2.0";
// Get configuration name at Build time
string configName = Host.ResolveParameterValue("-", "-", "BuildConfiguration");
diff --git a/Sources/Stylophone/Stylophone.csproj b/Sources/Stylophone/Stylophone.csproj
index 0ad7510..89a8705 100644
--- a/Sources/Stylophone/Stylophone.csproj
+++ b/Sources/Stylophone/Stylophone.csproj
@@ -148,22 +148,22 @@
10.1901.28001
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
1.1.0
diff --git a/Sources/Stylophone/ViewModels/LibraryViewModel.cs b/Sources/Stylophone/ViewModels/LibraryViewModel.cs
index c4b6348..c4360c7 100644
--- a/Sources/Stylophone/ViewModels/LibraryViewModel.cs
+++ b/Sources/Stylophone/ViewModels/LibraryViewModel.cs
@@ -59,6 +59,13 @@ public void RangesChanged(ItemIndexRange visibleRange, IReadOnlyList
{
+ // Try to show album artwork early if we have it in cache
+ for (var i = visibleRange.FirstIndex; i < visibleRange.LastIndex + 1; i++) // Increment LastIndex by one to properly cover the visible range
+ {
+ var album = this[i];
+ await album.LoadAlbumArtFromCacheAsync();
+ }
+
using (var c = await _mpdService.GetConnectionAsync(token))
for (var i = visibleRange.FirstIndex; i < visibleRange.LastIndex + 1; i++) // Increment LastIndex by one to properly cover the visible range
{
diff --git a/Sources/Stylophone/Views/ServerQueuePage.xaml b/Sources/Stylophone/Views/ServerQueuePage.xaml
index 093ffc4..fb1b1b5 100644
--- a/Sources/Stylophone/Views/ServerQueuePage.xaml
+++ b/Sources/Stylophone/Views/ServerQueuePage.xaml
@@ -35,7 +35,8 @@
ItemsSource="{x:Bind ViewModel.Source, Mode=OneWay}"
ReorderMode="Enabled"
RightTapped="Select_Item"
- SelectionMode="Extended">
+ SelectionMode="Extended"
+ Visibility="{x:Bind ViewModel.IsSourceEmpty, Mode=OneWay, Converter={StaticResource ReverseBoolToVisibilityConverter}}">