diff --git a/ErsatzTV/Pages/ArtistList.razor b/ErsatzTV/Pages/ArtistList.razor index 207f60cf3..1a13a2199 100644 --- a/ErsatzTV/Pages/ArtistList.razor +++ b/ErsatzTV/Pages/ArtistList.razor @@ -7,61 +7,36 @@ @inherits MultiSelectBase @inject NavigationManager NavigationManager - -
- @if (IsSelectMode()) - { - @SelectionLabel() -
- - Add To Collection - - - Clear Selection - -
- } - else - { - @_query -
- - - - - @Math.Min((PageNumber - 1) * PageSize + 1, _data.Count)-@Math.Min(_data.Count, PageNumber * PageSize) of @_data.Count - - - - -
- } + + + + +
+ + + + + + +
- - - - - - - - +
@if (_data.PageMap is not null) { ("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 AddArtistToCollection(collection.Id, artist.ArtistId); Either addResult = await Mediator.Send(request, CancellationToken); diff --git a/ErsatzTV/Pages/EpisodeList.razor b/ErsatzTV/Pages/EpisodeList.razor index a43f2df1c..cabee6bd7 100644 --- a/ErsatzTV/Pages/EpisodeList.razor +++ b/ErsatzTV/Pages/EpisodeList.razor @@ -7,68 +7,36 @@ @inherits MultiSelectBase @inject NavigationManager NavigationManager - -
- @if (IsSelectMode()) - { - @SelectionLabel() -
- - Add To Collection - - - Add To Playlist - - - Clear Selection - -
- } - else - { - @_query -
- - - - - @Math.Min((PageNumber - 1) * PageSize + 1, _data.Count)-@Math.Min(_data.Count, PageNumber * PageSize) of @_data.Count - - - - -
- } + + + + +
+ + + + + + +
- - - - - - - - +
@if (_data.PageMap is not null) { ("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, CancellationToken); diff --git a/ErsatzTV/Pages/ImageBrowser.razor b/ErsatzTV/Pages/ImageBrowser.razor index 0029bf7a0..0775f5d82 100644 --- a/ErsatzTV/Pages/ImageBrowser.razor +++ b/ErsatzTV/Pages/ImageBrowser.razor @@ -5,20 +5,22 @@ @inject IDialogService Dialog @inject IMediator Mediator - - - + +
+ + Images + -
-
+
+
@item.Value.Text
-
- @item.Value.EndText +
+ @item.Value.EndText @@ -29,6 +31,7 @@ if (!string.IsNullOrWhiteSpace(query)) { } @@ -40,9 +43,9 @@ - - - + +
+ @code { private readonly CancellationTokenSource _cts = new(); @@ -90,7 +93,7 @@ IDialogReference dialog = await Dialog.ShowAsync("Edit Image Folder Duration", parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled) + if (result is { Canceled: false }) { double? duration = await Mediator.Send(new UpdateImageFolderDuration(item.LibraryFolderId, result.Data as double?), _cts.Token); item.UpdateDuration(duration); diff --git a/ErsatzTV/Pages/ImageList.razor b/ErsatzTV/Pages/ImageList.razor index ebbbf666d..fad1d89d6 100644 --- a/ErsatzTV/Pages/ImageList.razor +++ b/ErsatzTV/Pages/ImageList.razor @@ -7,68 +7,36 @@ @inherits MultiSelectBase @inject NavigationManager NavigationManager - -
- @if (IsSelectMode()) - { - @SelectionLabel() -
- - Add To Collection - - - Add To Playlist - - - Clear Selection - -
- } - else - { - @_query -
- - - - - @Math.Min((PageNumber - 1) * PageSize + 1, _data.Count)-@Math.Min(_data.Count, PageNumber * PageSize) of @_data.Count - - - - -
- } + + + + +
+ + + + + + +
- - - - - - - - +
@if (_data.PageMap is not null) { ("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 AddImageToCollection(collection.Id, image.ImageId); Either addResult = await Mediator.Send(request, CancellationToken); diff --git a/ErsatzTV/Pages/Movie.razor b/ErsatzTV/Pages/Movie.razor index 17455aef9..bd3393f2f 100644 --- a/ErsatzTV/Pages/Movie.razor +++ b/ErsatzTV/Pages/Movie.razor @@ -27,23 +27,12 @@ } } - -
+ + @if (!string.IsNullOrWhiteSpace(_movie?.Poster)) { -
- @if (_movie.Poster.StartsWith("http://") || _movie.Poster.StartsWith("https://")) - { - movie poster - } - else - { - movie poster - } +
+ @if (_movie.MediaItemState == MediaItemState.FileNotFound) {
@@ -59,8 +48,15 @@
}
- @_movie?.Title - @_movie?.Year + + + @_movie?.Title + + + @_movie?.Title + + @_movie?.Year + @if (!string.IsNullOrWhiteSpace(_movie?.Plot)) { @@ -69,34 +65,28 @@ } -
- + Add To Collection -
-
- Add To Playlist -
-
Show Media Info -
+
-
+ @if (_movie?.MediaItemState == MediaItemState.FileNotFound) { @@ -121,7 +111,7 @@ } - + @if (_sortedContentRatings.Any()) { @@ -214,14 +204,14 @@ { Actors - - - @foreach (ActorCardViewModel actor in _movie.Actors) - { - - } + + @foreach (ActorCardViewModel actor in _movie.Actors) + { + + } + } @@ -296,7 +286,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 AddMovieToCollection(collection.Id, MovieId), _cts.Token); NavigationManager.NavigateTo($"media/collections/{collection.Id}"); @@ -310,7 +300,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 AddMovieToPlaylist(playlist.Id, MovieId), _cts.Token); NavigationManager.NavigateTo($"media/playlists/{playlist.Id}"); @@ -336,4 +326,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/MovieList.razor b/ErsatzTV/Pages/MovieList.razor index 04c531ad0..c74a853d6 100644 --- a/ErsatzTV/Pages/MovieList.razor +++ b/ErsatzTV/Pages/MovieList.razor @@ -9,67 +9,36 @@ @using ErsatzTV.Extensions @implements IDisposable - -
- @if (IsSelectMode()) - { - @SelectionLabel() -
- - Add To Collection - - - Add To Playlist - - - Clear Selection - -
- } - else - { - @_query -
- - - - - @Math.Min((PageNumber - 1) * PageSize + 1, _data.Count)-@Math.Min(_data.Count, PageNumber * PageSize) of @_data.Count - - - - -
- } + + + + +
+ + + + + + +
- - - - - - - - +
+ @if (_data.PageMap is not null) { ("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 AddMovieToCollection(collection.Id, movie.MovieId); Either addResult = await Mediator.Send(request, CancellationToken); diff --git a/ErsatzTV/Pages/MultiSelectBase.cs b/ErsatzTV/Pages/MultiSelectBase.cs index ca28ee767..1d19417d0 100644 --- a/ErsatzTV/Pages/MultiSelectBase.cs +++ b/ErsatzTV/Pages/MultiSelectBase.cs @@ -48,6 +48,7 @@ public class MultiSelectBase : FragmentNavigationBase { SelectedItems.Clear(); _recentlySelected = None; + StateHasChanged(); } protected virtual Task RefreshData() => Task.CompletedTask; @@ -125,7 +126,7 @@ public class MultiSelectBase : FragmentNavigationBase 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 AddItemsToCollection( collection.Id, @@ -170,7 +171,7 @@ public class MultiSelectBase : FragmentNavigationBase parameters, options); DialogResult result = await dialog.Result; - if (!result.Canceled) + if (result is { Canceled: false }) { var itemIds = SelectedItems.Map(vm => vm.MediaItemId).ToList(); @@ -208,7 +209,7 @@ public class MultiSelectBase : FragmentNavigationBase 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 AddItemsToPlaylist( playlist.Id, diff --git a/ErsatzTV/Pages/MusicVideoList.razor b/ErsatzTV/Pages/MusicVideoList.razor index 32d21f552..f99871cab 100644 --- a/ErsatzTV/Pages/MusicVideoList.razor +++ b/ErsatzTV/Pages/MusicVideoList.razor @@ -7,68 +7,36 @@ @inherits MultiSelectBase @inject NavigationManager NavigationManager - -
- @if (IsSelectMode()) - { - @SelectionLabel() -
- - Add To Collection - - - Add To Playlist - - - Clear Selection - -
- } - else - { - @_query -
- - - - - @Math.Min((PageNumber - 1) * PageSize + 1, _data.Count)-@Math.Min(_data.Count, PageNumber * PageSize) of @_data.Count - - - - -
- } + + + + +
+ + + + + + +
- - - - - - - - +
@if (_data.PageMap is not null) { ("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, CancellationToken); diff --git a/ErsatzTV/Pages/OtherVideoList.razor b/ErsatzTV/Pages/OtherVideoList.razor index 56ba5c61f..b5beb569c 100644 --- a/ErsatzTV/Pages/OtherVideoList.razor +++ b/ErsatzTV/Pages/OtherVideoList.razor @@ -7,68 +7,36 @@ @inherits MultiSelectBase @inject NavigationManager NavigationManager - -
- @if (IsSelectMode()) - { - @SelectionLabel() -
- - Add To Collection - - - Add To Playlist - - - Clear Selection - -
- } - else - { - @_query -
- - - - - @Math.Min((PageNumber - 1) * PageSize + 1, _data.Count)-@Math.Min(_data.Count, PageNumber * PageSize) of @_data.Count - - - - -
- } + + + + +
+ + + + + + +
- - - - - - - - +
@if (_data.PageMap is not null) { ("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 AddOtherVideoToCollection(collection.Id, otherVideo.OtherVideoId); Either addResult = await Mediator.Send(request, CancellationToken); diff --git a/ErsatzTV/Pages/SongList.razor b/ErsatzTV/Pages/SongList.razor index 2e7174c69..4c84f2c64 100644 --- a/ErsatzTV/Pages/SongList.razor +++ b/ErsatzTV/Pages/SongList.razor @@ -7,68 +7,36 @@ @inherits MultiSelectBase @inject NavigationManager NavigationManager - -
- @if (IsSelectMode()) - { - @SelectionLabel() -
- - Add To Collection - - - Add To Playlist - - - Clear Selection - -
- } - else - { - @_query -
- - - - - @Math.Min((PageNumber - 1) * PageSize + 1, _data.Count)-@Math.Min(_data.Count, PageNumber * PageSize) of @_data.Count - - - - -
- } + + + + +
+ + + + + + +
- - - - - - - - +
@if (_data.PageMap is not null) { ("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 AddSongToCollection(collection.Id, song.SongId); Either addResult = await Mediator.Send(request, CancellationToken); diff --git a/ErsatzTV/Pages/TelevisionSeasonList.razor b/ErsatzTV/Pages/TelevisionSeasonList.razor index e57354c97..2611557bf 100644 --- a/ErsatzTV/Pages/TelevisionSeasonList.razor +++ b/ErsatzTV/Pages/TelevisionSeasonList.razor @@ -26,26 +26,19 @@ } } - -
- @if (!string.IsNullOrWhiteSpace(_show?.Poster)) - { - if (_show.Poster.StartsWith("http://") || _show.Poster.StartsWith("https://")) - { - movie poster - } - else - { - movie poster - } - } + + +
- @_show?.Title - @_show?.Year + + + @_show?.Title + + + @_show?.Title + + @_show?.Year + @if (!string.IsNullOrWhiteSpace(_show?.Plot)) { @@ -54,31 +47,29 @@ } -
+ Add To Collection - Add To Playlist - Add To Schedule -
+
-
- + + @if (_sortedContentRatings.Any()) { @@ -157,29 +148,27 @@
Seasons - - - @foreach (TelevisionSeasonCardViewModel card in _data.Cards) + + @foreach (TelevisionSeasonCardViewModel card in _data.Cards) + { + + } + + @if ((_show?.Actors?.Count ?? 0) > 0) { - + Actors + + @foreach (ActorCardViewModel actor in _show.Actors) + { + + } + } -@if ((_show?.Actors?.Count ?? 0) > 0) -{ - - Actors - - - @foreach (ActorCardViewModel actor in _show.Actors) - { - - } - -} @code { private readonly CancellationTokenSource _cts = new(); @@ -195,8 +184,8 @@ private List _sortedGenres = []; private List _sortedTags = []; - private int _pageSize => 100; - private readonly int _pageNumber = 1; + private static int PageSize => 100; + private const int PageNumber = 1; private TelevisionSeasonCardResultsViewModel _data = new(0, new List(), null); @@ -222,7 +211,7 @@ _sortedNetworks = _show.Networks.OrderBy(n => n).ToList(); } - _data = await Mediator.Send(new GetTelevisionSeasonCards(ShowId, _pageNumber, _pageSize), _cts.Token); + _data = await Mediator.Send(new GetTelevisionSeasonCards(ShowId, PageNumber, PageSize), _cts.Token); } private async Task AddToCollection() @@ -232,7 +221,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 AddShowToCollection(collection.Id, ShowId), _cts.Token); NavigationManager.NavigateTo($"media/collections/{collection.Id}"); @@ -246,7 +235,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 AddShowToPlaylist(playlist.Id, ShowId), _cts.Token); NavigationManager.NavigateTo($"media/playlists/{playlist.Id}"); @@ -260,7 +249,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.TelevisionShow, null, null, null, ShowId, 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"); @@ -276,7 +265,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, _cts.Token); @@ -291,4 +280,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/TelevisionShowList.razor b/ErsatzTV/Pages/TelevisionShowList.razor index 7bbe1721a..c08242cff 100644 --- a/ErsatzTV/Pages/TelevisionShowList.razor +++ b/ErsatzTV/Pages/TelevisionShowList.razor @@ -9,67 +9,35 @@ @using ErsatzTV.Extensions @implements IDisposable - -
- @if (IsSelectMode()) - { - @SelectionLabel() -
- - Add To Collection - - - Add To Playlist - - - Clear Selection - -
- } - else - { - @_query -
- - - - - @Math.Min((PageNumber - 1) * PageSize + 1, _data.Count)-@Math.Min(_data.Count, PageNumber * PageSize) of @_data.Count - - - - -
- } + + + + +
+ + + + + + +
- - - - - - - - +
@if (_data.PageMap is not null) { ("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 AddShowToCollection(collection.Id, show.TelevisionShowId); Either addResult = await Mediator.Send(request, CancellationToken); diff --git a/ErsatzTV/Shared/MediaCardPager.razor b/ErsatzTV/Shared/MediaCardPager.razor new file mode 100644 index 000000000..879f92047 --- /dev/null +++ b/ErsatzTV/Shared/MediaCardPager.razor @@ -0,0 +1,108 @@ +@using System.Globalization + +
+ @if (IsSelectMode()) + { +
+
+ @SelectionLabel() +
+
+ + Add To Collection + + + Add To Playlist + + + Clear Selection + +
+
+
+ + + + + +
+
+ } + else + { +
+
+ @Query +
+
+ + + + + @PaddedString(Math.Min((PageNumber - 1) * PageSize + 1, TotalCount), TotalCount) - @PaddedString(Math.Min(TotalCount, PageNumber * PageSize), TotalCount) of @TotalCount + + + + +
+
+
+ } +
+ +@code { + + [Parameter] + public string Query { get; set; } + + [Parameter] + public int PageNumber { get; set; } + + [Parameter] + public int PageSize { get; set; } + + [Parameter] + public int TotalCount { get; set; } + + [Parameter] + public EventCallback PrevPage { get; set; } + + [Parameter] + public EventCallback NextPage { get; set; } + + [Parameter] + public Func IsSelectMode { get; set; } + + [Parameter] + public Func SelectionLabel { get; set; } + + [Parameter] + public Func AddSelectionToCollection { get; set; } + + [Parameter] + public Func AddSelectionToPlaylist { get; set; } + + [Parameter] + public Action ClearSelection { get; set; } + + private static MarkupString PaddedString(int value, int maximum) + { + int length = maximum.ToString(CultureInfo.InvariantCulture).Length; + return (MarkupString)value.ToString(CultureInfo.InvariantCulture).PadLeft(length, ' ').Replace(" ", " "); + } +} \ No newline at end of file diff --git a/ErsatzTV/wwwroot/css/site.css b/ErsatzTV/wwwroot/css/site.css index 69f9e72ce..2c4671bd2 100644 --- a/ErsatzTV/wwwroot/css/site.css +++ b/ErsatzTV/wwwroot/css/site.css @@ -92,9 +92,8 @@ } .fanart-container > .fanart-tint { - background: linear-gradient(360deg, black, transparent); + background: linear-gradient(rgba(39, 39, 39, 0.47) 0%, rgb(39, 39, 39) 100%); height: 400px; - opacity: 0.85; position: absolute; width: 100%; z-index: 1;