@page "/media/movies/{MovieId:int}" @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaItems @using ErsatzTV.Application.Movies @using ErsatzTV.Extensions @using LanguageExt.UnsafeValueAccess @implements IDisposable @inject IMediator Mediator @inject IDialogService Dialog @inject NavigationManager NavigationManager @inject ILogger Logger @inject ISnackbar Snackbar @inject PersistentComponentState ApplicationState
@if (!string.IsNullOrWhiteSpace(_movie?.FanArt)) { if (_movie.FanArt.StartsWith("http://") || _movie.FanArt.StartsWith("https://")) { fan art } else { fan art } }
@if (!string.IsNullOrWhiteSpace(_movie?.Poster)) {
@if (_movie.MediaItemState == MediaItemState.FileNotFound) {
} else if (_movie.MediaItemState == MediaItemState.Unavailable) {
}
}
@_movie?.Title @_movie?.Title @_movie?.Year @if (!string.IsNullOrWhiteSpace(_movie?.Plot)) { @_movie.Plot } Add To Collection Add To Playlist Show Media Info Troubleshoot Playback
@if (_movie?.MediaItemState == MediaItemState.FileNotFound) {
File Not Found:  @_movie.Path
} else if (_movie?.MediaItemState == MediaItemState.Unavailable) {
Unavailable:  @_movie.LocalPath
} @if (_sortedContentRatings.Any()) {
Content Ratings:  @_sortedContentRatings.Head() @foreach (string contentRating in _sortedContentRatings.Skip(1)) { @contentRating }
} @if (_sortedLanguages.Any()) {
Languages:  @_sortedLanguages.Head() @foreach (string language in _sortedLanguages.Skip(1)) { @language }
} @if (_sortedStudios.Any()) {
Studios:  @_sortedStudios.Head() @foreach (string studio in _sortedStudios.Skip(1)) { @studio }
} @if (_sortedDirectors.Any()) {
Directors:  @_sortedDirectors.Head() @foreach (string director in _sortedDirectors.Skip(1)) { @director }
} @if (_sortedWriters.Any()) {
Writers:  @_sortedWriters.Head() @foreach (string writer in _sortedWriters.Skip(1)) { @writer }
} @if (_sortedGenres.Any()) {
Genres:  @_sortedGenres.Head() @foreach (string genre in _sortedGenres.Skip(1)) { @genre }
} @if (_sortedTags.Any()) {
Tags:  @_sortedTags.Head() @foreach (string tag in _sortedTags.Skip(1)) { @tag }
}
@if (_movie is not null && _movie.Actors.Any()) { Actors @foreach (ActorCardViewModel actor in _movie.Actors) { } } @code { private CancellationTokenSource _cts; private PersistingComponentStateSubscription _persistingSubscription; [Parameter] public int MovieId { get; set; } private MovieViewModel _movie; private List _sortedContentRatings = new(); private List _sortedLanguages = new(); private List _sortedDirectors = new(); private List _sortedWriters = new(); private List _sortedStudios = new(); private List _sortedGenres = new(); private List _sortedTags = new(); public void Dispose() { _persistingSubscription.Dispose(); _cts?.Cancel(); _cts?.Dispose(); } protected override Task OnInitializedAsync() { _persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData); return base.OnInitializedAsync(); } protected override async Task OnParametersSetAsync() { _cts?.Cancel(); _cts?.Dispose(); _cts = new CancellationTokenSource(); var token = _cts.Token; try { if (!ApplicationState.TryTakeFromJson("_movie", out MovieViewModel restored)) { Option maybeMovie = await Mediator.Send(new GetMovieById(MovieId), token); foreach (var movie in maybeMovie) { _movie = movie; } if (maybeMovie.IsNone) { NavigationManager.NavigateTo("404"); } } else { _movie = restored; } _sortedContentRatings = _movie?.ContentRatings.OrderBy(cr => cr).ToList(); _sortedLanguages = _movie?.Languages.OrderBy(l => l).ToList(); _sortedStudios = _movie?.Studios.OrderBy(s => s).ToList(); _sortedGenres = _movie?.Genres.OrderBy(g => g).ToList(); _sortedTags = _movie?.Tags.OrderBy(t => t).ToList(); _sortedDirectors = _movie?.Directors.OrderBy(d => d).ToList(); _sortedWriters = _movie?.Writers.OrderBy(w => w).ToList(); } catch (OperationCanceledException) { // do nothing } } private Task PersistData() { ApplicationState.PersistAsJson("_movie", _movie); return Task.CompletedTask; } private async Task AddToCollection() { var parameters = new DialogParameters { { "EntityType", "movie" }, { "EntityName", _movie.Title } }; 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 }) { await Mediator.Send(new AddMovieToCollection(collection.Id, MovieId), _cts.Token); NavigationManager.NavigateTo($"media/collections/{collection.Id}"); } } private async Task AddToPlaylist() { var parameters = new DialogParameters { { "EntityType", "movie" }, { "EntityName", _movie.Title } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; IDialogReference dialog = await Dialog.ShowAsync("Add To Playlist", parameters, options); DialogResult result = await dialog.Result; if (result is { Canceled: false, Data: PlaylistViewModel playlist }) { await Mediator.Send(new AddMovieToPlaylist(playlist.Id, MovieId), _cts.Token); NavigationManager.NavigateTo($"media/playlists/{playlist.Id}"); } } private async Task ShowInfo() { Either maybeInfo = await Mediator.Send(new GetMediaItemInfo(MovieId)); foreach (BaseError error in maybeInfo.LeftToSeq()) { Snackbar.Add("Unexpected error loading media info"); Logger.LogError("Unexpected error loading media info: {Error}", error.Value); } foreach (MediaItemInfo info in maybeInfo.RightToSeq()) { var parameters = new DialogParameters { { "MediaItemInfo", info } }; var options = new DialogOptions { CloseButton = true, CloseOnEscapeKey = true, MaxWidth = MaxWidth.Medium, FullWidth = true }; IDialogReference dialog = await Dialog.ShowAsync(_movie.Title, parameters, options); DialogResult _ = await dialog.Result; } } private static string GetPosterUrl(string poster) => poster.StartsWith("http://") || poster.StartsWith("https://") ? poster : $"artwork/posters/{poster}"; }