diff --git a/ErsatzTV.Application/MediaCards/Mapper.cs b/ErsatzTV.Application/MediaCards/Mapper.cs index e30e4d54..edc98c52 100644 --- a/ErsatzTV.Application/MediaCards/Mapper.cs +++ b/ErsatzTV.Application/MediaCards/Mapper.cs @@ -187,7 +187,7 @@ internal static class Mapper e.EpisodeMetadata.Head(), maybeJellyfin, maybeEmby, - false, + true, string.Empty)) .ToList(), collection.MediaItems.OfType().Map(a => ProjectToViewModel(a.ArtistMetadata.Head())).ToList(), diff --git a/ErsatzTV.Application/MediaCards/Queries/GetCollectionCardsHandler.cs b/ErsatzTV.Application/MediaCards/Queries/GetCollectionCardsHandler.cs index 7c579dee..3f09be71 100644 --- a/ErsatzTV.Application/MediaCards/Queries/GetCollectionCardsHandler.cs +++ b/ErsatzTV.Application/MediaCards/Queries/GetCollectionCardsHandler.cs @@ -79,9 +79,11 @@ public class GetCollectionCardsHandler : .ThenInclude(i => (i as Episode).Season) .ThenInclude(s => s.Show) .ThenInclude(s => s.ShowMetadata) + .ThenInclude(sm => sm.Artwork) .Include(c => c.MediaItems) .ThenInclude(i => (i as Episode).Season) .ThenInclude(s => s.SeasonMetadata) + .ThenInclude(sm => sm.Artwork) .Include(c => c.MediaItems) .ThenInclude(i => (i as Episode).MediaVersions) .ThenInclude(mv => mv.MediaFiles) diff --git a/ErsatzTV/Pages/Artist.razor b/ErsatzTV/Pages/Artist.razor index ec7b1f7f..008827d5 100644 --- a/ErsatzTV/Pages/Artist.razor +++ b/ErsatzTV/Pages/Artist.razor @@ -19,17 +19,22 @@ fan art } - -
+ + @if (!string.IsNullOrWhiteSpace(_artist.Thumbnail)) { - artist thumbnail + }
- @_artist.Name - @_artist.Disambiguation + + + @_artist?.Name + + + @_artist?.Name + + @_artist.Disambiguation + @if (!string.IsNullOrWhiteSpace(_artist.Biography)) { @@ -47,23 +52,22 @@ } -
+ Add To Collection - Add To Schedule -
+
-
+ @if (_sortedLanguages.Any()) @@ -118,86 +122,110 @@
- @foreach (MusicVideoCardViewModel musicVideo in _musicVideos.Cards) - { - -
- @if (!string.IsNullOrWhiteSpace(musicVideo.Poster)) - { - - - @if (musicVideo.State == MediaItemState.FileNotFound) - { -
- + + @foreach (MusicVideoCardViewModel musicVideo in _musicVideos.Cards) + { + + + @if (!string.IsNullOrWhiteSpace(musicVideo.Poster)) + { +
+ + @if (musicVideo.State == MediaItemState.FileNotFound) + { +
+ +
+ } + else if (musicVideo.State == MediaItemState.Unavailable) + { +
+ +
+ } +
+ } + else + { + + @if (musicVideo.State is not MediaItemState.Normal and not MediaItemState.RemoteOnly) + { +
+ + @if (musicVideo.State == MediaItemState.FileNotFound) + { +
+ +
+ } + else if (musicVideo.State == MediaItemState.Unavailable) + { +
+ +
+ } +
+ } +
+ +
+ + @if (musicVideo.State == MediaItemState.FileNotFound) + { +
+ +
+ } + else if (musicVideo.State == MediaItemState.Unavailable) + { +
+ +
+ }
- } - else if (musicVideo.State == MediaItemState.Unavailable) - { -
- + + } + +
+ @musicVideo.Title + @if (!string.IsNullOrWhiteSpace(musicVideo.Album)) + { +
+ Album:  + @musicVideo.Album +
+ } + @musicVideo.Plot +
+ + Add To Collection +
- } - - } - else +
+
+ + @if (musicVideo.State == MediaItemState.FileNotFound) { -
- - @if (musicVideo.State == MediaItemState.FileNotFound) - { -
- -
- } - else if (musicVideo.State == MediaItemState.Unavailable) - { -
- -
- } +
+ + File Not Found:  + @musicVideo.Path
} - -
- @musicVideo.Title - @if (!string.IsNullOrWhiteSpace(musicVideo.Album)) - { -
- Album:  - @musicVideo.Album -
- } - @musicVideo.Plot -
- - Add To Collection - -
+ else if (musicVideo.State == MediaItemState.Unavailable) + { +
+ + Unavailable:  + @musicVideo.LocalPath
- -
- @if (musicVideo.State == MediaItemState.FileNotFound) - { -
- - File Not Found:  - @musicVideo.Path -
- } - else if (musicVideo.State == MediaItemState.Unavailable) - { -
- - Unavailable:  - @musicVideo.LocalPath -
- } - - } + } + + } + @code { @@ -242,7 +270,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled && result.Data is MediaCollectionViewModel collection) + if (result is { Canceled: false, Data: MediaCollectionViewModel collection }) { await Mediator.Send(new AddArtistToCollection(collection.Id, ArtistId), _cts.Token); NavigationManager.NavigateTo($"media/collections/{collection.Id}"); @@ -256,7 +284,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Add To Schedule", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled && result.Data is ProgramScheduleViewModel schedule) + if (result is { Canceled: false, Data: ProgramScheduleViewModel schedule }) { await Mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, null, PlayoutMode.One, ProgramScheduleItemCollectionType.Artist, null, null, null, ArtistId, null, PlaybackOrder.Shuffle, FillWithGroupMode.None, null, null, TailMode.None, null, null, GuideMode.Normal, null, null, null, null, null, null, null, null, null, null), _cts.Token); NavigationManager.NavigateTo($"schedules/{schedule.Id}/items"); @@ -270,7 +298,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled && result.Data is MediaCollectionViewModel collection) + if (result is { Canceled: false, Data: MediaCollectionViewModel collection }) { var request = new AddMusicVideoToCollection(collection.Id, musicVideo.MusicVideoId); Either addResult = await Mediator.Send(request, _cts.Token); diff --git a/ErsatzTV/Pages/CollectionEditor.razor b/ErsatzTV/Pages/CollectionEditor.razor index ff9e70ce..b5a1bced 100644 --- a/ErsatzTV/Pages/CollectionEditor.razor +++ b/ErsatzTV/Pages/CollectionEditor.razor @@ -7,25 +7,23 @@ @inject ISnackbar Snackbar @inject IMediator Mediator - -
- @(IsEdit ? "Edit Collection" : "Add Collection") - - - - - - - - - - @(IsEdit ? "Save Changes" : "Add Collection") - - - - + + + @(IsEdit ? "Save Collection" : "Add Collection") + +
+ + Collection + + +
+ Name +
+ +
+
- +
@code { private readonly CancellationTokenSource _cts = new(); @@ -34,8 +32,8 @@ public int Id { get; set; } private readonly CollectionEditViewModel _model = new(); - private EditContext _editContext; - private ValidationMessageStore _messageStore; + private MudForm _form; + private bool _success; public void Dispose() { @@ -60,18 +58,12 @@ } } - protected override void OnInitialized() - { - _editContext = new EditContext(_model); - _messageStore = new ValidationMessageStore(_editContext); - } - private bool IsEdit => Id != 0; private async Task HandleSubmitAsync() { - _messageStore.Clear(); - if (_editContext.Validate()) + await _form.Validate(); + if (_success) { Seq errorMessage = IsEdit ? (await Mediator.Send(new UpdateCollection(Id, _model.Name), _cts.Token)).LeftToSeq() : (await Mediator.Send(new CreateCollection(_model.Name), _cts.Token)).LeftToSeq(); diff --git a/ErsatzTV/Pages/CollectionItems.razor b/ErsatzTV/Pages/CollectionItems.razor index a7e249b1..2a54d786 100644 --- a/ErsatzTV/Pages/CollectionItems.razor +++ b/ErsatzTV/Pages/CollectionItems.razor @@ -5,313 +5,333 @@ @inject NavigationManager NavigationManager @inject IJSRuntime JsRuntime - -
- @if (IsSelectMode()) - { - @SelectionLabel() -
- - Remove From Collection - - - Clear Selection - -
- } - else - { -
- @_data?.Name - -
+ + +
+ @if (IsSelectMode()) + { +
+ @SelectionLabel() +
+
+ + Remove From Collection + + + Clear Selection + +
+
+
+ + + + +
+ } + else + { +
+ @_data?.Name +
+ + @if (_data?.MovieCards.Count > 0) + { + @_data.MovieCards.Count Movies + } + + @if (_data?.ShowCards.Count > 0) + { + @_data.ShowCards.Count Shows + } + + @if (_data?.SeasonCards.Count > 0) + { + @_data.SeasonCards.Count Seasons + } + + @if (_data?.EpisodeCards.Count > 0) + { + @_data.EpisodeCards.Count Episodes + } + + @if (_data?.ArtistCards.Count > 0) + { + @_data.ArtistCards.Count Artists + } + + @if (_data?.MusicVideoCards.Count > 0) + { + @_data.MusicVideoCards.Count Music Videos + } + + @if (_data?.OtherVideoCards.Count > 0) + { + @_data.OtherVideoCards.Count Other Videos + } + + @if (_data?.SongCards.Count > 0) + { + @_data.SongCards.Count Songs + } + + @if (_data?.ImageCards.Count > 0) + { + @_data.ImageCards.Count Images + } +
+ @if (SupportsCustomOrdering()) + { +
+ +
+ } +
+ +
+
+ } +
+
+
+ @if (_data?.MovieCards.Count > 0) { - @_data.MovieCards.Count Movies + + Movies + + + + + @foreach (MovieCardViewModel card in OrderMovies(_data.MovieCards)) + { + + } + } @if (_data?.ShowCards.Count > 0) { - @_data.ShowCards.Count Shows + + Shows + + + + + @foreach (TelevisionShowCardViewModel card in _data.ShowCards.OrderBy(m => m.SortTitle)) + { + + } + } @if (_data?.SeasonCards.Count > 0) { - @_data.SeasonCards.Count Seasons + + Seasons + + + + + @foreach (TelevisionSeasonCardViewModel card in _data.SeasonCards.OrderBy(m => m.SortTitle)) + { + + } + } @if (_data?.EpisodeCards.Count > 0) { - @_data.EpisodeCards.Count Episodes + + Episodes + + + + + @foreach (TelevisionEpisodeCardViewModel card in _data.EpisodeCards.OrderBy(e => e.Aired)) + { + + } + } @if (_data?.ArtistCards.Count > 0) { - @_data.ArtistCards.Count Artists + + Artists + + + + + @foreach (ArtistCardViewModel card in _data.ArtistCards.OrderBy(e => e.SortTitle)) + { + + } + } @if (_data?.MusicVideoCards.Count > 0) { - @_data.MusicVideoCards.Count Music Videos + + Music Videos + + + + + @foreach (MusicVideoCardViewModel card in _data.MusicVideoCards.OrderBy(e => e.SortTitle)) + { + + } + } @if (_data?.OtherVideoCards.Count > 0) { - @_data.OtherVideoCards.Count Other Videos + + Other Videos + + + + + @foreach (OtherVideoCardViewModel card in _data.OtherVideoCards.OrderBy(e => e.SortTitle)) + { + + } + } @if (_data?.SongCards.Count > 0) { - @_data.SongCards.Count Songs + + Songs + + + + + @foreach (SongCardViewModel card in _data.SongCards.OrderBy(e => e.SortTitle)) + { + + } + } @if (_data?.ImageCards.Count > 0) { - @_data.ImageCards.Count Images - } - - @if (SupportsCustomOrdering()) - { -
- -
- } - } -
- - - - @if (_data?.MovieCards.Count > 0) - { - - Movies - - - - @foreach (MovieCardViewModel card in OrderMovies(_data.MovieCards)) - { - - } - - } - - @if (_data?.ShowCards.Count > 0) - { - - Television Shows - - - - @foreach (TelevisionShowCardViewModel card in _data.ShowCards.OrderBy(m => m.SortTitle)) - { - - } - - } - - @if (_data?.SeasonCards.Count > 0) - { - - Television Seasons - - - - @foreach (TelevisionSeasonCardViewModel card in _data.SeasonCards.OrderBy(m => m.SortTitle)) - { - - } - - } - - @if (_data?.EpisodeCards.Count > 0) - { - - Television Episodes - - - - @foreach (TelevisionEpisodeCardViewModel card in _data.EpisodeCards.OrderBy(e => e.Aired)) - { - - } - - } - - @if (_data?.ArtistCards.Count > 0) - { - - Artists - - - - @foreach (ArtistCardViewModel card in _data.ArtistCards.OrderBy(e => e.SortTitle)) - { - - } - - } - - @if (_data?.MusicVideoCards.Count > 0) - { - - Music Videos - - - - @foreach (MusicVideoCardViewModel card in _data.MusicVideoCards.OrderBy(e => e.SortTitle)) - { - - } - - } - - @if (_data?.OtherVideoCards.Count > 0) - { - - Other Videos - - - - @foreach (OtherVideoCardViewModel card in _data.OtherVideoCards.OrderBy(e => e.SortTitle)) - { - - } - - } - - @if (_data?.SongCards.Count > 0) - { - - Songs - - - - @foreach (SongCardViewModel card in _data.SongCards.OrderBy(e => e.SortTitle)) - { - + + Images + + + + + @foreach (ImageCardViewModel card in _data.ImageCards.OrderBy(e => e.SortTitle)) + { + + } + } - } - - @if (_data?.ImageCards.Count > 0) - { - - Images - - - - @foreach (ImageCardViewModel card in _data.ImageCards.OrderBy(e => e.SortTitle)) - { - - } - - } - +
+ @code { @@ -512,7 +532,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Remove From Collection", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled) + if (result is { Canceled: false }) { await Mediator.Send(request, CancellationToken); await RefreshData(); diff --git a/ErsatzTV/Pages/Collections.razor b/ErsatzTV/Pages/Collections.razor index 3b9f088b..4c3eb6c7 100644 --- a/ErsatzTV/Pages/Collections.razor +++ b/ErsatzTV/Pages/Collections.razor @@ -6,130 +6,146 @@ @inject IDialogService Dialog @inject IMediator Mediator - -
- - Add Collection - - - Add Multi Collection - + + +
+
+ + Add Collection + + + Add Multi Collection + +
+
+
+ + + + +
+
+
+
+ + Collections + + + + + + + + + + Name + + + + @context.Name + +
+ + + + + + + + +
+
+
+ + + +
+ Multi Collections + + + + + + + + + + Name + + + + @context.Name + +
+ + + + + + + + +
+
+
+ + + +
+ Smart Collections + + + + + + + + + + Name + + + + @context.Name + +
+ + + + + + + + +
+
+
+ + + +
+
+
- - - Collections - - - - - - - Name - - - - @context.Name - -
- - - - - - - - -
-
-
- - - -
- - - Multi Collections - - - - - - - Name - - - - @context.Name - -
- - - - - - - - -
-
-
- - - -
- - - Smart Collections - - - - - - - Name - - - - @context.Name - -
- - - - - - - - -
-
-
- - - -
- +
@code { private readonly CancellationTokenSource _cts = new(); @@ -167,7 +183,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Delete Collection", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled) + if (result is { Canceled: false }) { await Mediator.Send(new DeleteCollection(collection.Id), _cts.Token); if (_collectionsTable != null) @@ -184,7 +200,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Delete Multi Collection", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled) + if (result is { Canceled: false }) { await Mediator.Send(new DeleteMultiCollection(collection.Id), _cts.Token); if (_multiCollectionsTable != null) @@ -201,7 +217,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Delete Smart Collection", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled) + if (result is { Canceled: false }) { await Mediator.Send(new DeleteSmartCollection(collection.Id), _cts.Token); if (_smartCollectionsTable != null) diff --git a/ErsatzTV/Pages/Movie.razor b/ErsatzTV/Pages/Movie.razor index bd3393f2..678ebd91 100644 --- a/ErsatzTV/Pages/Movie.razor +++ b/ErsatzTV/Pages/Movie.razor @@ -32,7 +32,7 @@ @if (!string.IsNullOrWhiteSpace(_movie?.Poster)) {
- + @if (_movie.MediaItemState == MediaItemState.FileNotFound) {
diff --git a/ErsatzTV/Pages/Search.razor b/ErsatzTV/Pages/Search.razor index 2f290b23..ebaf4c7e 100644 --- a/ErsatzTV/Pages/Search.razor +++ b/ErsatzTV/Pages/Search.razor @@ -10,10 +10,10 @@ -
+
@if (IsSelectMode()) { -
+
@SelectionLabel()
@@ -140,9 +140,7 @@ @if (_movies?.Count > 0) {
- + Movies @if (_movies.Count > 50) @@ -168,9 +166,7 @@ @if (_shows?.Count > 0) {
- + Shows @if (_shows.Count > 50) @@ -196,9 +192,7 @@ @if (_seasons?.Count > 0) {
- + Seasons @if (_seasons.Count > 50) @@ -224,9 +218,7 @@ @if (_episodes?.Count > 0) {
- + Episodes @if (_episodes.Count > 50) @@ -253,9 +245,7 @@ @if (_artists?.Count > 0) {
- + Artists @if (_artists.Count > 50) @@ -282,9 +272,7 @@ @if (_musicVideos?.Count > 0) {
- + Music Videos @if (_musicVideos.Count > 50) @@ -311,9 +299,7 @@ @if (_otherVideos?.Count > 0) {
- + Other Videos @if (_otherVideos.Count > 50) @@ -340,9 +326,7 @@ @if (_songs?.Count > 0) {
- + Songs @if (_songs.Count > 50) @@ -369,9 +353,7 @@ @if (_images?.Count > 0) {
- + Images @if (_images.Count > 50) @@ -604,6 +586,27 @@ } } + if (card is TelevisionSeasonCardViewModel season) + { + var parameters = new DialogParameters { { "EntityType", "season" }, { "EntityName", $"{season.Title} Season {season.TelevisionSeasonNumber}" } }; + var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; + + IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); + DialogResult result = await dialog.Result; + if (result is { Canceled: false, Data: MediaCollectionViewModel collection }) + { + var request = new AddSeasonToCollection(collection.Id, season.TelevisionSeasonId); + Either addResult = await Mediator.Send(request, CancellationToken); + addResult.Match( + Left: error => + { + Snackbar.Add($"Unexpected error adding season to collection: {error.Value}"); + Logger.LogError("Unexpected error adding season to collection: {Error}", error.Value); + }, + Right: _ => Snackbar.Add($"Added {season.Title} Season {season.TelevisionSeasonNumber} to collection {collection.Name}", Severity.Success)); + } + } + if (card is ArtistCardViewModel artist) { var parameters = new DialogParameters { { "EntityType", "artist" }, { "EntityName", artist.Title } }; diff --git a/ErsatzTV/Pages/TelevisionEpisodeList.razor b/ErsatzTV/Pages/TelevisionEpisodeList.razor index 3509d0da..846f23b0 100644 --- a/ErsatzTV/Pages/TelevisionEpisodeList.razor +++ b/ErsatzTV/Pages/TelevisionEpisodeList.razor @@ -27,165 +27,155 @@ } } - -
+ + @if (!string.IsNullOrWhiteSpace(_season?.Poster)) { - if (_season.Poster.StartsWith("http://") || _season.Poster.StartsWith("https://")) - { - season poster - } - else - { - season poster - } + } -
- - @_season?.Title - - @_season?.Name -
+ + + + + @_season?.Title + + + @_season?.Title + + + @_season?.Name + + Add To Collection - Add To Playlist - Add To Schedule -
-
-
+ + +
- @foreach (TelevisionEpisodeCardViewModel episode in _data.Cards) - { - -
- @if (!string.IsNullOrWhiteSpace(episode.Poster)) - { - - @if (episode.Poster.StartsWith("http://") || episode.Poster.StartsWith("https://")) - { - - } - else - { - - } - @if (episode.State == MediaItemState.FileNotFound) - { -
- -
- } - else if (episode.State == MediaItemState.Unavailable) - { -
- -
- } -
- } - -
- @episode.Episode. @episode.Title - @episode.Plot -
- - Add To Collection - + + @foreach (TelevisionEpisodeCardViewModel episode in _data.Cards) + { + + + @if (!string.IsNullOrWhiteSpace(episode.Poster)) + { +
+ + + + + + + @if (episode.State == MediaItemState.FileNotFound) + { +
+ +
+ } + else if (episode.State == MediaItemState.Unavailable) + { +
+ +
+ }
-
- - Add To Playlist - + } + +
+ @episode.Episode. @episode.Title + @episode.Plot + + + Add To Collection + + + Add To Playlist + + + Show Media Info + +
-
- - Show Media Info - + + +
+ @if (episode.State == MediaItemState.FileNotFound) + { +
+ + File Not Found:  + @episode.Path
+ } + else if (episode.State == MediaItemState.Unavailable) + { +
+ + Unavailable:  + @episode.LocalPath +
+ } +
+ Released: @episode.Aired.ToShortDateString()
- -
-
- @if (episode.State == MediaItemState.FileNotFound) - { -
- - File Not Found:  - @episode.Path -
- } - else if (episode.State == MediaItemState.Unavailable) - { -
- - Unavailable:  - @episode.LocalPath -
- } -
- Released: @episode.Aired.ToShortDateString() -
- @if (episode.Directors.Any()) - { - var sorted = episode.Directors.OrderBy(w => w).ToList(); + @if (episode.Directors.Any()) + { + var sorted = episode.Directors.OrderBy(w => w).ToList(); -
- Directors:  - @sorted.Head() - @foreach (string director in sorted.Skip(1)) - { - - @director - } -
- } - @if (episode.Writers.Any()) - { - var sorted = episode.Writers.OrderBy(w => w).ToList(); +
+ Directors:  + @sorted.Head() + @foreach (string director in sorted.Skip(1)) + { + + @director + } +
+ } + @if (episode.Writers.Any()) + { + var sorted = episode.Writers.OrderBy(w => w).ToList(); -
- Writers:  - @sorted.Head() - @foreach (string writer in sorted.Skip(1)) - { - - @writer - } -
- } -
- - } +
+ Writers:  + @sorted.Head() + @foreach (string writer in sorted.Skip(1)) + { + + @writer + } +
+ } +
+ + } + @code { @@ -196,8 +186,8 @@ private TelevisionSeasonViewModel _season; - private int _pageSize => 100; - private readonly int _pageNumber = 1; + private static int PageSize => 100; + private const int PageNumber = 1; private TelevisionEpisodeCardResultsViewModel _data = new(0, new List(), null); @@ -229,7 +219,7 @@ await Mediator.Send(new GetTelevisionSeasonById(SeasonId), _cts.Token) .IfSomeAsync(vm => _season = vm); - _data = await Mediator.Send(new GetTelevisionEpisodeCards(SeasonId, _pageNumber, _pageSize), _cts.Token); + _data = await Mediator.Send(new GetTelevisionEpisodeCards(SeasonId, PageNumber, PageSize), _cts.Token); } private async Task AddToCollection() @@ -239,7 +229,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled && result.Data is MediaCollectionViewModel collection) + if (result is { Canceled: false, Data: MediaCollectionViewModel collection }) { await Mediator.Send(new AddSeasonToCollection(collection.Id, SeasonId), _cts.Token); NavigationManager.NavigateTo($"media/collections/{collection.Id}"); @@ -253,7 +243,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Add To Playlist", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled && result.Data is PlaylistViewModel playlist) + if (result is { Canceled: false, Data: PlaylistViewModel playlist }) { await Mediator.Send(new AddSeasonToPlaylist(playlist.Id, SeasonId), _cts.Token); NavigationManager.NavigateTo($"media/playlists/{playlist.Id}"); @@ -267,7 +257,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Add To Schedule", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled && result.Data is ProgramScheduleViewModel schedule) + if (result is { Canceled: false, Data: ProgramScheduleViewModel schedule }) { await Mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, null, PlayoutMode.One, ProgramScheduleItemCollectionType.TelevisionSeason, null, null, null, SeasonId, null, PlaybackOrder.Shuffle, FillWithGroupMode.None, null, null, TailMode.None, null, null, GuideMode.Normal, null, null, null, null, null, null, null, null, null, null), _cts.Token); NavigationManager.NavigateTo($"schedules/{schedule.Id}/items"); @@ -281,7 +271,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled && result.Data is MediaCollectionViewModel collection) + if (result is { Canceled: false, Data: MediaCollectionViewModel collection }) { var request = new AddEpisodeToCollection(collection.Id, episode.EpisodeId); Either addResult = await Mediator.Send(request, _cts.Token); @@ -302,7 +292,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Add To Playlist", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled && result.Data is PlaylistViewModel playlist) + if (result is { Canceled: false, Data: PlaylistViewModel playlist }) { var request = new AddEpisodeToPlaylist(playlist.Id, episode.EpisodeId); Either addResult = await Mediator.Send(request, _cts.Token); @@ -338,4 +328,9 @@ } } + private static string GetPosterUrl(string poster) + { + return poster.StartsWith("http://") || poster.StartsWith("https://") ? poster : $"artwork/posters/{poster}"; + } + } \ No newline at end of file diff --git a/ErsatzTV/Pages/TelevisionSeasonList.razor b/ErsatzTV/Pages/TelevisionSeasonList.razor index 2611557b..82719c8c 100644 --- a/ErsatzTV/Pages/TelevisionSeasonList.razor +++ b/ErsatzTV/Pages/TelevisionSeasonList.razor @@ -28,7 +28,7 @@ - +
diff --git a/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor b/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor index 128495e1..60d637ad 100644 --- a/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor +++ b/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor @@ -138,7 +138,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled && result.Data is MediaCollectionViewModel collection) + if (result is { Canceled: false, Data: MediaCollectionViewModel collection }) { var request = new AddSeasonToCollection(collection.Id, season.TelevisionSeasonId); Either addResult = await Mediator.Send(request, CancellationToken); diff --git a/ErsatzTV/Pages/TraktLists.razor b/ErsatzTV/Pages/TraktLists.razor index 85b27bb5..277e0cd4 100644 --- a/ErsatzTV/Pages/TraktLists.razor +++ b/ErsatzTV/Pages/TraktLists.razor @@ -152,7 +152,7 @@ var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small }; IDialogReference dialog = await Dialog.ShowAsync("Add Trakt List", options); DialogResult result = await dialog.Result; - if (!result.Canceled && result.Data is string url) + if (result is { Canceled: false, Data: string url }) { await WorkerChannel.WriteAsync(new AddTraktList(url), _cts.Token); } diff --git a/ErsatzTV/Shared/MediaCard.razor b/ErsatzTV/Shared/MediaCard.razor index 62a7ec81..1a1134e6 100644 --- a/ErsatzTV/Shared/MediaCard.razor +++ b/ErsatzTV/Shared/MediaCard.razor @@ -1,6 +1,5 @@ @using ErsatzTV.Application.MediaCards @using static Prelude -@inject IMediator Mediator @inject NavigationManager NavigationManager
@@ -78,7 +77,7 @@ @(Title ?? Data.Title) - + @(Subtitle ?? Data.Subtitle)
diff --git a/ErsatzTV/Validators/CollectionEditViewModelValidator.cs b/ErsatzTV/Validators/CollectionEditViewModelValidator.cs deleted file mode 100644 index d6920b5f..00000000 --- a/ErsatzTV/Validators/CollectionEditViewModelValidator.cs +++ /dev/null @@ -1,9 +0,0 @@ -using ErsatzTV.ViewModels; -using FluentValidation; - -namespace ErsatzTV.Validators; - -public class CollectionEditViewModelValidator : AbstractValidator -{ - public CollectionEditViewModelValidator() => RuleFor(c => c.Name).NotEmpty(); -} diff --git a/ErsatzTV/wwwroot/css/site.css b/ErsatzTV/wwwroot/css/site.css index 2c4671bd..a50ae521 100644 --- a/ErsatzTV/wwwroot/css/site.css +++ b/ErsatzTV/wwwroot/css/site.css @@ -6,8 +6,6 @@ .media-card-container { width: 152px; } -.media-card-episode-container { width: 392px; } - .media-card { display: flex; /*filter: brightness(100%);*/ @@ -22,8 +20,6 @@ .media-card-selected-delete { box-shadow: 0 0 0 3px #f44336, 0 0 4px rgba(0, 0, 0, 0.3); } -.media-card-episode { width: 392px; } - .media-card:hover { /*filter: brightness(75%);*/ } .media-card-title {