Files
ersatztv/ErsatzTV/Pages/MultiSelectBase.cs
T
Jason DoveandGitHub e506dd38a8 merge latest develop (#230)
* sync guids/provider ids (#227)

* sync guids from plex

* cleanup

* sync local guids

* sync jellyfin and emby guids

* add episodes to search index (#228)

* sync episode directors and writers

* display episode writers and directors

* remove missing episodes from search index

* show episodes in search results

* fix emby and jellyfin episode updates

* fix updating plex episodes

* don't delete channel logos on startup

* add episodes page; fix adding episodes to collection

* cleanup

* multi-part episode grouping fixes (#229)
2021-05-30 06:08:33 -05:00

174 lines
6.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ErsatzTV.Application.MediaCards;
using ErsatzTV.Application.MediaCollections;
using ErsatzTV.Application.MediaCollections.Commands;
using ErsatzTV.Core;
using ErsatzTV.Shared;
using LanguageExt;
using LanguageExt.UnsafeValueAccess;
using MediatR;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.Logging;
using MudBlazor;
using static LanguageExt.Prelude;
using Unit = LanguageExt.Unit;
namespace ErsatzTV.Pages
{
public class MultiSelectBase<T> : FragmentNavigationBase
{
private readonly System.Collections.Generic.HashSet<MediaCardViewModel> _selectedItems;
private Option<MediaCardViewModel> _recentlySelected;
public MultiSelectBase()
{
_recentlySelected = None;
_selectedItems = new System.Collections.Generic.HashSet<MediaCardViewModel>();
}
[Inject]
protected IDialogService Dialog { get; set; }
[Inject]
protected ISnackbar Snackbar { get; set; }
[Inject]
protected ILogger<T> Logger { get; set; }
[Inject]
protected IMediator Mediator { get; set; }
protected bool IsSelected(MediaCardViewModel card) =>
_selectedItems.Contains(card);
protected bool IsSelectMode() =>
_selectedItems.Any();
protected string SelectionLabel() =>
$"{_selectedItems.Count} {(_selectedItems.Count == 1 ? "Item" : "Items")} Selected";
protected void ClearSelection()
{
_selectedItems.Clear();
_recentlySelected = None;
}
protected virtual Task RefreshData() => Task.CompletedTask;
protected void SelectClicked(
Func<List<MediaCardViewModel>> getSortedItems,
MediaCardViewModel card,
MouseEventArgs e)
{
if (_selectedItems.Contains(card))
{
_selectedItems.Remove(card);
}
else
{
if (e.ShiftKey && _recentlySelected.IsSome)
{
List<MediaCardViewModel> sorted = getSortedItems();
int start = sorted.IndexOf(_recentlySelected.ValueUnsafe());
int finish = sorted.IndexOf(card);
if (start > finish)
{
int temp = start;
start = finish;
finish = temp;
}
for (int i = start; i < finish; i++)
{
_selectedItems.Add(sorted[i]);
}
}
_recentlySelected = card;
_selectedItems.Add(card);
}
}
protected Task AddSelectionToCollection() => AddItemsToCollection(
_selectedItems.OfType<MovieCardViewModel>().Map(m => m.MovieId).ToList(),
_selectedItems.OfType<TelevisionShowCardViewModel>().Map(s => s.TelevisionShowId).ToList(),
_selectedItems.OfType<TelevisionEpisodeCardViewModel>().Map(e => e.EpisodeId).ToList(),
_selectedItems.OfType<ArtistCardViewModel>().Map(a => a.ArtistId).ToList(),
_selectedItems.OfType<MusicVideoCardViewModel>().Map(mv => mv.MusicVideoId).ToList());
protected async Task AddItemsToCollection(
List<int> movieIds,
List<int> showIds,
List<int> episodeIds,
List<int> artistIds,
List<int> musicVideoIds,
string entityName = "selected items")
{
int count = movieIds.Count + showIds.Count + episodeIds.Count + artistIds.Count + musicVideoIds.Count;
var parameters = new DialogParameters
{ { "EntityType", count.ToString() }, { "EntityName", entityName } };
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
IDialogReference dialog = Dialog.Show<AddToCollectionDialog>("Add To Collection", parameters, options);
DialogResult result = await dialog.Result;
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
{
var request = new AddItemsToCollection(
collection.Id,
movieIds,
showIds,
episodeIds,
artistIds,
musicVideoIds);
Either<BaseError, Unit> addResult = await Mediator.Send(request);
addResult.Match(
Left: error =>
{
Snackbar.Add($"Unexpected error adding items to collection: {error.Value}");
Logger.LogError("Unexpected error adding items to collection: {Error}", error.Value);
},
Right: _ =>
{
Snackbar.Add(
$"Added {count} items to collection {collection.Name}",
Severity.Success);
ClearSelection();
});
}
}
protected async Task RemoveSelectionFromCollection(int collectionId)
{
var parameters = new DialogParameters
{ { "EntityType", _selectedItems.Count.ToString() }, { "EntityName", "selected items" } };
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
IDialogReference dialog = Dialog.Show<RemoveFromCollectionDialog>(
"Remove From Collection",
parameters,
options);
DialogResult result = await dialog.Result;
if (!result.Cancelled)
{
var itemIds = _selectedItems.Map(vm => vm.MediaItemId).ToList();
await Mediator.Send(
new RemoveItemsFromCollection(collectionId)
{
MediaItemIds = itemIds
});
await RefreshData();
ClearSelection();
}
}
}
}