mirror of https://github.com/ErsatzTV/ErsatzTV.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
745 lines
30 KiB
745 lines
30 KiB
@page "/media/trash" |
|
@using ErsatzTV.Application.Maintenance |
|
@using ErsatzTV.Application.MediaCards |
|
@using ErsatzTV.Application.Search |
|
@using ErsatzTV.Extensions |
|
@inherits MultiSelectBase<Search> |
|
@inject NavigationManager NavigationManager |
|
@inject PersistentComponentState ApplicationState |
|
|
|
<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.Error" |
|
StartIcon="@Icons.Material.Filled.Delete" |
|
OnClick="@(_ => DeleteFromDatabase())"> |
|
Delete From Database |
|
</MudButton> |
|
<MudButton Class="ml-3" |
|
Variant="Variant.Filled" |
|
Color="Color.Secondary" |
|
StartIcon="@Icons.Material.Filled.Check" |
|
OnClick="@(_ => ClearSelection())"> |
|
Clear Selection |
|
</MudButton> |
|
</div> |
|
} |
|
else |
|
{ |
|
if (_movies?.Cards.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?.Cards.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?.Cards.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?.Cards.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?.Cards.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?.Cards.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?.Cards.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?.Cards.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?.Cards.Count > 0) |
|
{ |
|
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#images")" Style="margin-bottom: auto; margin-top: auto">@_images.Count Images</MudLink> |
|
} |
|
|
|
if (IsNotEmpty) |
|
{ |
|
<div style="margin-left: auto"> |
|
<MudButton Variant="@Variant.Filled" |
|
Color="@Color.Error" |
|
StartIcon="@Icons.Material.Filled.DeleteForever" |
|
OnClick="@(_ => EmptyTrash())"> |
|
Empty Trash |
|
</MudButton> |
|
</div> |
|
} |
|
else |
|
{ |
|
<MudText>Nothing to see here...</MudText> |
|
} |
|
} |
|
</div> |
|
</MudPaper> |
|
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Style="margin-top: 96px"> |
|
@if (_movies?.Cards.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}")" |
|
DeleteClicked="@DeleteItemFromDatabase" |
|
SelectColor="@Color.Error" |
|
SelectClicked="@(e => SelectClicked(card, e))" |
|
IsSelected="@IsSelected(card)" |
|
IsSelectMode="@IsSelectMode()"/> |
|
} |
|
</MudContainer> |
|
} |
|
|
|
@if (_shows?.Cards.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}")" |
|
DeleteClicked="@DeleteItemFromDatabase" |
|
SelectColor="@Color.Error" |
|
SelectClicked="@(e => SelectClicked(card, e))" |
|
IsSelected="@IsSelected(card)" |
|
IsSelectMode="@IsSelectMode()"/> |
|
} |
|
</MudContainer> |
|
} |
|
|
|
@if (_seasons?.Cards.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}")" |
|
DeleteClicked="@DeleteItemFromDatabase" |
|
SelectColor="@Color.Error" |
|
SelectClicked="@(e => SelectClicked(card, e))" |
|
IsSelected="@IsSelected(card)" |
|
IsSelectMode="@IsSelectMode()"/> |
|
} |
|
</MudContainer> |
|
} |
|
|
|
@if (_episodes?.Cards.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" |
|
DeleteClicked="@DeleteItemFromDatabase" |
|
SelectColor="@Color.Error" |
|
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?.Cards.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" |
|
DeleteClicked="@DeleteItemFromDatabase" |
|
SelectColor="@Color.Error" |
|
SelectClicked="@(e => SelectClicked(card, e))" |
|
IsSelected="@IsSelected(card)" |
|
IsSelectMode="@IsSelectMode()"/> |
|
} |
|
</MudContainer> |
|
} |
|
|
|
@if (_musicVideos?.Cards.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" |
|
DeleteClicked="@DeleteItemFromDatabase" |
|
SelectColor="@Color.Error" |
|
SelectClicked="@(e => SelectClicked(card, e))" |
|
IsSelected="@IsSelected(card)" |
|
IsSelectMode="@IsSelectMode()"/> |
|
} |
|
</MudContainer> |
|
} |
|
|
|
@if (_otherVideos?.Cards.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" |
|
DeleteClicked="@DeleteItemFromDatabase" |
|
SelectColor="@Color.Error" |
|
SelectClicked="@(e => SelectClicked(card, e))" |
|
IsSelected="@IsSelected(card)" |
|
IsSelectMode="@IsSelectMode()"/> |
|
} |
|
</MudContainer> |
|
} |
|
|
|
@if (_songs?.Cards.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" |
|
DeleteClicked="@DeleteItemFromDatabase" |
|
SelectColor="@Color.Error" |
|
SelectClicked="@(e => SelectClicked(card, e))" |
|
IsSelected="@IsSelected(card)" |
|
IsSelectMode="@IsSelectMode()"/> |
|
} |
|
</MudContainer> |
|
} |
|
|
|
@if (_images?.Cards.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" } })"> |
|
Songs |
|
</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" |
|
DeleteClicked="@DeleteItemFromDatabase" |
|
SelectColor="@Color.Error" |
|
SelectClicked="@(e => SelectClicked(card, e))" |
|
IsSelected="@IsSelected(card)" |
|
IsSelectMode="@IsSelectMode()"/> |
|
} |
|
</MudContainer> |
|
} |
|
</MudContainer> |
|
|
|
@code { |
|
private readonly CancellationTokenSource _cts = new(); |
|
|
|
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 void Dispose(bool disposing) |
|
{ |
|
if (disposing) |
|
{ |
|
_persistingSubscription.Dispose(); |
|
|
|
_cts.Cancel(); |
|
_cts.Dispose(); |
|
} |
|
|
|
base.Dispose(disposing); |
|
} |
|
|
|
protected override Task OnInitializedAsync() |
|
{ |
|
_persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData); |
|
return base.OnInitializedAsync(); |
|
} |
|
|
|
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("_images", _images); |
|
ApplicationState.PersistAsJson("_artists", _artists); |
|
|
|
return Task.CompletedTask; |
|
} |
|
|
|
protected override async Task OnParametersSetAsync() |
|
{ |
|
await RefreshData(); |
|
await InvokeAsync(StateHasChanged); |
|
} |
|
|
|
protected override async Task RefreshData() |
|
{ |
|
_query = "state:FileNotFound"; |
|
if (!string.IsNullOrWhiteSpace(_query)) |
|
{ |
|
if (!ApplicationState.TryTakeFromJson("_movies", out _movies)) |
|
{ |
|
_movies = await Mediator.Send(new QuerySearchIndexMovies($"type:movie AND ({_query})", 1, 50), _cts.Token); |
|
} |
|
|
|
if (!ApplicationState.TryTakeFromJson("_shows", out _shows)) |
|
{ |
|
_shows = await Mediator.Send(new QuerySearchIndexShows($"type:show AND ({_query})", 1, 50), _cts.Token); |
|
} |
|
|
|
if (!ApplicationState.TryTakeFromJson("_seasons", out _seasons)) |
|
{ |
|
_seasons = await Mediator.Send(new QuerySearchIndexSeasons($"type:season AND ({_query})", 1, 50), _cts.Token); |
|
} |
|
|
|
if (!ApplicationState.TryTakeFromJson("_episodes", out _episodes)) |
|
{ |
|
_episodes = await Mediator.Send(new QuerySearchIndexEpisodes($"type:episode AND ({_query})", 1, 50), _cts.Token); |
|
} |
|
|
|
if (!ApplicationState.TryTakeFromJson("_musicVideos", out _musicVideos)) |
|
{ |
|
_musicVideos = await Mediator.Send(new QuerySearchIndexMusicVideos($"type:music_video AND ({_query})", 1, 50), _cts.Token); |
|
} |
|
|
|
if (!ApplicationState.TryTakeFromJson("_otherVideos", out _otherVideos)) |
|
{ |
|
_otherVideos = await Mediator.Send(new QuerySearchIndexOtherVideos($"type:other_video AND ({_query})", 1, 50), _cts.Token); |
|
} |
|
|
|
if (!ApplicationState.TryTakeFromJson("_songs", out _songs)) |
|
{ |
|
_songs = await Mediator.Send(new QuerySearchIndexSongs($"type:song AND ({_query})", 1, 50), _cts.Token); |
|
} |
|
|
|
if (!ApplicationState.TryTakeFromJson("_images", out _images)) |
|
{ |
|
_images = await Mediator.Send(new QuerySearchIndexImages($"type:image AND ({_query})", 1, 50), _cts.Token); |
|
} |
|
|
|
if (!ApplicationState.TryTakeFromJson("_artists", out _artists)) |
|
{ |
|
_artists = await Mediator.Send(new QuerySearchIndexArtists($"type:artist AND ({_query})", 1, 50), _cts.Token); |
|
} |
|
} |
|
} |
|
|
|
private bool IsNotEmpty => |
|
_movies?.Cards.Count > 0 || _shows?.Cards.Count > 0 || _seasons?.Cards.Count > 0 || _episodes?.Cards.Count > 0 || _musicVideos?.Cards.Count > 0 || _otherVideos?.Cards.Count > 0 || _songs?.Cards.Count > 0 || _artists?.Cards.Count > 0 || _images?.Cards.Count > 0; |
|
|
|
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)) |
|
.Append(_images.Cards.OrderBy(i => i.SortTitle)) |
|
.ToList(); |
|
} |
|
|
|
SelectClicked(GetSortedItems, card, e); |
|
} |
|
|
|
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 Task DeleteFromDatabase() => DeleteItemsFromDatabase( |
|
SelectedItems.OfType<MovieCardViewModel>().Map(m => m.MovieId).ToList(), |
|
SelectedItems.OfType<TelevisionShowCardViewModel>().Map(s => s.TelevisionShowId).ToList(), |
|
SelectedItems.OfType<TelevisionSeasonCardViewModel>().Map(s => s.TelevisionSeasonId).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(), |
|
SelectedItems.OfType<OtherVideoCardViewModel>().Map(ov => ov.OtherVideoId).ToList(), |
|
SelectedItems.OfType<SongCardViewModel>().Map(s => s.SongId).ToList(), |
|
SelectedItems.OfType<ImageCardViewModel>().Map(i => i.ImageId).ToList()); |
|
|
|
private async Task DeleteItemsFromDatabase( |
|
List<int> movieIds, |
|
List<int> showIds, |
|
List<int> seasonIds, |
|
List<int> episodeIds, |
|
List<int> artistIds, |
|
List<int> musicVideoIds, |
|
List<int> otherVideoIds, |
|
List<int> songIds, |
|
List<int> imageIds, |
|
string entityName = "selected items") |
|
{ |
|
int count = movieIds.Count + showIds.Count + seasonIds.Count + episodeIds.Count + artistIds.Count + |
|
musicVideoIds.Count + otherVideoIds.Count + songIds.Count + imageIds.Count; |
|
|
|
var parameters = new DialogParameters |
|
{ { "EntityType", count.ToString() }, { "EntityName", entityName } }; |
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; |
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<DeleteFromDatabaseDialog>("Delete From Database", parameters, options); |
|
DialogResult result = await dialog.Result; |
|
if (result is { Canceled: false }) |
|
{ |
|
var request = new DeleteItemsFromDatabase( |
|
movieIds.Append(showIds) |
|
.Append(seasonIds) |
|
.Append(episodeIds) |
|
.Append(artistIds) |
|
.Append(musicVideoIds) |
|
.Append(otherVideoIds) |
|
.Append(songIds) |
|
.Append(imageIds) |
|
.ToList()); |
|
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, _cts.Token); |
|
await addResult.Match( |
|
Left: error => |
|
{ |
|
Snackbar.Add($"Unexpected error deleting items from database: {error.Value}"); |
|
Logger.LogError("Unexpected error deleting items from database: {Error}", error.Value); |
|
return Task.CompletedTask; |
|
}, |
|
Right: async _ => |
|
{ |
|
Snackbar.Add($"Deleted {count} items from the database", Severity.Success); |
|
ClearSelection(); |
|
await RefreshData(); |
|
}); |
|
} |
|
} |
|
|
|
private async Task DeleteItemFromDatabase(MediaCardViewModel vm) |
|
{ |
|
DeleteItemsFromDatabase request; |
|
|
|
switch (vm) |
|
{ |
|
case MovieCardViewModel movie: |
|
request = new DeleteItemsFromDatabase(new List<int> { movie.MovieId }); |
|
await DeleteItemsWithConfirmation("movie", $"{movie.Title} ({movie.Subtitle})", request); |
|
break; |
|
case TelevisionShowCardViewModel show: |
|
request = new DeleteItemsFromDatabase(new List<int> { show.TelevisionShowId }); |
|
await DeleteItemsWithConfirmation("show", $"{show.Title} ({show.Subtitle})", request); |
|
break; |
|
case TelevisionSeasonCardViewModel season: |
|
request = new DeleteItemsFromDatabase(new List<int> { season.TelevisionSeasonId }); |
|
await DeleteItemsWithConfirmation("season", $"{season.Title} ({season.Subtitle})", request); |
|
break; |
|
case TelevisionEpisodeCardViewModel episode: |
|
request = new DeleteItemsFromDatabase(new List<int> { episode.EpisodeId }); |
|
await DeleteItemsWithConfirmation("episode", $"{episode.Title} ({episode.Subtitle})", request); |
|
break; |
|
case ArtistCardViewModel artist: |
|
request = new DeleteItemsFromDatabase(new List<int> { artist.ArtistId }); |
|
await DeleteItemsWithConfirmation("artist", $"{artist.Title} ({artist.Subtitle})", request); |
|
break; |
|
case MusicVideoCardViewModel musicVideo: |
|
request = new DeleteItemsFromDatabase(new List<int> { musicVideo.MusicVideoId }); |
|
await DeleteItemsWithConfirmation("music video", $"{musicVideo.Title} ({musicVideo.Subtitle})", request); |
|
break; |
|
case OtherVideoCardViewModel otherVideo: |
|
request = new DeleteItemsFromDatabase(new List<int> { otherVideo.OtherVideoId }); |
|
await DeleteItemsWithConfirmation("other video", $"{otherVideo.Title} ({otherVideo.Subtitle})", request); |
|
break; |
|
case SongCardViewModel song: |
|
request = new DeleteItemsFromDatabase(new List<int> { song.SongId }); |
|
await DeleteItemsWithConfirmation("song", $"{song.Title} ({song.Subtitle})", request); |
|
break; |
|
case ImageCardViewModel image: |
|
request = new DeleteItemsFromDatabase(new List<int> { image.ImageId }); |
|
await DeleteItemsWithConfirmation("image", $"{image.Title} ({image.Subtitle})", request); |
|
break; |
|
} |
|
} |
|
|
|
private async Task DeleteItemsWithConfirmation( |
|
string entityType, |
|
string entityName, |
|
DeleteItemsFromDatabase request) |
|
{ |
|
var parameters = new DialogParameters { { "EntityType", entityType }, { "EntityName", entityName } }; |
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; |
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<DeleteFromDatabaseDialog>("Delete From Database", parameters, options); |
|
DialogResult result = await dialog.Result; |
|
if (result is not null && !result.Canceled) |
|
{ |
|
await Mediator.Send(request, _cts.Token); |
|
await RefreshData(); |
|
} |
|
} |
|
|
|
private async Task EmptyTrash() |
|
{ |
|
int count = _movies.Count + _shows.Count + _seasons.Count + _episodes.Count + _artists.Count + |
|
_musicVideos.Count + _otherVideos.Count + _songs.Count + _images.Count; |
|
|
|
var parameters = new DialogParameters { { "EntityType", count.ToString() }, { "EntityName", "missing items" } }; |
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; |
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<DeleteFromDatabaseDialog>("Delete From Database", parameters, options); |
|
DialogResult result = await dialog.Result; |
|
if (result is not null && !result.Canceled) |
|
{ |
|
Either<BaseError, Unit> emptyTrashResult = await Mediator.Send(new EmptyTrash(), _cts.Token); |
|
foreach (BaseError error in emptyTrashResult.LeftToSeq()) |
|
{ |
|
Snackbar.Add(error.Value, Severity.Error); |
|
Logger.LogError("Unexpected error emptying trash: {Error}", error.Value); |
|
} |
|
|
|
if (emptyTrashResult.IsRight) |
|
{ |
|
await RefreshData(); |
|
await InvokeAsync(StateHasChanged); |
|
} |
|
} |
|
} |
|
|
|
} |