diff --git a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj
index b480672de..8838b8727 100644
--- a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj
+++ b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj
@@ -30,6 +30,7 @@
+
diff --git a/ErsatzTV.Core.Tests/Pages/MediaCardSelectionHelperTests.cs b/ErsatzTV.Core.Tests/Pages/MediaCardSelectionHelperTests.cs
new file mode 100644
index 000000000..c39e911e0
--- /dev/null
+++ b/ErsatzTV.Core.Tests/Pages/MediaCardSelectionHelperTests.cs
@@ -0,0 +1,38 @@
+using ErsatzTV.Application.MediaCards;
+using ErsatzTV.Pages;
+using NUnit.Framework;
+using Shouldly;
+using System.Collections.Generic;
+
+namespace ErsatzTV.Core.Tests.Pages;
+
+[TestFixture]
+public class MediaCardSelectionHelperTests
+{
+ [Test]
+ public void Should_replace_existing_selection_and_return_last_card()
+ {
+ var existingCard = new MediaCardViewModel(1, "Existing", "Sub", "Existing", "", Core.Domain.MediaItemState.Normal, false);
+ var selected = new HashSet { existingCard };
+
+ var first = new MediaCardViewModel(2, "First", "Sub", "First", "", Core.Domain.MediaItemState.Normal, false);
+ var second = new MediaCardViewModel(3, "Second", "Sub", "Second", "", Core.Domain.MediaItemState.Normal, false);
+
+ MediaCardViewModel last = MediaCardSelectionHelper.SelectAllPageItems(selected, new[] { first, second });
+
+ selected.ShouldBe(new[] { first, second }, ignoreOrder: true);
+ last.ShouldBe(second);
+ }
+
+ [Test]
+ public void Should_clear_selection_when_no_cards()
+ {
+ var existingCard = new MediaCardViewModel(1, "Existing", "Sub", "Existing", "", Core.Domain.MediaItemState.Normal, false);
+ var selected = new HashSet { existingCard };
+
+ MediaCardViewModel last = MediaCardSelectionHelper.SelectAllPageItems(selected, []);
+
+ selected.ShouldBeEmpty();
+ last.ShouldBeNull();
+ }
+}
diff --git a/ErsatzTV/Pages/MediaCardSelectionHelper.cs b/ErsatzTV/Pages/MediaCardSelectionHelper.cs
new file mode 100644
index 000000000..d94b11db0
--- /dev/null
+++ b/ErsatzTV/Pages/MediaCardSelectionHelper.cs
@@ -0,0 +1,20 @@
+using ErsatzTV.Application.MediaCards;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ErsatzTV.Pages;
+
+public static class MediaCardSelectionHelper
+{
+ public static MediaCardViewModel SelectAllPageItems(
+ ISet selectedItems,
+ IEnumerable cards)
+ {
+ List cardList = (cards ?? Enumerable.Empty()).ToList();
+
+ selectedItems.Clear();
+ selectedItems.UnionWith(cardList);
+
+ return cardList.LastOrDefault();
+ }
+}
diff --git a/ErsatzTV/Pages/MultiSelectBase.cs b/ErsatzTV/Pages/MultiSelectBase.cs
index e5eb72673..42fdb54f5 100644
--- a/ErsatzTV/Pages/MultiSelectBase.cs
+++ b/ErsatzTV/Pages/MultiSelectBase.cs
@@ -8,6 +8,8 @@ using MediatR;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using MudBlazor;
+using System.Linq;
+using static LanguageExt.Prelude;
namespace ErsatzTV.Pages;
@@ -40,12 +42,8 @@ public class MultiSelectBase : FragmentNavigationBase
protected void SelectAllPageItems(IEnumerable cards)
{
- SelectedItems.Clear();
- foreach (MediaCardViewModel card in cards)
- {
- _recentlySelected = card;
- SelectedItems.Add(card);
- }
+ MediaCardViewModel lastSelected = MediaCardSelectionHelper.SelectAllPageItems(SelectedItems, cards);
+ _recentlySelected = Optional(lastSelected);
StateHasChanged();
}