|
|
@ -27,69 +27,62 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
</MudContainer> |
|
|
|
</MudContainer> |
|
|
|
<MudContainer MaxWidth="MaxWidth.Large" Style="margin-top: 200px"> |
|
|
|
<MudContainer MaxWidth="MaxWidth.Large" Style="margin-top: 100px"> |
|
|
|
<div style="display: flex; flex-direction: row;"> |
|
|
|
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Spacing="6"> |
|
|
|
@if (!string.IsNullOrWhiteSpace(_season?.Poster)) |
|
|
|
@if (!string.IsNullOrWhiteSpace(_season?.Poster)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (_season.Poster.StartsWith("http://") || _season.Poster.StartsWith("https://")) |
|
|
|
<MudImage Src="@GetPosterUrl(_season.Poster)" Elevation="2" Class="rounded-lg" Style="max-height: 325px; margin-left: auto; margin-right: auto"/> |
|
|
|
{ |
|
|
|
|
|
|
|
<img class="mud-elevation-2 mr-6" |
|
|
|
|
|
|
|
style="border-radius: 4px; flex-shrink: 0; max-height: 440px;" |
|
|
|
|
|
|
|
src="@_season.Poster" alt="season poster"/> |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
<img class="mud-elevation-2 mr-6" |
|
|
|
|
|
|
|
style="border-radius: 4px; flex-shrink: 0; max-height: 440px;" |
|
|
|
|
|
|
|
src="@($"artwork/posters/{_season.Poster}")" alt="season poster"/> |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
<MudStack Row="false" Style="flex: 1"> |
|
|
|
<div style="display: flex; flex-direction: column; height: 100%"> |
|
|
|
<MudStack Row="false"> |
|
|
|
<MudLink Href="@($"media/tv/shows/{_season?.ShowId}")"> |
|
|
|
<MudLink Href="@($"media/tv/shows/{_season?.ShowId}")"> |
|
|
|
|
|
|
|
<MudHidden Invert="true" Breakpoint="Breakpoint.SmAndDown"> |
|
|
|
|
|
|
|
<MudText Typo="Typo.h4" Class="media-item-title">@_season?.Title</MudText> |
|
|
|
|
|
|
|
</MudHidden> |
|
|
|
|
|
|
|
<MudHidden Invert="true" Breakpoint="Breakpoint.MdAndUp"> |
|
|
|
<MudText Typo="Typo.h2" Class="media-item-title">@_season?.Title</MudText> |
|
|
|
<MudText Typo="Typo.h2" Class="media-item-title">@_season?.Title</MudText> |
|
|
|
|
|
|
|
</MudHidden> |
|
|
|
</MudLink> |
|
|
|
</MudLink> |
|
|
|
<MudText Typo="Typo.subtitle1" Class="media-item-subtitle mb-6 mud-text-secondary">@_season?.Name</MudText> |
|
|
|
<MudText Typo="Typo.subtitle1" Class="media-item-subtitle mb-6 mud-text-secondary">@_season?.Name</MudText> |
|
|
|
<div> |
|
|
|
</MudStack> |
|
|
|
|
|
|
|
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="mb-6"> |
|
|
|
<MudButton Variant="Variant.Filled" |
|
|
|
<MudButton Variant="Variant.Filled" |
|
|
|
Color="Color.Primary" |
|
|
|
Color="Color.Primary" |
|
|
|
StartIcon="@Icons.Material.Filled.Add" |
|
|
|
StartIcon="@Icons.Material.Filled.Add" |
|
|
|
OnClick="@AddToCollection"> |
|
|
|
OnClick="@AddToCollection"> |
|
|
|
Add To Collection |
|
|
|
Add To Collection |
|
|
|
</MudButton> |
|
|
|
</MudButton> |
|
|
|
<MudButton Class="ml-3" |
|
|
|
<MudButton Variant="Variant.Filled" |
|
|
|
Variant="Variant.Filled" |
|
|
|
|
|
|
|
Color="Color.Primary" |
|
|
|
Color="Color.Primary" |
|
|
|
StartIcon="@Icons.Material.Filled.PlaylistAdd" |
|
|
|
StartIcon="@Icons.Material.Filled.PlaylistAdd" |
|
|
|
OnClick="@AddToPlaylist"> |
|
|
|
OnClick="@AddToPlaylist"> |
|
|
|
Add To Playlist |
|
|
|
Add To Playlist |
|
|
|
</MudButton> |
|
|
|
</MudButton> |
|
|
|
<MudButton Class="ml-3" |
|
|
|
<MudButton Variant="Variant.Filled" |
|
|
|
Variant="Variant.Filled" |
|
|
|
|
|
|
|
Color="Color.Primary" |
|
|
|
Color="Color.Primary" |
|
|
|
StartIcon="@Icons.Material.Filled.Schedule" |
|
|
|
StartIcon="@Icons.Material.Filled.Schedule" |
|
|
|
OnClick="@AddToSchedule"> |
|
|
|
OnClick="@AddToSchedule"> |
|
|
|
Add To Schedule |
|
|
|
Add To Schedule |
|
|
|
</MudButton> |
|
|
|
</MudButton> |
|
|
|
</div> |
|
|
|
</MudStack> |
|
|
|
</div> |
|
|
|
</MudStack> |
|
|
|
</div> |
|
|
|
</MudStack> |
|
|
|
</MudContainer> |
|
|
|
</MudContainer> |
|
|
|
<MudContainer MaxWidth="MaxWidth.Large" Class="mt-8"> |
|
|
|
<MudContainer MaxWidth="MaxWidth.Large" Class="mt-8"> |
|
|
|
|
|
|
|
<MudStack Row="false" Spacing="6"> |
|
|
|
@foreach (TelevisionEpisodeCardViewModel episode in _data.Cards) |
|
|
|
@foreach (TelevisionEpisodeCardViewModel episode in _data.Cards) |
|
|
|
{ |
|
|
|
{ |
|
|
|
<MudCard Class="mb-6"> |
|
|
|
<MudCard> |
|
|
|
<div id="@($"episode-{episode.EpisodeId}")" style="display: flex; flex-direction: row; scroll-margin-top: 85px"> |
|
|
|
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" id="@($"episode-{episode.EpisodeId}")"> |
|
|
|
@if (!string.IsNullOrWhiteSpace(episode.Poster)) |
|
|
|
@if (!string.IsNullOrWhiteSpace(episode.Poster)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
<MudPaper style="display: flex; flex-direction: column; position: relative"> |
|
|
|
<div style="display: flex; flex-direction: column; position: relative"> |
|
|
|
@if (episode.Poster.StartsWith("http://") || episode.Poster.StartsWith("https://")) |
|
|
|
<MudHidden Invert="true" Breakpoint="Breakpoint.SmAndDown"> |
|
|
|
{ |
|
|
|
<MudImage Src="@GetPosterUrl(episode.Poster)" Style="max-height: 220px; max-width: 265px; margin-left: auto; margin-right: auto;"/> |
|
|
|
<MudCardMedia Image="@episode.Poster" Style="flex-grow: 1; height: 220px; width: 392px;"/> |
|
|
|
</MudHidden> |
|
|
|
} |
|
|
|
<MudHidden Invert="true" Breakpoint="Breakpoint.MdAndUp"> |
|
|
|
else |
|
|
|
<MudImage Src="@GetPosterUrl(episode.Poster)" Style="max-height: 220px; max-width: 392px; margin-left: auto; margin-right: auto;"/> |
|
|
|
{ |
|
|
|
</MudHidden> |
|
|
|
<MudCardMedia Image="@($"artwork/thumbnails/{episode.Poster}")" Style="flex-grow: 1; height: 220px; width: 392px;"/> |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
@if (episode.State == MediaItemState.FileNotFound) |
|
|
|
@if (episode.State == MediaItemState.FileNotFound) |
|
|
|
{ |
|
|
|
{ |
|
|
|
<div style="position: absolute; right: 10px; top: 8px;"> |
|
|
|
<div style="position: absolute; right: 10px; top: 8px;"> |
|
|
@ -102,39 +95,35 @@ |
|
|
|
<MudIcon Icon="@Icons.Material.Filled.Warning" Color="Color.Warning" Size="Size.Large"/> |
|
|
|
<MudIcon Icon="@Icons.Material.Filled.Warning" Color="Color.Warning" Size="Size.Large"/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
} |
|
|
|
} |
|
|
|
</MudPaper> |
|
|
|
</div> |
|
|
|
} |
|
|
|
} |
|
|
|
<MudCardContent Class="ml-3"> |
|
|
|
<MudCardContent Class="ml-3"> |
|
|
|
<div style="display: flex; flex-direction: column; height: 100%"> |
|
|
|
<div style="display: flex; flex-direction: column; height: 100%"> |
|
|
|
<MudText Typo="Typo.h4">@episode.Episode. @episode.Title</MudText> |
|
|
|
<MudText Typo="Typo.h4" Class="mb-6">@episode.Episode. @episode.Title</MudText> |
|
|
|
<MudText Style="flex-grow: 1">@episode.Plot</MudText> |
|
|
|
<MudText Class="d-none d-md-flex" Style="flex-grow: 1">@episode.Plot</MudText> |
|
|
|
<div class="mt-6"> |
|
|
|
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown"> |
|
|
|
<MudButton Variant="Variant.Filled" |
|
|
|
<MudButton Variant="Variant.Filled" |
|
|
|
Color="Color.Primary" |
|
|
|
Color="Color.Primary" |
|
|
|
StartIcon="@Icons.Material.Filled.Add" |
|
|
|
StartIcon="@Icons.Material.Filled.Add" |
|
|
|
OnClick="@(_ => AddEpisodeToCollection(episode))"> |
|
|
|
OnClick="@(_ => AddEpisodeToCollection(episode))"> |
|
|
|
Add To Collection |
|
|
|
Add To Collection |
|
|
|
</MudButton> |
|
|
|
</MudButton> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="mt-6"> |
|
|
|
|
|
|
|
<MudButton Variant="Variant.Filled" |
|
|
|
<MudButton Variant="Variant.Filled" |
|
|
|
Color="Color.Primary" |
|
|
|
Color="Color.Primary" |
|
|
|
StartIcon="@Icons.Material.Filled.PlaylistAdd" |
|
|
|
StartIcon="@Icons.Material.Filled.PlaylistAdd" |
|
|
|
OnClick="@(_ => AddEpisodeToPlaylist(episode))"> |
|
|
|
OnClick="@(_ => AddEpisodeToPlaylist(episode))"> |
|
|
|
Add To Playlist |
|
|
|
Add To Playlist |
|
|
|
</MudButton> |
|
|
|
</MudButton> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="mt-6"> |
|
|
|
|
|
|
|
<MudButton Variant="Variant.Filled" |
|
|
|
<MudButton Variant="Variant.Filled" |
|
|
|
Color="Color.Secondary" |
|
|
|
Color="Color.Secondary" |
|
|
|
StartIcon="@Icons.Material.Filled.Info" |
|
|
|
StartIcon="@Icons.Material.Filled.Info" |
|
|
|
OnClick="@(_ => ShowInfo(episode))"> |
|
|
|
OnClick="@(_ => ShowInfo(episode))"> |
|
|
|
Show Media Info |
|
|
|
Show Media Info |
|
|
|
</MudButton> |
|
|
|
</MudButton> |
|
|
|
</div> |
|
|
|
</MudStack> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</MudCardContent> |
|
|
|
</MudCardContent> |
|
|
|
</div> |
|
|
|
</MudStack> |
|
|
|
<div class="pl-3 pt-3"> |
|
|
|
<div class="pl-3 pt-3"> |
|
|
|
@if (episode.State == MediaItemState.FileNotFound) |
|
|
|
@if (episode.State == MediaItemState.FileNotFound) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -152,7 +141,7 @@ |
|
|
|
<MudText>@episode.LocalPath</MudText> |
|
|
|
<MudText>@episode.LocalPath</MudText> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
} |
|
|
|
} |
|
|
|
<div style="display: flex; flex-direction: row; flex-wrap: wrap"> |
|
|
|
<div class="d-none d-md-flex" style="flex-direction: row; flex-wrap: wrap"> |
|
|
|
<MudText GutterBottom="true">Released: @episode.Aired.ToShortDateString()</MudText> |
|
|
|
<MudText GutterBottom="true">Released: @episode.Aired.ToShortDateString()</MudText> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
@if (episode.Directors.Any()) |
|
|
|
@if (episode.Directors.Any()) |
|
|
@ -186,6 +175,7 @@ |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</MudCard> |
|
|
|
</MudCard> |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
</MudStack> |
|
|
|
</MudContainer> |
|
|
|
</MudContainer> |
|
|
|
|
|
|
|
|
|
|
|
@code { |
|
|
|
@code { |
|
|
@ -196,8 +186,8 @@ |
|
|
|
|
|
|
|
|
|
|
|
private TelevisionSeasonViewModel _season; |
|
|
|
private TelevisionSeasonViewModel _season; |
|
|
|
|
|
|
|
|
|
|
|
private int _pageSize => 100; |
|
|
|
private static int PageSize => 100; |
|
|
|
private readonly int _pageNumber = 1; |
|
|
|
private const int PageNumber = 1; |
|
|
|
|
|
|
|
|
|
|
|
private TelevisionEpisodeCardResultsViewModel _data = new(0, new List<TelevisionEpisodeCardViewModel>(), null); |
|
|
|
private TelevisionEpisodeCardResultsViewModel _data = new(0, new List<TelevisionEpisodeCardViewModel>(), null); |
|
|
|
|
|
|
|
|
|
|
@ -229,7 +219,7 @@ |
|
|
|
await Mediator.Send(new GetTelevisionSeasonById(SeasonId), _cts.Token) |
|
|
|
await Mediator.Send(new GetTelevisionSeasonById(SeasonId), _cts.Token) |
|
|
|
.IfSomeAsync(vm => _season = vm); |
|
|
|
.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() |
|
|
|
private async Task AddToCollection() |
|
|
@ -239,7 +229,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options); |
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options); |
|
|
|
DialogResult result = await dialog.Result; |
|
|
|
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); |
|
|
|
await Mediator.Send(new AddSeasonToCollection(collection.Id, SeasonId), _cts.Token); |
|
|
|
NavigationManager.NavigateTo($"media/collections/{collection.Id}"); |
|
|
|
NavigationManager.NavigateTo($"media/collections/{collection.Id}"); |
|
|
@ -253,7 +243,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToPlaylistDialog>("Add To Playlist", parameters, options); |
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToPlaylistDialog>("Add To Playlist", parameters, options); |
|
|
|
DialogResult result = await dialog.Result; |
|
|
|
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); |
|
|
|
await Mediator.Send(new AddSeasonToPlaylist(playlist.Id, SeasonId), _cts.Token); |
|
|
|
NavigationManager.NavigateTo($"media/playlists/{playlist.Id}"); |
|
|
|
NavigationManager.NavigateTo($"media/playlists/{playlist.Id}"); |
|
|
@ -267,7 +257,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToScheduleDialog>("Add To Schedule", parameters, options); |
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToScheduleDialog>("Add To Schedule", parameters, options); |
|
|
|
DialogResult result = await dialog.Result; |
|
|
|
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); |
|
|
|
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"); |
|
|
|
NavigationManager.NavigateTo($"schedules/{schedule.Id}/items"); |
|
|
@ -281,7 +271,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options); |
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options); |
|
|
|
DialogResult result = await dialog.Result; |
|
|
|
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); |
|
|
|
var request = new AddEpisodeToCollection(collection.Id, episode.EpisodeId); |
|
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, _cts.Token); |
|
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, _cts.Token); |
|
|
@ -302,7 +292,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToPlaylistDialog>("Add To Playlist", parameters, options); |
|
|
|
IDialogReference dialog = await Dialog.ShowAsync<AddToPlaylistDialog>("Add To Playlist", parameters, options); |
|
|
|
DialogResult result = await dialog.Result; |
|
|
|
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); |
|
|
|
var request = new AddEpisodeToPlaylist(playlist.Id, episode.EpisodeId); |
|
|
|
Either<BaseError, Unit> addResult = await Mediator.Send(request, _cts.Token); |
|
|
|
Either<BaseError, Unit> 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}"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |