diff --git a/ErsatzTV.Application/MediaCollections/CollectionUpdateResult.cs b/ErsatzTV.Application/MediaCollections/CollectionUpdateResult.cs index 0d88e52b5..f0fe4959f 100644 --- a/ErsatzTV.Application/MediaCollections/CollectionUpdateResult.cs +++ b/ErsatzTV.Application/MediaCollections/CollectionUpdateResult.cs @@ -2,7 +2,7 @@ namespace ErsatzTV.Application.MediaCollections { - public record CollectionUpdateResult + public class CollectionUpdateResult { public List ModifiedPlayoutIds { get; set; } } diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollection.cs b/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollection.cs index ae69c119c..5847d2112 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollection.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollection.cs @@ -1,7 +1,9 @@ using ErsatzTV.Core; using LanguageExt; +using MediatR; namespace ErsatzTV.Application.MediaCollections.Commands { - public record AddEpisodeToCollection(int CollectionId, int EpisodeId) : MediatR.IRequest>; + public record AddEpisodeToCollection + (int CollectionId, int EpisodeId) : IRequest>; } diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs index 00c9abaeb..e354d5cc1 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs @@ -3,11 +3,14 @@ using System.Threading.Tasks; using ErsatzTV.Core; using ErsatzTV.Core.Interfaces.Repositories; using LanguageExt; +using MediatR; +using Unit = LanguageExt.Unit; namespace ErsatzTV.Application.MediaCollections.Commands { public class - AddEpisodeToCollectionHandler : MediatR.IRequestHandler> + AddEpisodeToCollectionHandler : IRequestHandler> { private readonly IMediaCollectionRepository _mediaCollectionRepository; private readonly ITelevisionRepository _televisionRepository; @@ -20,15 +23,25 @@ namespace ErsatzTV.Application.MediaCollections.Commands _televisionRepository = televisionRepository; } - public Task> Handle( + public Task> Handle( AddEpisodeToCollection request, CancellationToken cancellationToken) => Validate(request) .MapT(_ => ApplyAddTelevisionEpisodeRequest(request)) .Bind(v => v.ToEitherAsync()); - private Task ApplyAddTelevisionEpisodeRequest(AddEpisodeToCollection request) => - _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.EpisodeId); + private async Task ApplyAddTelevisionEpisodeRequest(AddEpisodeToCollection request) + { + var result = new CollectionUpdateResult(); + + if (await _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.EpisodeId)) + { + result.ModifiedPlayoutIds = + await _mediaCollectionRepository.PlayoutIdsUsingCollection(request.CollectionId); + } + + return result; + } private async Task> Validate(AddEpisodeToCollection request) => (await CollectionMustExist(request), await ValidateEpisode(request)) diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddMovieCollection.cs b/ErsatzTV.Application/MediaCollections/Commands/AddMovieCollection.cs index e9bc90deb..7b0d55512 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddMovieCollection.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddMovieCollection.cs @@ -1,7 +1,9 @@ using ErsatzTV.Core; using LanguageExt; +using MediatR; namespace ErsatzTV.Application.MediaCollections.Commands { - public record AddMovieToCollection(int CollectionId, int MovieId) : MediatR.IRequest>; + public record AddMovieToCollection + (int CollectionId, int MovieId) : IRequest>; } diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddMovieToCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddMovieToCollectionHandler.cs index d0f3d521b..7e858574e 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddMovieToCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddMovieToCollectionHandler.cs @@ -4,10 +4,13 @@ using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using LanguageExt; +using MediatR; +using Unit = LanguageExt.Unit; namespace ErsatzTV.Application.MediaCollections.Commands { - public class AddMovieToCollectionHandler : MediatR.IRequestHandler> + public class + AddMovieToCollectionHandler : IRequestHandler> { private readonly IMediaCollectionRepository _mediaCollectionRepository; private readonly IMovieRepository _movieRepository; @@ -20,15 +23,25 @@ namespace ErsatzTV.Application.MediaCollections.Commands _movieRepository = movieRepository; } - public Task> Handle( + public Task> Handle( AddMovieToCollection request, CancellationToken cancellationToken) => Validate(request) .MapT(_ => ApplyAddMoviesRequest(request)) .Bind(v => v.ToEitherAsync()); - private Task ApplyAddMoviesRequest(AddMovieToCollection request) => - _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.MovieId); + private async Task ApplyAddMoviesRequest(AddMovieToCollection request) + { + var result = new CollectionUpdateResult(); + + if (await _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.MovieId)) + { + result.ModifiedPlayoutIds = + await _mediaCollectionRepository.PlayoutIdsUsingCollection(request.CollectionId); + } + + return result; + } private async Task> Validate(AddMovieToCollection request) => (await CollectionMustExist(request), await ValidateMovies(request)) diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollection.cs b/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollection.cs index e3f795f82..5aea47221 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollection.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollection.cs @@ -1,7 +1,9 @@ using ErsatzTV.Core; using LanguageExt; +using MediatR; namespace ErsatzTV.Application.MediaCollections.Commands { - public record AddSeasonToCollection(int CollectionId, int SeasonId) : MediatR.IRequest>; + public record AddSeasonToCollection + (int CollectionId, int SeasonId) : IRequest>; } diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollectionHandler.cs index 4812be04b..583eaed32 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollectionHandler.cs @@ -4,10 +4,13 @@ using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using LanguageExt; +using MediatR; +using Unit = LanguageExt.Unit; namespace ErsatzTV.Application.MediaCollections.Commands { - public class AddSeasonToCollectionHandler : MediatR.IRequestHandler> + public class + AddSeasonToCollectionHandler : IRequestHandler> { private readonly IMediaCollectionRepository _mediaCollectionRepository; private readonly ITelevisionRepository _televisionRepository; @@ -20,15 +23,25 @@ namespace ErsatzTV.Application.MediaCollections.Commands _televisionRepository = televisionRepository; } - public Task> Handle( + public Task> Handle( AddSeasonToCollection request, CancellationToken cancellationToken) => Validate(request) .MapT(_ => ApplyAddTelevisionSeasonRequest(request)) .Bind(v => v.ToEitherAsync()); - private async Task ApplyAddTelevisionSeasonRequest(AddSeasonToCollection request) => - await _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.SeasonId); + private async Task ApplyAddTelevisionSeasonRequest(AddSeasonToCollection request) + { + var result = new CollectionUpdateResult(); + + if (await _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.SeasonId)) + { + result.ModifiedPlayoutIds = + await _mediaCollectionRepository.PlayoutIdsUsingCollection(request.CollectionId); + } + + return result; + } private async Task> Validate(AddSeasonToCollection request) => (await CollectionMustExist(request), await ValidateSeason(request)) diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollection.cs b/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollection.cs index 48233e6d4..e1c1388a0 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollection.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollection.cs @@ -1,7 +1,9 @@ using ErsatzTV.Core; using LanguageExt; +using MediatR; namespace ErsatzTV.Application.MediaCollections.Commands { - public record AddShowToCollection(int CollectionId, int ShowId) : MediatR.IRequest>; + public record AddShowToCollection + (int CollectionId, int ShowId) : IRequest>; } diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollectionHandler.cs index 9c7e780a9..a6e005d18 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollectionHandler.cs @@ -4,10 +4,13 @@ using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using LanguageExt; +using MediatR; +using Unit = LanguageExt.Unit; namespace ErsatzTV.Application.MediaCollections.Commands { - public class AddShowToCollectionHandler : MediatR.IRequestHandler> + public class + AddShowToCollectionHandler : IRequestHandler> { private readonly IMediaCollectionRepository _mediaCollectionRepository; private readonly ITelevisionRepository _televisionRepository; @@ -20,15 +23,25 @@ namespace ErsatzTV.Application.MediaCollections.Commands _televisionRepository = televisionRepository; } - public Task> Handle( + public Task> Handle( AddShowToCollection request, CancellationToken cancellationToken) => Validate(request) .MapT(_ => ApplyAddTelevisionShowRequest(request)) .Bind(v => v.ToEitherAsync()); - private Task ApplyAddTelevisionShowRequest(AddShowToCollection request) - => _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.ShowId); + private async Task ApplyAddTelevisionShowRequest(AddShowToCollection request) + { + var result = new CollectionUpdateResult(); + + if (await _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.ShowId)) + { + result.ModifiedPlayoutIds = + await _mediaCollectionRepository.PlayoutIdsUsingCollection(request.CollectionId); + } + + return result; + } private async Task> Validate(AddShowToCollection request) => (await CollectionMustExist(request), await ValidateShow(request)) diff --git a/ErsatzTV.Application/MediaCollections/Commands/RemoveItemsFromCollection.cs b/ErsatzTV.Application/MediaCollections/Commands/RemoveItemsFromCollection.cs index 76894eb50..c4d16fc70 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/RemoveItemsFromCollection.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/RemoveItemsFromCollection.cs @@ -1,10 +1,11 @@ using System.Collections.Generic; using ErsatzTV.Core; using LanguageExt; +using MediatR; namespace ErsatzTV.Application.MediaCollections.Commands { - public record RemoveItemsFromCollection(int MediaCollectionId) : MediatR.IRequest> + public record RemoveItemsFromCollection(int MediaCollectionId) : IRequest> { public List MediaItemIds { get; set; } = new(); } diff --git a/ErsatzTV.Application/MediaCollections/Commands/RemoveItemsFromCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/RemoveItemsFromCollectionHandler.cs index 7164e812b..21b09dc7b 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/RemoveItemsFromCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/RemoveItemsFromCollectionHandler.cs @@ -36,15 +36,13 @@ namespace ErsatzTV.Application.MediaCollections.Commands itemsToRemove.ForEach(m => collection.MediaItems.Remove(m)); + var result = new CollectionUpdateResult(); if (itemsToRemove.Any() && await _mediaCollectionRepository.Update(collection)) { - return new CollectionUpdateResult - { - ModifiedPlayoutIds = await _mediaCollectionRepository.PlayoutIdsUsingCollection(collection.Id) - }; + result.ModifiedPlayoutIds = await _mediaCollectionRepository.PlayoutIdsUsingCollection(collection.Id); } - return new CollectionUpdateResult(); + return result; } private Task> Validate( diff --git a/ErsatzTV.Core.Tests/Fakes/FakeMediaCollectionRepository.cs b/ErsatzTV.Core.Tests/Fakes/FakeMediaCollectionRepository.cs index 893e6059b..2323eaa8b 100644 --- a/ErsatzTV.Core.Tests/Fakes/FakeMediaCollectionRepository.cs +++ b/ErsatzTV.Core.Tests/Fakes/FakeMediaCollectionRepository.cs @@ -15,7 +15,7 @@ namespace ErsatzTV.Core.Tests.Fakes public FakeMediaCollectionRepository(Map> data) => _data = data; public Task Add(Collection collection) => throw new NotSupportedException(); - public Task AddMediaItem(int collectionId, int mediaItemId) => throw new NotSupportedException(); + public Task AddMediaItem(int collectionId, int mediaItemId) => throw new NotSupportedException(); public Task> Get(int id) => throw new NotSupportedException(); public Task> GetCollectionWithItems(int id) => throw new NotSupportedException(); public Task> GetCollectionWithItemsUntracked(int id) => throw new NotSupportedException(); diff --git a/ErsatzTV.Core/Interfaces/Repositories/IMediaCollectionRepository.cs b/ErsatzTV.Core/Interfaces/Repositories/IMediaCollectionRepository.cs index d42ccde74..60ddbc70e 100644 --- a/ErsatzTV.Core/Interfaces/Repositories/IMediaCollectionRepository.cs +++ b/ErsatzTV.Core/Interfaces/Repositories/IMediaCollectionRepository.cs @@ -8,7 +8,7 @@ namespace ErsatzTV.Core.Interfaces.Repositories public interface IMediaCollectionRepository { Task Add(Collection collection); - Task AddMediaItem(int collectionId, int mediaItemId); + Task AddMediaItem(int collectionId, int mediaItemId); Task> Get(int id); Task> GetCollectionWithItems(int id); Task> GetCollectionWithItemsUntracked(int id); diff --git a/ErsatzTV.Core/Iptv/ChannelGuide.cs b/ErsatzTV.Core/Iptv/ChannelGuide.cs index 11289b785..fbdb59e0a 100644 --- a/ErsatzTV.Core/Iptv/ChannelGuide.cs +++ b/ErsatzTV.Core/Iptv/ChannelGuide.cs @@ -62,15 +62,18 @@ namespace ErsatzTV.Core.Iptv string title = playoutItem.MediaItem switch { - Movie m => m.MovieMetadata.HeadOrNone().Map(mm => mm.Title ?? string.Empty).IfNone("[unknown movie]"), - Episode e => e.EpisodeMetadata.HeadOrNone().Map(em => em.Title ?? string.Empty).IfNone("[unknown episode]"), + Movie m => m.MovieMetadata.HeadOrNone().Map(mm => mm.Title ?? string.Empty) + .IfNone("[unknown movie]"), + Episode e => e.EpisodeMetadata.HeadOrNone().Map(em => em.Title ?? string.Empty) + .IfNone("[unknown episode]"), _ => "[unknown]" }; string description = playoutItem.MediaItem switch { Movie m => m.MovieMetadata.HeadOrNone().Map(mm => mm.Plot ?? string.Empty).IfNone(string.Empty), - Episode e => e.EpisodeMetadata.HeadOrNone().Map(em => em.Plot ?? string.Empty).IfNone(string.Empty), + Episode e => e.EpisodeMetadata.HeadOrNone().Map(em => em.Plot ?? string.Empty) + .IfNone(string.Empty), _ => string.Empty }; @@ -108,7 +111,7 @@ namespace ErsatzTV.Core.Iptv xml.WriteAttributeString("system", "onscreen"); xml.WriteString($"S{s:00}E{e:00}"); xml.WriteEndElement(); // episode-num - + xml.WriteStartElement("episode-num"); xml.WriteAttributeString("system", "xmltv_ns"); xml.WriteString($"{s - 1}.{e - 1}.0/1"); diff --git a/ErsatzTV.Core/Metadata/FallbackMetadataProvider.cs b/ErsatzTV.Core/Metadata/FallbackMetadataProvider.cs index aa911336d..15cdd7cf1 100644 --- a/ErsatzTV.Core/Metadata/FallbackMetadataProvider.cs +++ b/ErsatzTV.Core/Metadata/FallbackMetadataProvider.cs @@ -34,7 +34,7 @@ namespace ErsatzTV.Core.Metadata return fileName != null ? GetMovieMetadata(fileName, metadata) : metadata; } - + public string GetSortTitle(string title) { if (string.IsNullOrWhiteSpace(title)) diff --git a/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs index b2eb8f53f..0a0afeef0 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs @@ -30,8 +30,10 @@ namespace ErsatzTV.Infrastructure.Data.Repositories } - public async Task AddMediaItem(int collectionId, int mediaItemId) + public async Task AddMediaItem(int collectionId, int mediaItemId) { + var modified = false; + Option maybeCollection = await _dbContext.Collections .Include(c => c.MediaItems) .OrderBy(c => c.Id) @@ -52,12 +54,12 @@ namespace ErsatzTV.Infrastructure.Data.Repositories async mediaItem => { collection.MediaItems.Add(mediaItem); - await _dbContext.SaveChangesAsync(); + modified = await _dbContext.SaveChangesAsync() > 0; }); } }); - return Unit.Default; + return modified; } public Task> Get(int id) => diff --git a/ErsatzTV.Infrastructure/Data/Repositories/MediaSourceRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/MediaSourceRepository.cs index fc21f44dd..bcdf3366c 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/MediaSourceRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/MediaSourceRepository.cs @@ -173,7 +173,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories await _dbConnection.ExecuteAsync( "UPDATE PlexLibrary SET ShouldSyncItems = 0 WHERE Id IN @ids", new { ids = libraryIds }); - + await _dbConnection.ExecuteAsync( "UPDATE Library SET LastScan = null WHERE Id IN @ids", new { ids = libraryIds }); diff --git a/ErsatzTV.Infrastructure/Data/Repositories/MovieRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/MovieRepository.cs index f6b007c8a..ad20a7293 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/MovieRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/MovieRepository.cs @@ -122,7 +122,10 @@ namespace ErsatzTV.Infrastructure.Data.Repositories } } - private async Task> AddPlexMovie(TvContext context, PlexLibrary library, PlexMovie item) + private async Task> AddPlexMovie( + TvContext context, + PlexLibrary library, + PlexMovie item) { try { diff --git a/ErsatzTV.Infrastructure/Plex/PlexServerApiClient.cs b/ErsatzTV.Infrastructure/Plex/PlexServerApiClient.cs index 0447915bb..650d75a16 100644 --- a/ErsatzTV.Infrastructure/Plex/PlexServerApiClient.cs +++ b/ErsatzTV.Infrastructure/Plex/PlexServerApiClient.cs @@ -18,10 +18,8 @@ namespace ErsatzTV.Infrastructure.Plex { private readonly IFallbackMetadataProvider _fallbackMetadataProvider; - public PlexServerApiClient(IFallbackMetadataProvider fallbackMetadataProvider) - { + public PlexServerApiClient(IFallbackMetadataProvider fallbackMetadataProvider) => _fallbackMetadataProvider = fallbackMetadataProvider; - } public async Task>> GetLibraries( PlexConnection connection, @@ -150,7 +148,7 @@ namespace ErsatzTV.Infrastructure.Plex } private static string ConvertToSAR(double aspectRatio) => "1:1"; - // TODO: fix this with more detailed stats pull from plex for each item - // Math.Abs(aspectRatio - 1) < 0.01 ? "1:1" : $"{(int) (aspectRatio * 100)}:100"; + // TODO: fix this with more detailed stats pull from plex for each item + // Math.Abs(aspectRatio - 1) < 0.01 ? "1:1" : $"{(int) (aspectRatio * 100)}:100"; } } diff --git a/ErsatzTV/Extensions/HostExtensions.cs b/ErsatzTV/Extensions/HostExtensions.cs index bce49bcbb..1bc1a6763 100644 --- a/ErsatzTV/Extensions/HostExtensions.cs +++ b/ErsatzTV/Extensions/HostExtensions.cs @@ -36,7 +36,10 @@ namespace ErsatzTV.Extensions .IfFail( ex => { - LogException(ex, "Error occured while migrating database; shutting down.", scope.ServiceProvider); + LogException( + ex, + "Error occured while migrating database; shutting down.", + scope.ServiceProvider); Environment.Exit(13); return unit; }); diff --git a/ErsatzTV/Pages/CollectionItems.razor b/ErsatzTV/Pages/CollectionItems.razor index 6d0c79443..766584d5b 100644 --- a/ErsatzTV/Pages/CollectionItems.razor +++ b/ErsatzTV/Pages/CollectionItems.razor @@ -9,6 +9,7 @@ @inject ILogger Logger @inject ISnackbar Snackbar @inject IDialogService Dialog +@inject ChannelWriter Channel
@_data.Name @@ -169,7 +170,7 @@ { foreach (int playoutId in collectionUpdateResult.ModifiedPlayoutIds) { - await Mediator.Send(new BuildPlayout(playoutId, true)); + await Channel.WriteAsync(new BuildPlayout(playoutId, true)); } }, _ => Task.CompletedTask); diff --git a/ErsatzTV/Pages/MovieList.razor b/ErsatzTV/Pages/MovieList.razor index e312f82d5..ea294287f 100644 --- a/ErsatzTV/Pages/MovieList.razor +++ b/ErsatzTV/Pages/MovieList.razor @@ -4,12 +4,13 @@ @using ErsatzTV.Application.MediaCards.Queries @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaCollections.Commands -@using Unit = LanguageExt.Unit +@using ErsatzTV.Application.Playouts.Commands @inject ILogger Logger @inject ISnackbar Snackbar @inject IMediator Mediator @inject IDialogService Dialog @inject NavigationManager NavigationManager +@inject ChannelWriter Channel @@ -73,14 +74,22 @@ if (!result.Cancelled && result.Data is MediaCollectionViewModel collection) { var request = new AddMovieToCollection(collection.Id, movie.MovieId); - Either addResult = await Mediator.Send(request); - addResult.Match( + Either addResult = await Mediator.Send(request); + await addResult.Match( Left: error => { Snackbar.Add($"Unexpected error adding movie to collection: {error.Value}"); Logger.LogError("Unexpected error adding movie to collection: {Error}", error.Value); + return Task.CompletedTask; }, - Right: _ => Snackbar.Add($"Added {movie.Title} to collection {collection.Name}", Severity.Success)); + Right: async collectionUpdateResult => + { + foreach (int playoutId in collectionUpdateResult.ModifiedPlayoutIds) + { + await Channel.WriteAsync(new BuildPlayout(playoutId, true)); + } + Snackbar.Add($"Added {movie.Title} to collection {collection.Name}", Severity.Success); + }); } } } diff --git a/ErsatzTV/Pages/Search.razor b/ErsatzTV/Pages/Search.razor index e18b378fe..3d14582ec 100644 --- a/ErsatzTV/Pages/Search.razor +++ b/ErsatzTV/Pages/Search.razor @@ -3,14 +3,15 @@ @using ErsatzTV.Application.MediaCards.Queries @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaCollections.Commands +@using ErsatzTV.Application.Playouts.Commands @using Microsoft.AspNetCore.WebUtilities @using Microsoft.Extensions.Primitives -@using Unit = LanguageExt.Unit @inject NavigationManager NavigationManager @inject IMediator Mediator @inject ILogger Logger @inject ISnackbar Snackbar @inject IDialogService Dialog +@inject ChannelWriter Channel
@@ -74,14 +75,21 @@ if (!result.Cancelled && result.Data is MediaCollectionViewModel collection) { var request = new AddMovieToCollection(collection.Id, movie.MovieId); - Either addResult = await Mediator.Send(request); + Either addResult = await Mediator.Send(request); addResult.Match( Left: error => { Snackbar.Add($"Unexpected error adding movie to collection: {error.Value}"); Logger.LogError("Unexpected error adding movie to collection: {Error}", error.Value); }, - Right: _ => Snackbar.Add($"Added {movie.Title} to collection {collection.Name}", Severity.Success)); + Right: async collectionUpdateResult => + { + foreach (int playoutId in collectionUpdateResult.ModifiedPlayoutIds) + { + await Channel.WriteAsync(new BuildPlayout(playoutId, true)); + } + Snackbar.Add($"Added {movie.Title} to collection {collection.Name}", Severity.Success); + }); } } @@ -95,14 +103,21 @@ if (!result.Cancelled && result.Data is MediaCollectionViewModel collection) { var request = new AddShowToCollection(collection.Id, show.TelevisionShowId); - Either addResult = await Mediator.Send(request); + Either addResult = await Mediator.Send(request); addResult.Match( Left: error => { Snackbar.Add($"Unexpected error adding show to collection: {error.Value}"); Logger.LogError("Unexpected error adding show to collection: {Error}", error.Value); }, - Right: _ => Snackbar.Add($"Added {show.Title} to collection {collection.Name}", Severity.Success)); + Right: async collectionUpdateResult => + { + foreach (int playoutId in collectionUpdateResult.ModifiedPlayoutIds) + { + await Channel.WriteAsync(new BuildPlayout(playoutId, true)); + } + Snackbar.Add($"Added {show.Title} to collection {collection.Name}", Severity.Success); + }); } } } diff --git a/ErsatzTV/Pages/TelevisionEpisodeList.razor b/ErsatzTV/Pages/TelevisionEpisodeList.razor index 430d83b55..e79016a11 100644 --- a/ErsatzTV/Pages/TelevisionEpisodeList.razor +++ b/ErsatzTV/Pages/TelevisionEpisodeList.razor @@ -5,14 +5,15 @@ @using ErsatzTV.Application.MediaCards.Queries @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaCollections.Commands +@using ErsatzTV.Application.Playouts.Commands @using ErsatzTV.Application.ProgramSchedules @using ErsatzTV.Application.ProgramSchedules.Commands -@using Unit=LanguageExt.Unit; @inject IMediator Mediator @inject ILogger Logger @inject ISnackbar Snackbar @inject IDialogService Dialog @inject NavigationManager NavigationManager +@inject ChannelWriter Channel @@ -122,7 +123,7 @@ NavigationManager.NavigateTo($"/schedules/{schedule.Id}/items"); } } - + private async Task AddEpisodeToCollection(MediaCardViewModel card) { if (card is TelevisionEpisodeCardViewModel episode) @@ -135,14 +136,21 @@ if (!result.Cancelled && result.Data is MediaCollectionViewModel collection) { var request = new AddEpisodeToCollection(collection.Id, episode.EpisodeId); - Either addResult = await Mediator.Send(request); + Either addResult = await Mediator.Send(request); addResult.Match( Left: error => { Snackbar.Add($"Unexpected error adding episode to collection: {error.Value}"); Logger.LogError("Unexpected error adding episode to collection: {Error}", error.Value); }, - Right: _ => Snackbar.Add($"Added {episode.Title} to collection {collection.Name}", Severity.Success)); + Right: async collectionUpdateResult => + { + foreach (int playoutId in collectionUpdateResult.ModifiedPlayoutIds) + { + await Channel.WriteAsync(new BuildPlayout(playoutId, true)); + } + Snackbar.Add($"Added {episode.Title} to collection {collection.Name}", Severity.Success); + }); } } } diff --git a/ErsatzTV/Pages/TelevisionSeasonList.razor b/ErsatzTV/Pages/TelevisionSeasonList.razor index 64dfd2569..a8ea317b0 100644 --- a/ErsatzTV/Pages/TelevisionSeasonList.razor +++ b/ErsatzTV/Pages/TelevisionSeasonList.razor @@ -5,14 +5,15 @@ @using ErsatzTV.Application.MediaCards.Queries @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaCollections.Commands +@using ErsatzTV.Application.Playouts.Commands @using ErsatzTV.Application.ProgramSchedules @using ErsatzTV.Application.ProgramSchedules.Commands -@using Unit=LanguageExt.Unit; @inject IMediator Mediator @inject ILogger Logger @inject ISnackbar Snackbar @inject IDialogService Dialog @inject NavigationManager NavigationManager +@inject ChannelWriter Channel @@ -116,7 +117,7 @@ NavigationManager.NavigateTo($"/schedules/{schedule.Id}/items"); } } - + private async Task AddSeasonToCollection(MediaCardViewModel card) { if (card is TelevisionSeasonCardViewModel season) @@ -129,14 +130,21 @@ if (!result.Cancelled && result.Data is MediaCollectionViewModel collection) { var request = new AddSeasonToCollection(collection.Id, season.TelevisionSeasonId); - Either addResult = await Mediator.Send(request); + Either addResult = await Mediator.Send(request); 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} to collection {collection.Name}", Severity.Success)); + Right: async collectionUpdateResult => + { + foreach (int playoutId in collectionUpdateResult.ModifiedPlayoutIds) + { + await Channel.WriteAsync(new BuildPlayout(playoutId, true)); + } + Snackbar.Add($"Added {season.Title} to collection {collection.Name}", Severity.Success); + }); } } } diff --git a/ErsatzTV/Pages/TelevisionShowList.razor b/ErsatzTV/Pages/TelevisionShowList.razor index 2924ce570..15d774c23 100644 --- a/ErsatzTV/Pages/TelevisionShowList.razor +++ b/ErsatzTV/Pages/TelevisionShowList.razor @@ -3,11 +3,12 @@ @using ErsatzTV.Application.MediaCards.Queries @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaCollections.Commands -@using Unit = LanguageExt.Unit +@using ErsatzTV.Application.Playouts.Commands @inject ILogger Logger @inject ISnackbar Snackbar @inject IMediator Mediator @inject IDialogService Dialog +@inject ChannelWriter Channel @@ -69,14 +70,21 @@ if (!result.Cancelled && result.Data is MediaCollectionViewModel collection) { var request = new AddShowToCollection(collection.Id, show.TelevisionShowId); - Either addResult = await Mediator.Send(request); + Either addResult = await Mediator.Send(request); addResult.Match( Left: error => { Snackbar.Add($"Unexpected error adding show to collection: {error.Value}"); Logger.LogError("Unexpected error adding show to collection: {Error}", error.Value); }, - Right: _ => Snackbar.Add($"Added {show.Title} to collection {collection.Name}", Severity.Success)); + Right: async collectionUpdateResult => + { + foreach (int playoutId in collectionUpdateResult.ModifiedPlayoutIds) + { + await Channel.WriteAsync(new BuildPlayout(playoutId, true)); + } + Snackbar.Add($"Added {show.Title} to collection {collection.Name}", Severity.Success); + }); } } } diff --git a/ErsatzTV/Shared/MainLayout.razor b/ErsatzTV/Shared/MainLayout.razor index 1ade69772..5dbe09036 100644 --- a/ErsatzTV/Shared/MainLayout.razor +++ b/ErsatzTV/Shared/MainLayout.razor @@ -67,7 +67,7 @@ private static readonly string InfoVersion = Assembly.GetEntryAssembly().GetCustomAttribute()?.InformationalVersion ?? "unknown"; private MudTextField _textField; - + private MudTheme _ersatzTvTheme { get diff --git a/ErsatzTV/Shared/MediaCard.razor b/ErsatzTV/Shared/MediaCard.razor index 6f78a7e2a..4ef1d8cb4 100644 --- a/ErsatzTV/Shared/MediaCard.razor +++ b/ErsatzTV/Shared/MediaCard.razor @@ -21,7 +21,7 @@ { } @if (DeleteClicked.HasDelegate) diff --git a/ErsatzTV/wwwroot/browserconfig.xml b/ErsatzTV/wwwroot/browserconfig.xml index b3930d0f0..c6f1bea66 100644 --- a/ErsatzTV/wwwroot/browserconfig.xml +++ b/ErsatzTV/wwwroot/browserconfig.xml @@ -1,9 +1,10 @@ + - + #da532c - + \ No newline at end of file diff --git a/ErsatzTV/wwwroot/css/site.css b/ErsatzTV/wwwroot/css/site.css index 9d0ae74bb..29d0d7136 100644 --- a/ErsatzTV/wwwroot/css/site.css +++ b/ErsatzTV/wwwroot/css/site.css @@ -4,13 +4,9 @@ flex-wrap: wrap; } -.media-card-container { - width: 152px; -} +.media-card-container { width: 152px; } -.media-card-episode-container { - width: 392px; -} +.media-card-episode-container { width: 392px; } .media-card { display: flex; @@ -22,12 +18,9 @@ width: 152px; } -.media-card-episode { - width: 392px; -} +.media-card-episode { width: 392px; } -.media-card:hover { /*filter: brightness(75%);*/ -} +.media-card:hover { /*filter: brightness(75%);*/ } .media-card-title { overflow: hidden; @@ -36,9 +29,7 @@ width: 100%; } -.media-card-poster-placeholder { - font-weight: bold; -} +.media-card-poster-placeholder { font-weight: bold; } .media-card-menu { bottom: 0; @@ -47,9 +38,7 @@ right: 0; } -.media-card:hover .media-card-menu { - display: block; -} +.media-card:hover .media-card-menu { display: block; } .media-card-overlay { background: rgba(0, 0, 0, 0.4); @@ -63,26 +52,20 @@ transition: opacity 0.2s; } -.media-card-overlay:hover { - opacity: 1; -} +.media-card-overlay:hover { opacity: 1; } -.search-bar .mud-input { - height: 42px; -} +.search-bar .mud-input { height: 42px; } .search-bar { background-color: rgba(255, 255, 255, .15); - margin-bottom: 5px; - height: 42px; border-radius: 4px; + height: 42px; + margin-bottom: 5px; } -.search-bar div .mud-input-root { - color: #fafafa; -} +.search-bar div .mud-input-root { color: #fafafa; } .search-bar .mud-input.mud-input-outlined .mud-input-outlined-border { border: none; border-radius: 4px; -} +} \ No newline at end of file