859 lines
37 KiB
Plaintext
859 lines
37 KiB
Plaintext
@page "/search"
|
|
@inherits MultiSelectBase<Search>
|
|
@inject NavigationManager NavigationManager
|
|
@inject PersistentComponentState ApplicationState
|
|
@using ErsatzTV.Application.MediaCards
|
|
@using ErsatzTV.Application.MediaCollections
|
|
@using ErsatzTV.Application.Search
|
|
@using ErsatzTV.Extensions
|
|
@implements IDisposable
|
|
|
|
<MudPaper Square="true" Style="display: flex; height: 64px; width: 100%; z-index: 100;">
|
|
<div style="display: flex; flex-direction: row; margin-bottom: auto; margin-top: auto; width: 100%" class="ml-6 mr-6">
|
|
@if (IsSelectMode())
|
|
{
|
|
<MudText Typo="Typo.h6" Color="Color.Primary">@SelectionLabel()</MudText>
|
|
<div style="margin-left: auto">
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Primary"
|
|
StartIcon="@Icons.Material.Filled.Add"
|
|
OnClick="@(_ => AddSelectionToCollection())">
|
|
Add To Collection
|
|
</MudButton>
|
|
<MudButton Class="ml-3"
|
|
Variant="Variant.Filled"
|
|
Color="Color.Primary"
|
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
|
OnClick="@(_ => AddSelectionToPlaylist())">
|
|
Add To Playlist
|
|
</MudButton>
|
|
<MudButton Class="ml-3"
|
|
Variant="Variant.Filled"
|
|
Color="Color.Secondary"
|
|
StartIcon="@Icons.Material.Filled.Check"
|
|
OnClick="@(_ => ClearSelection())">
|
|
Clear Selection
|
|
</MudButton>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div style="align-items: center; display: flex; width: 100%" class="d-none d-md-flex">
|
|
<MudText Style="margin-bottom: auto; margin-top: auto">@_query</MudText>
|
|
@if (_movies?.Count > 0)
|
|
{
|
|
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#movies")" Style="margin-bottom: auto; margin-top: auto">@_movies.Count Movies</MudLink>
|
|
}
|
|
|
|
@if (_shows?.Count > 0)
|
|
{
|
|
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#shows")" Style="margin-bottom: auto; margin-top: auto">@_shows.Count Shows</MudLink>
|
|
}
|
|
|
|
@if (_seasons?.Count > 0)
|
|
{
|
|
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#seasons")" Style="margin-bottom: auto; margin-top: auto">@_seasons.Count Seasons</MudLink>
|
|
}
|
|
|
|
@if (_episodes?.Count > 0)
|
|
{
|
|
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#episodes")" Style="margin-bottom: auto; margin-top: auto">@_episodes.Count Episodes</MudLink>
|
|
}
|
|
|
|
@if (_artists?.Count > 0)
|
|
{
|
|
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#artists")" Style="margin-bottom: auto; margin-top: auto">@_artists.Count Artists</MudLink>
|
|
}
|
|
|
|
@if (_musicVideos?.Count > 0)
|
|
{
|
|
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#music_videos")" Style="margin-bottom: auto; margin-top: auto">@_musicVideos.Count Music Videos</MudLink>
|
|
}
|
|
|
|
@if (_otherVideos?.Count > 0)
|
|
{
|
|
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#other_videos")" Style="margin-bottom: auto; margin-top: auto">@_otherVideos.Count Other Videos</MudLink>
|
|
}
|
|
|
|
@if (_songs?.Count > 0)
|
|
{
|
|
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#songs")" Style="margin-bottom: auto; margin-top: auto">@_songs.Count Songs</MudLink>
|
|
}
|
|
|
|
@if (_images?.Count > 0)
|
|
{
|
|
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#images")" Style="margin-bottom: auto; margin-top: auto">@_images.Count Images</MudLink>
|
|
}
|
|
<div class="flex-grow-1 d-none d-md-flex"></div>
|
|
<div>
|
|
<MudTooltip Text="Add All To Collection">
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Primary"
|
|
StartIcon="@Icons.Material.Filled.Add"
|
|
OnClick="@AddAllToCollection">
|
|
Add All
|
|
</MudButton>
|
|
</MudTooltip>
|
|
<MudTooltip Text="Add All To Playlist">
|
|
<MudButton Class="ml-3"
|
|
Variant="Variant.Filled"
|
|
Color="Color.Primary"
|
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
|
OnClick="@AddAllToPlaylist">
|
|
Add All
|
|
</MudButton>
|
|
</MudTooltip>
|
|
<MudTooltip Text="Save As Smart Collection">
|
|
<MudButton Class="ml-3" Variant="Variant.Filled"
|
|
Color="Color.Secondary"
|
|
StartIcon="@Icons.Material.Filled.Save"
|
|
OnClick="@SaveAsSmartCollection">
|
|
Save As
|
|
</MudButton>
|
|
</MudTooltip>
|
|
</div>
|
|
</div>
|
|
<div style="align-items: center; display: flex; width: 100%" class="d-md-none">
|
|
<div class="flex-grow-1"></div>
|
|
<MudMenu Icon="@Icons.Material.Filled.MoreVert">
|
|
<MudMenuItem Icon="@Icons.Material.Filled.Add" Label="Add All To Collection" OnClick="@AddAllToCollection"/>
|
|
<MudMenuItem Icon="@Icons.Material.Filled.PlaylistAdd" Label="Add All To Playlist" OnClick="AddAllToPlaylist"/>
|
|
<MudMenuItem Icon="@Icons.Material.Filled.Save" Label="Save As Smart Collection" OnClick="SaveAsSmartCollection"/>
|
|
</MudMenu>
|
|
</div>
|
|
}
|
|
</div>
|
|
</MudPaper>
|
|
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Style="margin-top: 96px">
|
|
@if (_movies?.Count > 0)
|
|
{
|
|
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
|
|
<MudText Typo="Typo.h4"
|
|
Style="scroll-margin-top: 160px"
|
|
UserAttributes="@(new Dictionary<string, object> { { "id", "movies" } })">
|
|
Movies
|
|
</MudText>
|
|
@if (_movies.Count > 50)
|
|
{
|
|
<MudLink Href="@GetMoviesLink()" Class="ml-4">See All >></MudLink>
|
|
}
|
|
</div>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.False" Class="media-card-grid">
|
|
@foreach (MovieCardViewModel card in _movies.Cards.OrderBy(m => m.SortTitle))
|
|
{
|
|
<MediaCard Data="@card"
|
|
Href="@($"media/movies/{card.MovieId}")"
|
|
AddToCollectionClicked="@AddToCollection"
|
|
SelectClicked="@(e => SelectClicked(card, e))"
|
|
IsSelected="@IsSelected(card)"
|
|
IsSelectMode="@IsSelectMode()"/>
|
|
}
|
|
</MudContainer>
|
|
}
|
|
|
|
@if (_shows?.Count > 0)
|
|
{
|
|
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
|
|
<MudText Typo="Typo.h4"
|
|
Style="scroll-margin-top: 160px"
|
|
UserAttributes="@(new Dictionary<string, object> { { "id", "shows" } })">
|
|
Shows
|
|
</MudText>
|
|
@if (_shows.Count > 50)
|
|
{
|
|
<MudLink Href="@GetShowsLink()" Class="ml-4">See All >></MudLink>
|
|
}
|
|
</div>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.False" Class="media-card-grid">
|
|
@foreach (TelevisionShowCardViewModel card in _shows.Cards.OrderBy(s => s.SortTitle))
|
|
{
|
|
<MediaCard Data="@card"
|
|
Href="@($"media/tv/shows/{card.TelevisionShowId}")"
|
|
AddToCollectionClicked="@AddToCollection"
|
|
SelectClicked="@(e => SelectClicked(card, e))"
|
|
IsSelected="@IsSelected(card)"
|
|
IsSelectMode="@IsSelectMode()"/>
|
|
}
|
|
</MudContainer>
|
|
}
|
|
|
|
@if (_seasons?.Count > 0)
|
|
{
|
|
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
|
|
<MudText Typo="Typo.h4"
|
|
Style="scroll-margin-top: 160px"
|
|
UserAttributes="@(new Dictionary<string, object> { { "id", "seasons" } })">
|
|
Seasons
|
|
</MudText>
|
|
@if (_seasons.Count > 50)
|
|
{
|
|
<MudLink Href="@GetSeasonsLink()" Class="ml-4">See All >></MudLink>
|
|
}
|
|
</div>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.False" Class="media-card-grid">
|
|
@foreach (TelevisionSeasonCardViewModel card in _seasons.Cards.OrderBy(s => s.SortTitle))
|
|
{
|
|
<MediaCard Data="@card"
|
|
Href="@($"media/tv/seasons/{card.TelevisionSeasonId}")"
|
|
AddToCollectionClicked="@AddToCollection"
|
|
SelectClicked="@(e => SelectClicked(card, e))"
|
|
IsSelected="@IsSelected(card)"
|
|
IsSelectMode="@IsSelectMode()"/>
|
|
}
|
|
</MudContainer>
|
|
}
|
|
|
|
@if (_episodes?.Count > 0)
|
|
{
|
|
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
|
|
<MudText Typo="Typo.h4"
|
|
Style="scroll-margin-top: 160px"
|
|
UserAttributes="@(new Dictionary<string, object> { { "id", "episodes" } })">
|
|
Episodes
|
|
</MudText>
|
|
@if (_episodes.Count > 50)
|
|
{
|
|
<MudLink Href="@GetEpisodesLink()" Class="ml-4">See All >></MudLink>
|
|
}
|
|
</div>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.False" Class="media-card-grid">
|
|
@foreach (TelevisionEpisodeCardViewModel card in _episodes.Cards.OrderBy(s => s.SortTitle))
|
|
{
|
|
<MediaCard Data="@card"
|
|
AddToCollectionClicked="@AddToCollection"
|
|
Href="@($"media/tv/seasons/{card.SeasonId}#episode-{card.EpisodeId}")"
|
|
Subtitle="@($"{card.ShowTitle} - S{card.Season} E{card.Episode}")"
|
|
SelectClicked="@(e => SelectClicked(card, e))"
|
|
IsSelected="@IsSelected(card)"
|
|
IsSelectMode="@IsSelectMode()"/>
|
|
}
|
|
</MudContainer>
|
|
}
|
|
|
|
@if (_artists?.Count > 0)
|
|
{
|
|
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
|
|
<MudText Typo="Typo.h4"
|
|
Style="scroll-margin-top: 160px"
|
|
UserAttributes="@(new Dictionary<string, object> { { "id", "artists" } })">
|
|
Artists
|
|
</MudText>
|
|
@if (_artists.Count > 50)
|
|
{
|
|
<MudLink Href="@GetArtistsLink()" Class="ml-4">See All >></MudLink>
|
|
}
|
|
</div>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.False" Class="media-card-grid">
|
|
@foreach (ArtistCardViewModel card in _artists.Cards.OrderBy(s => s.SortTitle))
|
|
{
|
|
<MediaCard Data="@card"
|
|
Href="@($"media/music/artists/{card.ArtistId}")"
|
|
ArtworkKind="ArtworkKind.Thumbnail"
|
|
AddToCollectionClicked="@AddToCollection"
|
|
SelectClicked="@(e => SelectClicked(card, e))"
|
|
IsSelected="@IsSelected(card)"
|
|
IsSelectMode="@IsSelectMode()"/>
|
|
}
|
|
</MudContainer>
|
|
}
|
|
|
|
@if (_musicVideos?.Count > 0)
|
|
{
|
|
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
|
|
<MudText Typo="Typo.h4"
|
|
Style="scroll-margin-top: 160px"
|
|
UserAttributes="@(new Dictionary<string, object> { { "id", "music_videos" } })">
|
|
Music Videos
|
|
</MudText>
|
|
@if (_musicVideos.Count > 50)
|
|
{
|
|
<MudLink Href="@GetMusicVideosLink()" Class="ml-4">See All >></MudLink>
|
|
}
|
|
</div>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.False" Class="media-card-grid">
|
|
@foreach (MusicVideoCardViewModel card in _musicVideos.Cards.OrderBy(s => s.SortTitle))
|
|
{
|
|
<MediaCard Data="@card"
|
|
Href=""
|
|
ArtworkKind="ArtworkKind.Thumbnail"
|
|
AddToCollectionClicked="@AddToCollection"
|
|
SelectClicked="@(e => SelectClicked(card, e))"
|
|
IsSelected="@IsSelected(card)"
|
|
IsSelectMode="@IsSelectMode()"/>
|
|
}
|
|
</MudContainer>
|
|
}
|
|
|
|
@if (_otherVideos?.Count > 0)
|
|
{
|
|
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
|
|
<MudText Typo="Typo.h4"
|
|
Style="scroll-margin-top: 160px"
|
|
UserAttributes="@(new Dictionary<string, object> { { "id", "other_videos" } })">
|
|
Other Videos
|
|
</MudText>
|
|
@if (_otherVideos.Count > 50)
|
|
{
|
|
<MudLink Href="@GetOtherVideosLink()" Class="ml-4">See All >></MudLink>
|
|
}
|
|
</div>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.False" Class="media-card-grid">
|
|
@foreach (OtherVideoCardViewModel card in _otherVideos.Cards.OrderBy(s => s.SortTitle))
|
|
{
|
|
<MediaCard Data="@card"
|
|
Href=""
|
|
ArtworkKind="ArtworkKind.Thumbnail"
|
|
AddToCollectionClicked="@AddToCollection"
|
|
SelectClicked="@(e => SelectClicked(card, e))"
|
|
IsSelected="@IsSelected(card)"
|
|
IsSelectMode="@IsSelectMode()"/>
|
|
}
|
|
</MudContainer>
|
|
}
|
|
|
|
@if (_songs?.Count > 0)
|
|
{
|
|
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
|
|
<MudText Typo="Typo.h4"
|
|
Style="scroll-margin-top: 160px"
|
|
UserAttributes="@(new Dictionary<string, object> { { "id", "songs" } })">
|
|
Songs
|
|
</MudText>
|
|
@if (_songs.Count > 50)
|
|
{
|
|
<MudLink Href="@GetSongsLink()" Class="ml-4">See All >></MudLink>
|
|
}
|
|
</div>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.False" Class="media-card-grid">
|
|
@foreach (SongCardViewModel card in _songs.Cards.OrderBy(s => s.SortTitle))
|
|
{
|
|
<MediaCard Data="@card"
|
|
Href=""
|
|
ArtworkKind="ArtworkKind.Thumbnail"
|
|
AddToCollectionClicked="@AddToCollection"
|
|
SelectClicked="@(e => SelectClicked(card, e))"
|
|
IsSelected="@IsSelected(card)"
|
|
IsSelectMode="@IsSelectMode()"/>
|
|
}
|
|
</MudContainer>
|
|
}
|
|
|
|
@if (_images?.Count > 0)
|
|
{
|
|
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
|
|
<MudText Typo="Typo.h4"
|
|
Style="scroll-margin-top: 160px"
|
|
UserAttributes="@(new Dictionary<string, object> { { "id", "images" } })">
|
|
Images
|
|
</MudText>
|
|
@if (_images.Count > 50)
|
|
{
|
|
<MudLink Href="@GetImagesLink()" Class="ml-4">See All >></MudLink>
|
|
}
|
|
</div>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.False" Class="media-card-grid">
|
|
@foreach (ImageCardViewModel card in _images.Cards.OrderBy(s => s.SortTitle))
|
|
{
|
|
<MediaCard Data="@card"
|
|
Href=""
|
|
ArtworkKind="ArtworkKind.Thumbnail"
|
|
AddToCollectionClicked="@AddToCollection"
|
|
SelectClicked="@(e => SelectClicked(card, e))"
|
|
IsSelected="@IsSelected(card)"
|
|
IsSelectMode="@IsSelectMode()"/>
|
|
}
|
|
</MudContainer>
|
|
}
|
|
</MudContainer>
|
|
|
|
@code {
|
|
private string _query;
|
|
private MovieCardResultsViewModel _movies;
|
|
private TelevisionShowCardResultsViewModel _shows;
|
|
private TelevisionSeasonCardResultsViewModel _seasons;
|
|
private TelevisionEpisodeCardResultsViewModel _episodes;
|
|
private MusicVideoCardResultsViewModel _musicVideos;
|
|
private OtherVideoCardResultsViewModel _otherVideos;
|
|
private SongCardResultsViewModel _songs;
|
|
private ImageCardResultsViewModel _images;
|
|
private ArtistCardResultsViewModel _artists;
|
|
private PersistingComponentStateSubscription _persistingSubscription;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
_persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
|
|
|
|
_query = NavigationManager.Uri.GetSearchQuery();
|
|
if (!string.IsNullOrWhiteSpace(_query))
|
|
{
|
|
if (!ApplicationState.TryTakeFromJson("_movies", out MovieCardResultsViewModel restoredMovies))
|
|
{
|
|
_movies = await Mediator.Send(new QuerySearchIndexMovies($"type:movie AND ({_query})", 1, 50), CancellationToken);
|
|
}
|
|
else
|
|
{
|
|
_movies = restoredMovies;
|
|
}
|
|
|
|
if (!ApplicationState.TryTakeFromJson("_shows", out TelevisionShowCardResultsViewModel restoredShows))
|
|
{
|
|
_shows = await Mediator.Send(new QuerySearchIndexShows($"type:show AND ({_query})", 1, 50), CancellationToken);
|
|
}
|
|
else
|
|
{
|
|
_shows = restoredShows;
|
|
}
|
|
|
|
if (!ApplicationState.TryTakeFromJson("_seasons", out TelevisionSeasonCardResultsViewModel restoredSeasons))
|
|
{
|
|
_seasons = await Mediator.Send(new QuerySearchIndexSeasons($"type:season AND ({_query})", 1, 50), CancellationToken);
|
|
}
|
|
else
|
|
{
|
|
_seasons = restoredSeasons;
|
|
}
|
|
|
|
if (!ApplicationState.TryTakeFromJson("_episodes", out TelevisionEpisodeCardResultsViewModel restoredEpisodes))
|
|
{
|
|
_episodes = await Mediator.Send(new QuerySearchIndexEpisodes($"type:episode AND ({_query})", 1, 50), CancellationToken);
|
|
}
|
|
else
|
|
{
|
|
_episodes = restoredEpisodes;
|
|
}
|
|
|
|
if (!ApplicationState.TryTakeFromJson("_musicVideos", out MusicVideoCardResultsViewModel restoredMusicVideos))
|
|
{
|
|
_musicVideos = await Mediator.Send(new QuerySearchIndexMusicVideos($"type:music_video AND ({_query})", 1, 50), CancellationToken);
|
|
}
|
|
else
|
|
{
|
|
_musicVideos = restoredMusicVideos;
|
|
}
|
|
|
|
if (!ApplicationState.TryTakeFromJson("_otherVideos", out OtherVideoCardResultsViewModel restoredOtherVideos))
|
|
{
|
|
_otherVideos = await Mediator.Send(new QuerySearchIndexOtherVideos($"type:other_video AND ({_query})", 1, 50), CancellationToken);
|
|
}
|
|
else
|
|
{
|
|
_otherVideos = restoredOtherVideos;
|
|
}
|
|
|
|
if (!ApplicationState.TryTakeFromJson("_songs", out SongCardResultsViewModel restoredSongs))
|
|
{
|
|
_songs = await Mediator.Send(new QuerySearchIndexSongs($"type:song AND ({_query})", 1, 50), CancellationToken);
|
|
}
|
|
else
|
|
{
|
|
_songs = restoredSongs;
|
|
}
|
|
|
|
if (!ApplicationState.TryTakeFromJson("_images", out ImageCardResultsViewModel restoredImages))
|
|
{
|
|
_images = await Mediator.Send(new QuerySearchIndexImages($"type:image AND ({_query})", 1, 50), CancellationToken);
|
|
}
|
|
else
|
|
{
|
|
_images = restoredImages;
|
|
}
|
|
|
|
if (!ApplicationState.TryTakeFromJson("_artists", out ArtistCardResultsViewModel restoredArtists))
|
|
{
|
|
_artists = await Mediator.Send(new QuerySearchIndexArtists($"type:artist AND ({_query})", 1, 50), CancellationToken);
|
|
}
|
|
else
|
|
{
|
|
_artists = restoredArtists;
|
|
}
|
|
}
|
|
}
|
|
|
|
private Task PersistData()
|
|
{
|
|
ApplicationState.PersistAsJson("_movies", _movies);
|
|
ApplicationState.PersistAsJson("_shows", _shows);
|
|
ApplicationState.PersistAsJson("_seasons", _seasons);
|
|
ApplicationState.PersistAsJson("_episodes", _episodes);
|
|
ApplicationState.PersistAsJson("_musicVideos", _musicVideos);
|
|
ApplicationState.PersistAsJson("_otherVideos", _otherVideos);
|
|
ApplicationState.PersistAsJson("_songs", _songs);
|
|
ApplicationState.PersistAsJson("_artists", _artists);
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
void IDisposable.Dispose()
|
|
{
|
|
_persistingSubscription.Dispose();
|
|
base.Dispose();
|
|
}
|
|
|
|
private void SelectClicked(MediaCardViewModel card, MouseEventArgs e)
|
|
{
|
|
List<MediaCardViewModel> GetSortedItems()
|
|
{
|
|
return _movies.Cards.OrderBy(m => m.SortTitle)
|
|
.Append<MediaCardViewModel>(_shows.Cards.OrderBy(s => s.SortTitle))
|
|
.Append(_seasons.Cards.OrderBy(s => s.SortTitle))
|
|
.Append(_episodes.Cards.OrderBy(ep => ep.SortTitle))
|
|
.Append(_artists.Cards.OrderBy(a => a.SortTitle))
|
|
.Append(_musicVideos.Cards.OrderBy(mv => mv.SortTitle))
|
|
.Append(_otherVideos.Cards.OrderBy(ov => ov.SortTitle))
|
|
.Append(_songs.Cards.OrderBy(ov => ov.SortTitle))
|
|
.ToList();
|
|
}
|
|
|
|
SelectClicked(GetSortedItems, card, e);
|
|
}
|
|
|
|
private async Task AddToCollection(MediaCardViewModel card)
|
|
{
|
|
if (card is MovieCardViewModel movie)
|
|
{
|
|
var parameters = new DialogParameters { { "EntityType", "movie" }, { "EntityName", movie.Title } };
|
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options);
|
|
DialogResult result = await dialog.Result;
|
|
if (!result.Canceled && result.Data is MediaCollectionViewModel collection)
|
|
{
|
|
var request = new AddMovieToCollection(collection.Id, movie.MovieId);
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
|
addResult.Match(
|
|
Left: error =>
|
|
{
|
|
Snackbar.Add($"Unexpected error adding movie to collection: {error.Value}");
|
|
Logger.LogError("Unexpected error adding movie to collection: {Error}", error.Value);
|
|
},
|
|
Right: _ => Snackbar.Add($"Added {movie.Title} to collection {collection.Name}", Severity.Success));
|
|
}
|
|
}
|
|
|
|
if (card is TelevisionShowCardViewModel show)
|
|
{
|
|
var parameters = new DialogParameters { { "EntityType", "show" }, { "EntityName", show.Title } };
|
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options);
|
|
DialogResult result = await dialog.Result;
|
|
if (!result.Canceled && result.Data is MediaCollectionViewModel collection)
|
|
{
|
|
var request = new AddShowToCollection(collection.Id, show.TelevisionShowId);
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
|
addResult.Match(
|
|
Left: error =>
|
|
{
|
|
Snackbar.Add($"Unexpected error adding show to collection: {error.Value}");
|
|
Logger.LogError("Unexpected error adding show to collection: {Error}", error.Value);
|
|
},
|
|
Right: _ => Snackbar.Add($"Added {show.Title} to collection {collection.Name}", Severity.Success));
|
|
}
|
|
}
|
|
|
|
if (card is TelevisionEpisodeCardViewModel episode)
|
|
{
|
|
var parameters = new DialogParameters { { "EntityType", "episode" }, { "EntityName", episode.Title } };
|
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options);
|
|
DialogResult result = await dialog.Result;
|
|
if (!result.Canceled && result.Data is MediaCollectionViewModel collection)
|
|
{
|
|
var request = new AddEpisodeToCollection(collection.Id, episode.EpisodeId);
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
|
addResult.Match(
|
|
Left: error =>
|
|
{
|
|
Snackbar.Add($"Unexpected error adding episode to collection: {error.Value}");
|
|
Logger.LogError("Unexpected error adding episode to collection: {Error}", error.Value);
|
|
},
|
|
Right: _ => Snackbar.Add($"Added {episode.Title} to collection {collection.Name}", Severity.Success));
|
|
}
|
|
}
|
|
|
|
if (card is ArtistCardViewModel artist)
|
|
{
|
|
var parameters = new DialogParameters { { "EntityType", "artist" }, { "EntityName", artist.Title } };
|
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options);
|
|
DialogResult result = await dialog.Result;
|
|
if (!result.Canceled && result.Data is MediaCollectionViewModel collection)
|
|
{
|
|
var request = new AddArtistToCollection(collection.Id, artist.ArtistId);
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
|
addResult.Match(
|
|
Left: error =>
|
|
{
|
|
Snackbar.Add($"Unexpected error adding artist to collection: {error.Value}");
|
|
Logger.LogError("Unexpected error adding artist to collection: {Error}", error.Value);
|
|
},
|
|
Right: _ => Snackbar.Add($"Added {artist.Title} to collection {collection.Name}", Severity.Success));
|
|
}
|
|
}
|
|
|
|
if (card is MusicVideoCardViewModel musicVideo)
|
|
{
|
|
var parameters = new DialogParameters { { "EntityType", "music video" }, { "EntityName", musicVideo.Title } };
|
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options);
|
|
DialogResult result = await dialog.Result;
|
|
if (!result.Canceled && result.Data is MediaCollectionViewModel collection)
|
|
{
|
|
var request = new AddMusicVideoToCollection(collection.Id, musicVideo.MusicVideoId);
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
|
addResult.Match(
|
|
Left: error =>
|
|
{
|
|
Snackbar.Add($"Unexpected error adding music video to collection: {error.Value}");
|
|
Logger.LogError("Unexpected error adding music video to collection: {Error}", error.Value);
|
|
},
|
|
Right: _ => Snackbar.Add($"Added {musicVideo.Title} to collection {collection.Name}", Severity.Success));
|
|
}
|
|
}
|
|
|
|
if (card is OtherVideoCardViewModel otherVideo)
|
|
{
|
|
var parameters = new DialogParameters { { "EntityType", "other video" }, { "EntityName", otherVideo.Title } };
|
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options);
|
|
DialogResult result = await dialog.Result;
|
|
if (!result.Canceled && result.Data is MediaCollectionViewModel collection)
|
|
{
|
|
var request = new AddOtherVideoToCollection(collection.Id, otherVideo.OtherVideoId);
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
|
addResult.Match(
|
|
Left: error =>
|
|
{
|
|
Snackbar.Add($"Unexpected error adding other video to collection: {error.Value}");
|
|
Logger.LogError("Unexpected error adding other video to collection: {Error}", error.Value);
|
|
},
|
|
Right: _ => Snackbar.Add($"Added {otherVideo.Title} to collection {collection.Name}", Severity.Success));
|
|
}
|
|
}
|
|
|
|
if (card is SongCardViewModel song)
|
|
{
|
|
var parameters = new DialogParameters { { "EntityType", "song" }, { "EntityName", song.Title } };
|
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options);
|
|
DialogResult result = await dialog.Result;
|
|
if (!result.Canceled && result.Data is MediaCollectionViewModel collection)
|
|
{
|
|
var request = new AddSongToCollection(collection.Id, song.SongId);
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
|
addResult.Match(
|
|
Left: error =>
|
|
{
|
|
Snackbar.Add($"Unexpected error adding song to collection: {error.Value}");
|
|
Logger.LogError("Unexpected error adding song to collection: {Error}", error.Value);
|
|
},
|
|
Right: _ => Snackbar.Add($"Added {song.Title} to collection {collection.Name}", Severity.Success));
|
|
}
|
|
}
|
|
|
|
if (card is ImageCardViewModel image)
|
|
{
|
|
var parameters = new DialogParameters { { "EntityType", "image" }, { "EntityName", image.Title } };
|
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options);
|
|
DialogResult result = await dialog.Result;
|
|
if (result is { Canceled: false, Data: MediaCollectionViewModel collection })
|
|
{
|
|
var request = new AddImageToCollection(collection.Id, image.ImageId);
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
|
addResult.Match(
|
|
Left: error =>
|
|
{
|
|
Snackbar.Add($"Unexpected error adding image to collection: {error.Value}");
|
|
Logger.LogError("Unexpected error adding image to collection: {Error}", error.Value);
|
|
},
|
|
Right: _ => Snackbar.Add($"Added {image.Title} to collection {collection.Name}", Severity.Success));
|
|
}
|
|
}
|
|
}
|
|
|
|
private string GetMoviesLink()
|
|
{
|
|
var uri = "media/movies/page/1";
|
|
if (!string.IsNullOrWhiteSpace(_query))
|
|
{
|
|
(string key, string value) = _query.EncodeQuery();
|
|
uri = $"{uri}?{key}={value}";
|
|
}
|
|
|
|
return uri;
|
|
}
|
|
|
|
private string GetShowsLink()
|
|
{
|
|
var uri = "media/tv/shows/page/1";
|
|
if (!string.IsNullOrWhiteSpace(_query))
|
|
{
|
|
(string key, string value) = _query.EncodeQuery();
|
|
uri = $"{uri}?{key}={value}";
|
|
}
|
|
|
|
return uri;
|
|
}
|
|
|
|
private string GetSeasonsLink()
|
|
{
|
|
var uri = "media/tv/seasons/page/1";
|
|
if (!string.IsNullOrWhiteSpace(_query))
|
|
{
|
|
(string key, string value) = _query.EncodeQuery();
|
|
uri = $"{uri}?{key}={value}";
|
|
}
|
|
|
|
return uri;
|
|
}
|
|
|
|
private string GetEpisodesLink()
|
|
{
|
|
var uri = "media/tv/episodes/page/1";
|
|
if (!string.IsNullOrWhiteSpace(_query))
|
|
{
|
|
(string key, string value) = _query.EncodeQuery();
|
|
uri = $"{uri}?{key}={value}";
|
|
}
|
|
|
|
return uri;
|
|
}
|
|
|
|
private string GetArtistsLink()
|
|
{
|
|
var uri = "media/music/artists/page/1";
|
|
if (!string.IsNullOrWhiteSpace(_query))
|
|
{
|
|
(string key, string value) = _query.EncodeQuery();
|
|
uri = $"{uri}?{key}={value}";
|
|
}
|
|
|
|
return uri;
|
|
}
|
|
|
|
private string GetMusicVideosLink()
|
|
{
|
|
var uri = "media/music/videos/page/1";
|
|
if (!string.IsNullOrWhiteSpace(_query))
|
|
{
|
|
(string key, string value) = _query.EncodeQuery();
|
|
uri = $"{uri}?{key}={value}";
|
|
}
|
|
|
|
return uri;
|
|
}
|
|
|
|
private string GetOtherVideosLink()
|
|
{
|
|
var uri = "media/other/videos/page/1";
|
|
if (!string.IsNullOrWhiteSpace(_query))
|
|
{
|
|
(string key, string value) = _query.EncodeQuery();
|
|
uri = $"{uri}?{key}={value}";
|
|
}
|
|
|
|
return uri;
|
|
}
|
|
|
|
private string GetSongsLink()
|
|
{
|
|
var uri = "media/music/songs/page/1";
|
|
if (!string.IsNullOrWhiteSpace(_query))
|
|
{
|
|
(string key, string value) = _query.EncodeQuery();
|
|
uri = $"{uri}?{key}={value}";
|
|
}
|
|
|
|
return uri;
|
|
}
|
|
|
|
private string GetImagesLink()
|
|
{
|
|
var uri = "media/images/page/1";
|
|
if (!string.IsNullOrWhiteSpace(_query))
|
|
{
|
|
(string key, string value) = _query.EncodeQuery();
|
|
uri = $"{uri}?{key}={value}";
|
|
}
|
|
|
|
return uri;
|
|
}
|
|
|
|
private async Task AddAllToCollection(MouseEventArgs _)
|
|
{
|
|
SearchResultAllItemsViewModel results = await Mediator.Send(new QuerySearchIndexAllItems(_query), CancellationToken);
|
|
await AddItemsToCollection(
|
|
results.MovieIds,
|
|
results.ShowIds,
|
|
results.SeasonIds,
|
|
results.EpisodeIds,
|
|
results.ArtistIds,
|
|
results.MusicVideoIds,
|
|
results.OtherVideoIds,
|
|
results.SongIds,
|
|
results.ImageIds,
|
|
"search results");
|
|
}
|
|
|
|
private async Task AddAllToPlaylist(MouseEventArgs _)
|
|
{
|
|
SearchResultAllItemsViewModel results = await Mediator.Send(new QuerySearchIndexAllItems(_query), CancellationToken);
|
|
await AddItemsToPlaylist(
|
|
results.MovieIds,
|
|
results.ShowIds,
|
|
results.SeasonIds,
|
|
results.EpisodeIds,
|
|
results.ArtistIds,
|
|
results.MusicVideoIds,
|
|
results.OtherVideoIds,
|
|
results.SongIds,
|
|
results.ImageIds,
|
|
"search results");
|
|
}
|
|
|
|
private async Task SaveAsSmartCollection(MouseEventArgs _)
|
|
{
|
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<SaveAsSmartCollectionDialog>("Save As Smart Collection", options);
|
|
DialogResult result = await dialog.Result;
|
|
if (!result.Canceled && result.Data is SmartCollectionViewModel collection)
|
|
{
|
|
var request = new UpdateSmartCollection(
|
|
collection.Id,
|
|
_query);
|
|
|
|
Either<BaseError, Unit> updateResult = await Mediator.Send(request, CancellationToken);
|
|
updateResult.Match(
|
|
Left: error =>
|
|
{
|
|
Snackbar.Add($"Unexpected error saving smart collection: {error.Value}");
|
|
Logger.LogError("Unexpected error saving smart collection: {Error}", error.Value);
|
|
},
|
|
Right: _ =>
|
|
{
|
|
Snackbar.Add(
|
|
$"Saved smart collection {collection.Name}",
|
|
Severity.Success);
|
|
ClearSelection();
|
|
});
|
|
}
|
|
}
|
|
|
|
} |