From a87ec2d75d6dd9b134c1c4a7a78275fd0711f153 Mon Sep 17 00:00:00 2001 From: Jason Dove <1695733+jasongdove@users.noreply.github.com> Date: Mon, 6 May 2024 17:00:52 -0500 Subject: [PATCH] cleanup (#1708) * fix blazor naming * code cleanup * update dependencies --- .config/dotnet-tools.json | 2 +- .../Commands/RefreshChannelDataHandler.cs | 64 -- .../Commands/RefreshChannelListHandler.cs | 5 - .../ErsatzTV.Application.csproj | 2 +- .../Commands/AddEpisodeToCollectionHandler.cs | 4 +- .../Commands/AddMovieToPlaylistHandler.cs | 8 +- .../AddMusicVideoToCollectionHandler.cs | 4 +- .../AddOtherVideoToCollectionHandler.cs | 4 +- .../Commands/CreatePlaylistGroupHandler.cs | 4 +- .../Commands/PreviewPlaylistPlayoutHandler.cs | 4 +- .../Commands/ReplacePlaylistItemsHandler.cs | 9 +- .../MediaCollections/Mapper.cs | 2 +- .../Queries/GetAllPlaylistGroupsHandler.cs | 4 +- ErsatzTV.Application/MediaItems/Mapper.cs | 6 +- .../Scheduling/Commands/CreateDecoTemplate.cs | 3 +- .../ReplaceDecoTemplateItemsHandler.cs | 10 +- .../Scheduling/Commands/UpdateDecoHandler.cs | 6 +- .../Commands/UpdateDefaultDecoHandler.cs | 3 +- ErsatzTV.Application/Scheduling/Mapper.cs | 3 +- .../Queries/GetDecoTemplateByIdHandler.cs | 4 +- .../Queries/GetDecoTemplateItemsHandler.cs | 4 +- .../Streaming/HlsSessionWorker.cs | 2 +- .../Streaming/HlsSessionWorkerV2.cs | 3 +- .../GetHlsPlaylistByChannelNumberHandler.cs | 4 +- ...layoutItemProcessByChannelNumberHandler.cs | 10 +- .../GetWrappedProcessByChannelNumber.cs | 6 +- .../Emby/EmbyPathReplacementServiceTests.cs | 2 +- .../ErsatzTV.Core.Tests.csproj | 2 +- .../JellyfinPathReplacementServiceTests.cs | 2 +- .../Plex/PlexPathReplacementServiceTests.cs | 2 +- .../PlayoutTemplateSelectorTests.cs | 36 +- ErsatzTV.Core/Domain/Collection/Playlist.cs | 1 + .../Domain/Scheduling/PlayoutTemplate.cs | 1 + .../Emby/EmbyPathReplacementService.cs | 3 +- ErsatzTV.Core/ErsatzTV.Core.csproj | 2 +- .../FFmpeg/FFmpegLibraryProcessService.cs | 2 +- ErsatzTV.Core/FileSystemLayout.cs | 2 +- .../JellyfinPathReplacementService.cs | 3 +- .../Plex/PlexPathReplacementService.cs | 3 +- ...layoutShuffledMediaCollectionEnumerator.cs | 2 +- ErsatzTV.Core/Scheduling/CollectionKey.cs | 2 +- .../Scheduling/MediaItemsForCollection.cs | 6 + .../Scheduling/PlaylistEnumerator.cs | 109 ++-- ErsatzTV.Core/Scheduling/PlayoutBuilder.cs | 4 +- .../PlayoutModeSchedulerDuration.cs | 3 +- .../Scheduling/PlayoutModeSchedulerFlood.cs | 3 +- .../PlayoutModeSchedulerMultiple.cs | 3 +- .../Scheduling/PlayoutModeSchedulerOne.cs | 3 +- .../Scheduling/PlayoutTemplateSelector.cs | 4 +- ErsatzTV.Core/Scheduling/SuperShuffle.cs | 2 +- ErsatzTV.FFmpeg/Encoder/Amf/EncoderH264Amf.cs | 4 +- ErsatzTV.FFmpeg/Encoder/EncoderLibx264.cs | 4 +- ErsatzTV.FFmpeg/Encoder/EncoderLibx265.cs | 2 +- .../Encoder/Nvenc/EncoderH264Nvenc.cs | 2 +- .../Encoder/Nvenc/EncoderHevcNvenc.cs | 6 +- ErsatzTV.FFmpeg/Encoder/Qsv/EncoderH264Qsv.cs | 4 +- ErsatzTV.FFmpeg/Encoder/Qsv/EncoderHevcQsv.cs | 2 +- .../Encoder/Vaapi/EncoderH264Vaapi.cs | 2 +- .../VideoToolbox/EncoderH264VideoToolbox.cs | 4 +- .../Pipeline/PipelineBuilderBase.cs | 5 +- ErsatzTV.FFmpeg/Preset/AvailablePresets.cs | 6 +- ErsatzTV.FFmpeg/Preset/VideoPreset.cs | 4 +- .../ErsatzTV.Infrastructure.Tests.csproj | 2 +- .../Collection/PlaylistConfiguration.cs | 3 +- .../Collection/PlaylistItemConfiguration.cs | 2 +- .../ProgramScheduleItemConfiguration.cs | 2 +- .../Scheduling/DecoConfiguration.cs | 2 +- .../Repositories/MediaCollectionRepository.cs | 34 +- .../ErsatzTV.Infrastructure.csproj | 6 +- ErsatzTV.Infrastructure/Plex/PlexEtag.cs | 4 +- ...MultiEpisodeShuffleCollectionEnumerator.cs | 2 +- .../Search/CustomMultiFieldQueryParser.cs | 10 +- .../Search/LuceneSearchIndex.cs | 6 +- .../Search/Models/ElasticSearchItem.cs | 2 +- .../Search/SearchQueryParser.cs | 12 +- .../ErsatzTV.Scanner.Tests.csproj | 2 +- .../Core/Metadata/ImageFolderScanner.cs | 2 +- .../Core/Metadata/MusicVideoFolderScanner.cs | 2 +- .../Core/Metadata/OtherVideoFolderScanner.cs | 6 +- .../Core/Metadata/SongFolderScanner.cs | 4 +- .../Core/Metadata/TelevisionFolderScanner.cs | 4 +- .../Core/Plex/PlexTelevisionLibraryScanner.cs | 2 +- ErsatzTV/Controllers/IptvController.cs | 10 +- ErsatzTV/ErsatzTV.csproj | 4 +- ErsatzTV/Pages/Artist.razor | 40 +- ErsatzTV/Pages/ArtistList.razor | 11 +- ErsatzTV/Pages/BlockEditor.razor | 4 +- ErsatzTV/Pages/BlockPlayoutEditor.razor | 155 ++--- ErsatzTV/Pages/Blocks.razor | 2 +- ErsatzTV/Pages/ChannelEditor.razor | 4 +- ErsatzTV/Pages/Channels.razor | 2 +- ErsatzTV/Pages/CollectionEditor.razor | 18 +- ErsatzTV/Pages/Collections.razor | 4 +- ErsatzTV/Pages/DecoEditor.razor | 287 ++++----- ErsatzTV/Pages/DecoTemplateEditor.razor | 2 +- ErsatzTV/Pages/DecoTemplates.razor | 2 +- ErsatzTV/Pages/Decos.razor | 2 +- ErsatzTV/Pages/EmbyLibrariesEditor.razor | 14 +- ErsatzTV/Pages/EmbyMediaSourceEditor.razor | 11 +- ErsatzTV/Pages/EmbyMediaSources.razor | 10 +- .../Pages/EmbyPathReplacementsEditor.razor | 11 +- ErsatzTV/Pages/EpisodeList.razor | 11 +- ErsatzTV/Pages/FFmpegEditor.razor | 8 +- ErsatzTV/Pages/FillerPresetEditor.razor | 34 +- ErsatzTV/Pages/FillerPresets.razor | 16 +- ErsatzTV/Pages/ImageBrowser.razor | 4 +- ErsatzTV/Pages/ImageList.razor | 2 +- ErsatzTV/Pages/Index.razor | 4 +- ErsatzTV/Pages/JellyfinLibrariesEditor.razor | 14 +- .../Pages/JellyfinMediaSourceEditor.razor | 11 +- ErsatzTV/Pages/JellyfinMediaSources.razor | 10 +- .../JellyfinPathReplacementsEditor.razor | 11 +- ErsatzTV/Pages/Libraries.razor | 6 +- ErsatzTV/Pages/LocalLibraries.razor | 26 +- ErsatzTV/Pages/LocalLibraryEditor.razor | 48 +- ErsatzTV/Pages/LocalLibraryPathEditor.razor | 28 +- ErsatzTV/Pages/Logs.razor | 2 +- ErsatzTV/Pages/Movie.razor | 8 +- ErsatzTV/Pages/MovieList.razor | 2 +- ErsatzTV/Pages/MultiCollectionEditor.razor | 24 +- ErsatzTV/Pages/MultiSelectBase.cs | 4 +- ErsatzTV/Pages/MusicVideoList.razor | 11 +- ErsatzTV/Pages/OtherVideoList.razor | 2 +- ErsatzTV/Pages/PlaylistEditor.razor | 4 +- ErsatzTV/Pages/Playlists.razor | 2 +- .../PlayoutAlternateSchedulesEditor.razor | 6 +- ErsatzTV/Pages/PlayoutTemplatesEditor.razor | 554 ++++++++--------- ErsatzTV/Pages/Playouts.razor | 4 +- ErsatzTV/Pages/PlexLibrariesEditor.razor | 10 +- ErsatzTV/Pages/PlexMediaSources.razor | 52 +- .../Pages/PlexPathReplacementsEditor.razor | 9 +- ErsatzTV/Pages/ScheduleItemsEditor.razor | 580 +++++++++--------- ErsatzTV/Pages/Schedules.razor | 2 +- ErsatzTV/Pages/Search.razor | 27 +- ErsatzTV/Pages/Settings.razor | 2 +- ErsatzTV/Pages/SongList.razor | 11 +- ErsatzTV/Pages/TelevisionEpisodeList.razor | 72 +-- ErsatzTV/Pages/TelevisionSeasonList.razor | 47 +- .../Pages/TelevisionSeasonSearchResults.razor | 11 +- ErsatzTV/Pages/TelevisionShowList.razor | 2 +- ErsatzTV/Pages/TemplateEditor.razor | 2 +- ErsatzTV/Pages/Templates.razor | 2 +- ErsatzTV/Pages/TraktLists.razor | 50 +- ErsatzTV/Pages/Trash.razor | 24 +- ErsatzTV/Pages/Troubleshooting.razor | 4 +- ErsatzTV/Pages/WatermarkEditor.razor | 2 +- ErsatzTV/Pages/Watermarks.razor | 18 +- ErsatzTV/Shared/AddToCollectionDialog.razor | 26 +- ErsatzTV/Shared/AddToPlaylistDialog.razor | 6 +- ErsatzTV/Shared/AddToScheduleDialog.razor | 4 +- ErsatzTV/Shared/AddTraktListDialog.razor | 8 +- ErsatzTV/Shared/CopyFFmpegProfileDialog.razor | 12 +- ErsatzTV/Shared/CopyWatermarkDialog.razor | 12 +- .../Shared/DeleteFromDatabaseDialog.razor | 4 +- ErsatzTV/Shared/LetterBar.razor | 4 +- ErsatzTV/Shared/MainLayout.razor | 2 +- ErsatzTV/Shared/MediaCard.razor | 4 +- ErsatzTV/Shared/MediaItemInfoDialog.razor | 4 +- .../Shared/MoveLocalLibraryPathDialog.razor | 26 +- ErsatzTV/Shared/RemoteMediaSourceEditor.razor | 14 +- .../RemoteMediaSourceLibrariesEditor.razor | 22 +- ...oteMediaSourcePathReplacementsEditor.razor | 18 +- .../Shared/RemoveFromCollectionDialog.razor | 4 +- .../Shared/SaveAsSmartCollectionDialog.razor | 26 +- ErsatzTV/Shared/SchedulePlayoutReset.razor | 12 +- ErsatzTV/Startup.cs | 17 +- .../ViewModels/PlaylistItemEditViewModel.cs | 2 +- .../PlayoutTemplateEditViewModel.cs | 12 +- 168 files changed, 1543 insertions(+), 1608 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 393d69891..bfbc2e133 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2023.3.3", + "version": "2024.1.1", "commands": [ "jb" ] diff --git a/ErsatzTV.Application/Channels/Commands/RefreshChannelDataHandler.cs b/ErsatzTV.Application/Channels/Commands/RefreshChannelDataHandler.cs index 20d3f9773..934e98d22 100644 --- a/ErsatzTV.Application/Channels/Commands/RefreshChannelDataHandler.cs +++ b/ErsatzTV.Application/Channels/Commands/RefreshChannelDataHandler.cs @@ -956,68 +956,6 @@ public class RefreshChannelDataHandler : IRequestHandler }; } - private static string GetDescription(PlayoutItem playoutItem) - { - if (!string.IsNullOrWhiteSpace(playoutItem.CustomTitle)) - { - return string.Empty; - } - - return 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), - MusicVideo mv => mv.MusicVideoMetadata.HeadOrNone().Map(mvm => mvm.Plot ?? string.Empty) - .IfNone(string.Empty), - OtherVideo ov => ov.OtherVideoMetadata.HeadOrNone().Map(ovm => ovm.Plot ?? string.Empty) - .IfNone(string.Empty), - _ => string.Empty - }; - } - - private Option GetContentRating(PlayoutItem playoutItem) - { - try - { - return playoutItem.MediaItem switch - { - Movie m => m.MovieMetadata - .HeadOrNone() - .Match(mm => ParseContentRating(mm.ContentRating, "MPAA"), () => None), - Episode e => e.Season.Show.ShowMetadata - .HeadOrNone() - .Match(sm => ParseContentRating(sm.ContentRating, "VCHIP"), () => None), - _ => None - }; - } - catch (Exception ex) - { - _logger.LogWarning(ex, "Failed to get content rating for playout item {Item}", GetTitle(playoutItem)); - return None; - } - } - - private static Option ParseContentRating(string contentRating, string system) - { - Option maybeFirst = (contentRating ?? string.Empty).Split('/').HeadOrNone(); - return maybeFirst.Map( - first => - { - string[] split = first.Split(':'); - if (split.Length == 2) - { - return split[0].Equals("us", StringComparison.OrdinalIgnoreCase) - ? new ContentRating(system, split[1].ToUpperInvariant()) - : new ContentRating(None, split[1].ToUpperInvariant()); - } - - return string.IsNullOrWhiteSpace(first) - ? Option.None - : new ContentRating(None, first); - }).Flatten(); - } - private static string GetPrioritizedArtworkPath(Metadata metadata) { Option maybeArtwork = Optional(metadata.Artwork).Flatten() @@ -1179,6 +1117,4 @@ public class RefreshChannelDataHandler : IRequestHandler ] }; } - - private sealed record ContentRating(Option System, string Value); } diff --git a/ErsatzTV.Application/Channels/Commands/RefreshChannelListHandler.cs b/ErsatzTV.Application/Channels/Commands/RefreshChannelListHandler.cs index ed13c3081..ecaa237cc 100644 --- a/ErsatzTV.Application/Channels/Commands/RefreshChannelListHandler.cs +++ b/ErsatzTV.Application/Channels/Commands/RefreshChannelListHandler.cs @@ -132,11 +132,6 @@ public class RefreshChannelListHandler : IRequestHandler .Distinct() .ToList(); - private static string GetIconUrl(ChannelResult channel) => - string.IsNullOrWhiteSpace(channel.ArtworkPath) - ? "{RequestBase}/iptv/images/ersatztv-500.png{AccessTokenUri}" - : $"{{RequestBase}}/iptv/logos/{channel.ArtworkPath}.jpg{{AccessTokenUri}}"; - // ReSharper disable once ClassNeverInstantiated.Local private sealed record ChannelResult(string Number, string Name, string Categories, string ArtworkPath); } diff --git a/ErsatzTV.Application/ErsatzTV.Application.csproj b/ErsatzTV.Application/ErsatzTV.Application.csproj index 71da7f96c..48709b163 100644 --- a/ErsatzTV.Application/ErsatzTV.Application.csproj +++ b/ErsatzTV.Application/ErsatzTV.Application.csproj @@ -15,7 +15,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs index 36b1deaeb..bcc49bed1 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs @@ -33,7 +33,9 @@ public class AddEpisodeToCollectionHandler : { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); Validation validation = await Validate(dbContext, request); - return await validation.Apply(parameters => ApplyAddTelevisionEpisodeRequest(dbContext, parameters)); + return await LanguageExtensions.Apply( + validation, + parameters => ApplyAddTelevisionEpisodeRequest(dbContext, parameters)); } private async Task ApplyAddTelevisionEpisodeRequest(TvContext dbContext, Parameters parameters) diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddMovieToPlaylistHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddMovieToPlaylistHandler.cs index a4cf96d1e..1a3adf964 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddMovieToPlaylistHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddMovieToPlaylistHandler.cs @@ -1,9 +1,5 @@ -using System.Threading.Channels; -using ErsatzTV.Application.Playouts; -using ErsatzTV.Core; +using ErsatzTV.Core; using ErsatzTV.Core.Domain; -using ErsatzTV.Core.Interfaces.Repositories; -using ErsatzTV.Core.Scheduling; using ErsatzTV.Infrastructure.Data; using ErsatzTV.Infrastructure.Extensions; using Microsoft.EntityFrameworkCore; @@ -32,7 +28,7 @@ public class AddMovieToPlaylistHandler(IDbContextFactory dbContextFac PlaybackOrder = PlaybackOrder.Shuffle, IncludeInProgramGuide = true }; - + parameters.Playlist.Items.Add(playlistItem); await dbContext.SaveChangesAsync(); return Unit.Default; diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddMusicVideoToCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddMusicVideoToCollectionHandler.cs index 6af44700d..1d468dd75 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddMusicVideoToCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddMusicVideoToCollectionHandler.cs @@ -33,7 +33,9 @@ public class AddMusicVideoToCollectionHandler : { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); Validation validation = await Validate(dbContext, request); - return await validation.Apply(parameters => ApplyAddMusicVideoRequest(dbContext, parameters)); + return await LanguageExtensions.Apply( + validation, + parameters => ApplyAddMusicVideoRequest(dbContext, parameters)); } private async Task ApplyAddMusicVideoRequest(TvContext dbContext, Parameters parameters) diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddOtherVideoToCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddOtherVideoToCollectionHandler.cs index 9ac8a4ad0..5f9b847ca 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddOtherVideoToCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddOtherVideoToCollectionHandler.cs @@ -33,7 +33,9 @@ public class AddOtherVideoToCollectionHandler : { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); Validation validation = await Validate(dbContext, request); - return await validation.Apply(parameters => ApplyAddOtherVideoRequest(dbContext, parameters)); + return await LanguageExtensions.Apply( + validation, + parameters => ApplyAddOtherVideoRequest(dbContext, parameters)); } private async Task ApplyAddOtherVideoRequest(TvContext dbContext, Parameters parameters) diff --git a/ErsatzTV.Application/MediaCollections/Commands/CreatePlaylistGroupHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/CreatePlaylistGroupHandler.cs index a11f4c21a..ebbc6173d 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/CreatePlaylistGroupHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/CreatePlaylistGroupHandler.cs @@ -17,7 +17,9 @@ public class CreatePlaylistGroupHandler(IDbContextFactory dbContextFa return await validation.Apply(profile => PersistPlaylistGroup(dbContext, profile)); } - private static async Task PersistPlaylistGroup(TvContext dbContext, PlaylistGroup playlistGroup) + private static async Task PersistPlaylistGroup( + TvContext dbContext, + PlaylistGroup playlistGroup) { await dbContext.PlaylistGroups.AddAsync(playlistGroup); await dbContext.SaveChangesAsync(); diff --git a/ErsatzTV.Application/MediaCollections/Commands/PreviewPlaylistPlayoutHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/PreviewPlaylistPlayoutHandler.cs index 905ec5dc1..fc4f49c68 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/PreviewPlaylistPlayoutHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/PreviewPlaylistPlayoutHandler.cs @@ -46,7 +46,7 @@ public class PreviewPlaylistPlayoutHandler( playoutBuilder.DebugPlaylist = playout.ProgramSchedule.Items[0].Playlist; await playoutBuilder.Build(playout, PlayoutBuildMode.Reset, cancellationToken); - int maxItems = 0; + var maxItems = 0; Dictionary> map = await mediaCollectionRepository.GetPlaylistItemMap(playout.ProgramSchedule.Items[0].Playlist); foreach (PlaylistItem item in playout.ProgramSchedule.Items[0].Playlist.Items) @@ -94,7 +94,7 @@ public class PreviewPlaylistPlayoutHandler( playoutItem.MediaItem = mediaItem; } } - + return playout.Items.OrderBy(i => i.StartOffset).Map(Scheduling.Mapper.ProjectToViewModel).ToList(); } diff --git a/ErsatzTV.Application/MediaCollections/Commands/ReplacePlaylistItemsHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/ReplacePlaylistItemsHandler.cs index f18903c35..d8292914d 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/ReplacePlaylistItemsHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/ReplacePlaylistItemsHandler.cs @@ -1,6 +1,5 @@ using ErsatzTV.Core; using ErsatzTV.Core.Domain; -using ErsatzTV.Core.Domain.Scheduling; using ErsatzTV.Infrastructure.Data; using ErsatzTV.Infrastructure.Extensions; using Microsoft.EntityFrameworkCore; @@ -60,10 +59,14 @@ public class ReplacePlaylistItemsHandler(IDbContextFactory dbContextF .SelectOneAsync(b => b.Id, b => b.Id == playlistId) .Map(o => o.ToValidation("[PlaylistId] does not exist.")); - private static Validation CollectionTypesMustBeValid(ReplacePlaylistItems request, Playlist playlist) => + private static Validation CollectionTypesMustBeValid( + ReplacePlaylistItems request, + Playlist playlist) => request.Items.Map(item => CollectionTypeMustBeValid(item, playlist)).Sequence().Map(_ => playlist); - private static Validation CollectionTypeMustBeValid(ReplacePlaylistItem item, Playlist playlist) + private static Validation CollectionTypeMustBeValid( + ReplacePlaylistItem item, + Playlist playlist) { switch (item.CollectionType) { diff --git a/ErsatzTV.Application/MediaCollections/Mapper.cs b/ErsatzTV.Application/MediaCollections/Mapper.cs index b0581ff53..3c68c2827 100644 --- a/ErsatzTV.Application/MediaCollections/Mapper.cs +++ b/ErsatzTV.Application/MediaCollections/Mapper.cs @@ -48,7 +48,7 @@ internal static class Mapper internal static PlaylistGroupViewModel ProjectToViewModel(PlaylistGroup playlistGroup) => new(playlistGroup.Id, playlistGroup.Name, playlistGroup.Playlists.Count); - + internal static PlaylistViewModel ProjectToViewModel(Playlist playlist) => new(playlist.Id, playlist.PlaylistGroupId, playlist.Name); diff --git a/ErsatzTV.Application/MediaCollections/Queries/GetAllPlaylistGroupsHandler.cs b/ErsatzTV.Application/MediaCollections/Queries/GetAllPlaylistGroupsHandler.cs index d011badf9..65ba014af 100644 --- a/ErsatzTV.Application/MediaCollections/Queries/GetAllPlaylistGroupsHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Queries/GetAllPlaylistGroupsHandler.cs @@ -7,7 +7,9 @@ namespace ErsatzTV.Application.MediaCollections; public class GetAllPlaylistGroupsHandler(IDbContextFactory dbContextFactory) : IRequestHandler> { - public async Task> Handle(GetAllPlaylistGroups request, CancellationToken cancellationToken) + public async Task> Handle( + GetAllPlaylistGroups request, + CancellationToken cancellationToken) { await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); diff --git a/ErsatzTV.Application/MediaItems/Mapper.cs b/ErsatzTV.Application/MediaItems/Mapper.cs index 3528a43ac..018dfa15b 100644 --- a/ErsatzTV.Application/MediaItems/Mapper.cs +++ b/ErsatzTV.Application/MediaItems/Mapper.cs @@ -25,10 +25,10 @@ internal static class Mapper internal static NamedMediaItemViewModel ProjectToViewModel(OtherVideo otherVideo) => new(otherVideo.Id, otherVideo.OtherVideoMetadata.HeadOrNone().Match(ov => ov.Title, () => "???")); - + internal static NamedMediaItemViewModel ProjectToViewModel(Song song) => new(song.Id, SongTitle(song)); - + internal static NamedMediaItemViewModel ProjectToViewModel(Image image) => new(image.Id, image.ImageMetadata.HeadOrNone().Match(i => i.Title, () => "???")); @@ -68,7 +68,7 @@ internal static class Mapper private static string SeasonDescription(Season season) => season.SeasonNumber == 0 ? "Specials" : $"Season {season.SeasonNumber}"; - + private static string EpisodeTitle(Episode e) { string showTitle = e.Season.Show.ShowMetadata.HeadOrNone() diff --git a/ErsatzTV.Application/Scheduling/Commands/CreateDecoTemplate.cs b/ErsatzTV.Application/Scheduling/Commands/CreateDecoTemplate.cs index 0c5cc7d05..5a43d8be4 100644 --- a/ErsatzTV.Application/Scheduling/Commands/CreateDecoTemplate.cs +++ b/ErsatzTV.Application/Scheduling/Commands/CreateDecoTemplate.cs @@ -2,4 +2,5 @@ using ErsatzTV.Core; namespace ErsatzTV.Application.Scheduling; -public record CreateDecoTemplate(int DecoTemplateGroupId, string Name) : IRequest>; +public record CreateDecoTemplate(int DecoTemplateGroupId, string Name) + : IRequest>; diff --git a/ErsatzTV.Application/Scheduling/Commands/ReplaceDecoTemplateItemsHandler.cs b/ErsatzTV.Application/Scheduling/Commands/ReplaceDecoTemplateItemsHandler.cs index 67c240784..8b0aaeba3 100644 --- a/ErsatzTV.Application/Scheduling/Commands/ReplaceDecoTemplateItemsHandler.cs +++ b/ErsatzTV.Application/Scheduling/Commands/ReplaceDecoTemplateItemsHandler.cs @@ -27,7 +27,7 @@ public class ReplaceDecoTemplateItemsHandler(IDbContextFactory dbCont decoTemplate.DateUpdated = DateTime.UtcNow; dbContext.RemoveRange(decoTemplate.Items); - + // drop items that are invalid decoTemplate.Items = request.Items .Map(i => BuildItem(decoTemplate, i)) @@ -60,10 +60,14 @@ public class ReplaceDecoTemplateItemsHandler(IDbContextFactory dbCont EndTime = item.EndTime }; - private static Task> Validate(TvContext dbContext, ReplaceDecoTemplateItems request) => + private static Task> Validate( + TvContext dbContext, + ReplaceDecoTemplateItems request) => DecoTemplateMustExist(dbContext, request.DecoTemplateId); - private static Task> DecoTemplateMustExist(TvContext dbContext, int decoTemplateId) => + private static Task> DecoTemplateMustExist( + TvContext dbContext, + int decoTemplateId) => dbContext.DecoTemplates .Include(b => b.Items) .SelectOneAsync(b => b.Id, b => b.Id == decoTemplateId) diff --git a/ErsatzTV.Application/Scheduling/Commands/UpdateDecoHandler.cs b/ErsatzTV.Application/Scheduling/Commands/UpdateDecoHandler.cs index 87b5e2d70..47452d86d 100644 --- a/ErsatzTV.Application/Scheduling/Commands/UpdateDecoHandler.cs +++ b/ErsatzTV.Application/Scheduling/Commands/UpdateDecoHandler.cs @@ -22,11 +22,11 @@ public class UpdateDecoHandler(IDbContextFactory dbContextFactory) UpdateDeco request) { existing.Name = request.Name; - + // watermark existing.WatermarkMode = request.WatermarkMode; existing.WatermarkId = request.WatermarkMode is DecoMode.Override ? request.WatermarkId : null; - + // dead air fallback existing.DeadAirFallbackMode = request.DeadAirFallbackMode; existing.DeadAirFallbackCollectionType = request.DeadAirFallbackCollectionType; @@ -58,7 +58,7 @@ public class UpdateDecoHandler(IDbContextFactory dbContextFactory) dbContext.Decos .SelectOneAsync(d => d.Id, d => d.Id == request.DecoId) .Map(o => o.ToValidation("Deco does not exist")); - + private static async Task> ValidateDecoName( TvContext dbContext, UpdateDeco request) diff --git a/ErsatzTV.Application/Scheduling/Commands/UpdateDefaultDecoHandler.cs b/ErsatzTV.Application/Scheduling/Commands/UpdateDefaultDecoHandler.cs index 41b2bb080..e14e77667 100644 --- a/ErsatzTV.Application/Scheduling/Commands/UpdateDefaultDecoHandler.cs +++ b/ErsatzTV.Application/Scheduling/Commands/UpdateDefaultDecoHandler.cs @@ -3,7 +3,8 @@ using Microsoft.EntityFrameworkCore; namespace ErsatzTV.Application.Scheduling; -public class UpdateDefaultDecoHandler(IDbContextFactory dbContextFactory) : IRequestHandler +public class UpdateDefaultDecoHandler(IDbContextFactory dbContextFactory) + : IRequestHandler { public async Task Handle(UpdateDefaultDeco request, CancellationToken cancellationToken) { diff --git a/ErsatzTV.Application/Scheduling/Mapper.cs b/ErsatzTV.Application/Scheduling/Mapper.cs index facebb659..d836e68e0 100644 --- a/ErsatzTV.Application/Scheduling/Mapper.cs +++ b/ErsatzTV.Application/Scheduling/Mapper.cs @@ -45,7 +45,7 @@ internal static class Mapper DateTime endTime = startTime.AddMinutes(templateItem.Block.Minutes); return new TemplateItemViewModel(templateItem.BlockId, templateItem.Block.Name, startTime, endTime); } - + internal static DecoGroupViewModel ProjectToViewModel(DecoGroup decoGroup) => new(decoGroup.Id, decoGroup.Name, decoGroup.Decos.Count); @@ -84,6 +84,7 @@ internal static class Mapper { endTime = endTime.AddDays(1); } + return new DecoTemplateItemViewModel(decoTemplateItem.DecoId, decoTemplateItem.Deco.Name, startTime, endTime); } diff --git a/ErsatzTV.Application/Scheduling/Queries/GetDecoTemplateByIdHandler.cs b/ErsatzTV.Application/Scheduling/Queries/GetDecoTemplateByIdHandler.cs index a9ad82f29..a409b00df 100644 --- a/ErsatzTV.Application/Scheduling/Queries/GetDecoTemplateByIdHandler.cs +++ b/ErsatzTV.Application/Scheduling/Queries/GetDecoTemplateByIdHandler.cs @@ -7,7 +7,9 @@ namespace ErsatzTV.Application.Scheduling; public class GetDecoTemplateByIdHandler(IDbContextFactory dbContextFactory) : IRequestHandler> { - public async Task> Handle(GetDecoTemplateById request, CancellationToken cancellationToken) + public async Task> Handle( + GetDecoTemplateById request, + CancellationToken cancellationToken) { await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); return await dbContext.DecoTemplates diff --git a/ErsatzTV.Application/Scheduling/Queries/GetDecoTemplateItemsHandler.cs b/ErsatzTV.Application/Scheduling/Queries/GetDecoTemplateItemsHandler.cs index f44264630..fbfbc27ad 100644 --- a/ErsatzTV.Application/Scheduling/Queries/GetDecoTemplateItemsHandler.cs +++ b/ErsatzTV.Application/Scheduling/Queries/GetDecoTemplateItemsHandler.cs @@ -6,7 +6,9 @@ namespace ErsatzTV.Application.Scheduling; public class GetDecoTemplateItemsHandler(IDbContextFactory dbContextFactory) : IRequestHandler> { - public async Task> Handle(GetDecoTemplateItems request, CancellationToken cancellationToken) + public async Task> Handle( + GetDecoTemplateItems request, + CancellationToken cancellationToken) { await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); diff --git a/ErsatzTV.Application/Streaming/HlsSessionWorker.cs b/ErsatzTV.Application/Streaming/HlsSessionWorker.cs index dcc188ea6..98a8a0024 100644 --- a/ErsatzTV.Application/Streaming/HlsSessionWorker.cs +++ b/ErsatzTV.Application/Streaming/HlsSessionWorker.cs @@ -21,13 +21,13 @@ namespace ErsatzTV.Application.Streaming; public class HlsSessionWorker : IHlsSessionWorker { private static int _workAheadCount; - private readonly SemaphoreSlim _slim = new(1, 1); private readonly IClient _client; private readonly IConfigElementRepository _configElementRepository; private readonly IHlsPlaylistFilter _hlsPlaylistFilter; private readonly ILocalFileSystem _localFileSystem; private readonly ILogger _logger; private readonly IMediator _mediator; + private readonly SemaphoreSlim _slim = new(1, 1); private readonly object _sync = new(); private readonly Option _targetFramerate; private CancellationTokenSource _cancellationTokenSource; diff --git a/ErsatzTV.Application/Streaming/HlsSessionWorkerV2.cs b/ErsatzTV.Application/Streaming/HlsSessionWorkerV2.cs index b0257cdd7..94e863830 100644 --- a/ErsatzTV.Application/Streaming/HlsSessionWorkerV2.cs +++ b/ErsatzTV.Application/Streaming/HlsSessionWorkerV2.cs @@ -16,14 +16,13 @@ namespace ErsatzTV.Application.Streaming; public class HlsSessionWorkerV2 : IHlsSessionWorker { - private readonly SemaphoreSlim _slim = new(1, 1); - //private static int _workAheadCount; private readonly string _host; private readonly ILocalFileSystem _localFileSystem; private readonly ILogger _logger; private readonly IMediator _mediator; private readonly string _scheme; + private readonly SemaphoreSlim _slim = new(1, 1); private readonly object _sync = new(); private readonly Option _targetFramerate; private CancellationTokenSource _cancellationTokenSource; diff --git a/ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumberHandler.cs b/ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumberHandler.cs index ec31b144b..197d28946 100644 --- a/ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumberHandler.cs +++ b/ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumberHandler.cs @@ -28,7 +28,9 @@ public class GetHlsPlaylistByChannelNumberHandler : await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); DateTimeOffset now = DateTimeOffset.Now; Validation validation = await Validate(dbContext, request, now); - return await validation.Apply(parameters => GetPlaylist(dbContext, request, parameters, now)); + return await LanguageExtensions.Apply( + validation, + parameters => GetPlaylist(dbContext, request, parameters, now)); } private Task GetPlaylist( diff --git a/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs b/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs index de9a3d7aa..876a9ba2c 100644 --- a/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs +++ b/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs @@ -91,7 +91,6 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler< .ThenInclude(t => t.Items) .ThenInclude(i => i.Deco) .ThenInclude(d => d.Watermark) - .Include(i => i.MediaItem) .ThenInclude(mi => (mi as Episode).EpisodeMetadata) .ThenInclude(em => em.Subtitles) @@ -186,10 +185,9 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler< .ThenInclude(t => t.Items) .ThenInclude(i => i.Deco) .ThenInclude(d => d.Watermark) - .SelectOneAsync(p => p.ChannelId, p => p.ChannelId == channel.Id); - foreach (var playout in maybePlayout) + foreach (Playout playout in maybePlayout) { maybePlayoutItem = await CheckForFallbackFiller(dbContext, channel, playout, now); } @@ -489,6 +487,7 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler< .GetValue(ConfigElementKey.FFmpegGlobalFallbackFillerId) .BindT(fillerId => dbContext.FillerPresets.SelectOneAsync(w => w.Id, w => w.Id == fillerId)); } + break; } @@ -780,12 +779,17 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler< private sealed record DecoEntries(Option TemplateDeco, Option PlayoutDeco); private abstract record WatermarkResult; + private sealed record InheritWatermark : WatermarkResult; + private sealed record DisableWatermark : WatermarkResult; + private sealed record CustomWatermark(ChannelWatermark Watermark) : WatermarkResult; private abstract record DeadAirFallbackResult; + private sealed record InheritDeadAirFallback : DeadAirFallbackResult; + private sealed record DisableDeadAirFallback : DeadAirFallbackResult; private sealed record CustomDeadAirFallback( diff --git a/ErsatzTV.Application/Streaming/Queries/GetWrappedProcessByChannelNumber.cs b/ErsatzTV.Application/Streaming/Queries/GetWrappedProcessByChannelNumber.cs index 94315af3e..7b2646cd9 100644 --- a/ErsatzTV.Application/Streaming/Queries/GetWrappedProcessByChannelNumber.cs +++ b/ErsatzTV.Application/Streaming/Queries/GetWrappedProcessByChannelNumber.cs @@ -2,7 +2,11 @@ public record GetWrappedProcessByChannelNumber : FFmpegProcessRequest { - public GetWrappedProcessByChannelNumber(string scheme, string host, string accessToken, string channelNumber) : base( + public GetWrappedProcessByChannelNumber( + string scheme, + string host, + string accessToken, + string channelNumber) : base( channelNumber, "ts", DateTimeOffset.Now, diff --git a/ErsatzTV.Core.Tests/Emby/EmbyPathReplacementServiceTests.cs b/ErsatzTV.Core.Tests/Emby/EmbyPathReplacementServiceTests.cs index 0e8f37daa..81e4bde80 100644 --- a/ErsatzTV.Core.Tests/Emby/EmbyPathReplacementServiceTests.cs +++ b/ErsatzTV.Core.Tests/Emby/EmbyPathReplacementServiceTests.cs @@ -164,7 +164,7 @@ public class EmbyPathReplacementServiceTests result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } - + [Test] public async Task EmbyWindows_To_EtvLinux_UncPathWithMixedCaseServerName() { diff --git a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj index d26a73eb9..e6729d827 100644 --- a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj +++ b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj @@ -17,7 +17,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ErsatzTV.Core.Tests/Jellyfin/JellyfinPathReplacementServiceTests.cs b/ErsatzTV.Core.Tests/Jellyfin/JellyfinPathReplacementServiceTests.cs index 6adc621ac..6aaf9b753 100644 --- a/ErsatzTV.Core.Tests/Jellyfin/JellyfinPathReplacementServiceTests.cs +++ b/ErsatzTV.Core.Tests/Jellyfin/JellyfinPathReplacementServiceTests.cs @@ -164,7 +164,7 @@ public class JellyfinPathReplacementServiceTests result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } - + [Test] public async Task JellyfinWindows_To_EtvLinux_UncPathWithMixedCaseServerName() { diff --git a/ErsatzTV.Core.Tests/Plex/PlexPathReplacementServiceTests.cs b/ErsatzTV.Core.Tests/Plex/PlexPathReplacementServiceTests.cs index f0ed6686c..015ca1acb 100644 --- a/ErsatzTV.Core.Tests/Plex/PlexPathReplacementServiceTests.cs +++ b/ErsatzTV.Core.Tests/Plex/PlexPathReplacementServiceTests.cs @@ -140,7 +140,7 @@ public class PlexPathReplacementServiceTests result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } - + [Test] public async Task PlexWindows_To_EtvLinux_UncPathWithMixedCaseServerName() { diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutTemplateSelectorTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutTemplateSelectorTests.cs index ee0672ab4..55ba81242 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutTemplateSelectorTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutTemplateSelectorTests.cs @@ -11,7 +11,7 @@ public static class PlayoutTemplateSelectorTests public class GetPlayoutTemplateFor { private static readonly TimeSpan Offset = TimeSpan.FromHours(-5); - + [Test] public void LimitToDateRange_Before_Start_Should_Not_Return_Template() { @@ -33,7 +33,7 @@ public static class PlayoutTemplateSelectorTests result.IsNone.Should().BeTrue(); } - + [Test] public void LimitToDateRange_On_Start_Should_Return_Template() { @@ -55,7 +55,7 @@ public static class PlayoutTemplateSelectorTests result.IsSome.Should().BeTrue(); } - + [Test] public void LimitToDateRange_In_Range_Should_Return_Template() { @@ -77,7 +77,7 @@ public static class PlayoutTemplateSelectorTests result.IsSome.Should().BeTrue(); } - + [Test] public void LimitToDateRange_On_End_Should_Return_Template() { @@ -99,7 +99,7 @@ public static class PlayoutTemplateSelectorTests result.IsSome.Should().BeTrue(); } - + [Test] public void LimitToDateRange_After_End_Should_Not_Return_Template() { @@ -121,7 +121,7 @@ public static class PlayoutTemplateSelectorTests result.IsNone.Should().BeTrue(); } - + [Test] public void LimitToDateRange_Before_Invalid_Start_Date_Should_Not_Return_Template() { @@ -143,7 +143,7 @@ public static class PlayoutTemplateSelectorTests result.IsNone.Should().BeTrue(); } - + [Test] public void LimitToDateRange_After_Invalid_Start_Date_Should_Return_Template() { @@ -165,7 +165,7 @@ public static class PlayoutTemplateSelectorTests result.IsSome.Should().BeTrue(); } - + [Test] public void LimitToDateRange_Before_Invalid_End_Date_Should_Return_Template() { @@ -187,7 +187,7 @@ public static class PlayoutTemplateSelectorTests result.IsSome.Should().BeTrue(); } - + [Test] public void LimitToDateRange_After_Invalid_End_Date_Should_Not_Return_Template() { @@ -209,7 +209,7 @@ public static class PlayoutTemplateSelectorTests result.IsNone.Should().BeTrue(); } - + [Test] public void LimitToDateRange_Wrap_Around_Before_Start_Should_Not_Return_Template() { @@ -231,7 +231,7 @@ public static class PlayoutTemplateSelectorTests result.IsNone.Should().BeTrue(); } - + [Test] public void LimitToDateRange_Wrap_Around_On_Start_Should_Return_Template() { @@ -253,7 +253,7 @@ public static class PlayoutTemplateSelectorTests result.IsSome.Should().BeTrue(); } - + [Test] public void LimitToDateRange_Wrap_Around_In_Range_Should_Return_Template() { @@ -275,7 +275,7 @@ public static class PlayoutTemplateSelectorTests result.IsSome.Should().BeTrue(); } - + [Test] public void LimitToDateRange_Wrap_Around_On_End_Should_Return_Template() { @@ -297,7 +297,7 @@ public static class PlayoutTemplateSelectorTests result.IsSome.Should().BeTrue(); } - + [Test] public void LimitToDateRange_Wrap_Around_After_End_Should_Not_Return_Template() { @@ -319,7 +319,7 @@ public static class PlayoutTemplateSelectorTests result.IsNone.Should().BeTrue(); } - + [Test] public void LimitToDateRange_Wrap_Around_Before_Invalid_Start_Date_Should_Not_Return_Template() { @@ -341,7 +341,7 @@ public static class PlayoutTemplateSelectorTests result.IsNone.Should().BeTrue(); } - + [Test] public void LimitToDateRange_Wrap_Around_After_Invalid_Start_Date_Should_Return_Template() { @@ -363,7 +363,7 @@ public static class PlayoutTemplateSelectorTests result.IsSome.Should().BeTrue(); } - + [Test] public void LimitToDateRange_Wrap_Around_Before_Invalid_End_Date_Should_Return_Template() { @@ -385,7 +385,7 @@ public static class PlayoutTemplateSelectorTests result.IsSome.Should().BeTrue(); } - + [Test] public void LimitToDateRange_Wrap_Around_After_Invalid_End_Date_Should_Not_Return_Template() { diff --git a/ErsatzTV.Core/Domain/Collection/Playlist.cs b/ErsatzTV.Core/Domain/Collection/Playlist.cs index daaea3d45..b0795bdb0 100644 --- a/ErsatzTV.Core/Domain/Collection/Playlist.cs +++ b/ErsatzTV.Core/Domain/Collection/Playlist.cs @@ -6,6 +6,7 @@ public class Playlist public int PlaylistGroupId { get; set; } public PlaylistGroup PlaylistGroup { get; set; } public string Name { get; set; } + public ICollection Items { get; set; } //public DateTime DateUpdated { get; set; } } diff --git a/ErsatzTV.Core/Domain/Scheduling/PlayoutTemplate.cs b/ErsatzTV.Core/Domain/Scheduling/PlayoutTemplate.cs index bd6d5c353..e9c040dae 100644 --- a/ErsatzTV.Core/Domain/Scheduling/PlayoutTemplate.cs +++ b/ErsatzTV.Core/Domain/Scheduling/PlayoutTemplate.cs @@ -18,6 +18,7 @@ public class PlayoutTemplate public int StartDay { get; set; } public int EndMonth { get; set; } public int EndDay { get; set; } + public DateTime DateUpdated { get; set; } //public ICollection AdditionalDays { get; set; } diff --git a/ErsatzTV.Core/Emby/EmbyPathReplacementService.cs b/ErsatzTV.Core/Emby/EmbyPathReplacementService.cs index 50601b172..66d692819 100644 --- a/ErsatzTV.Core/Emby/EmbyPathReplacementService.cs +++ b/ErsatzTV.Core/Emby/EmbyPathReplacementService.cs @@ -86,7 +86,8 @@ public class EmbyPathReplacementService : IEmbyPathReplacementService foreach (EmbyPathReplacement replacement in maybeReplacement) { - string finalPath = Regex.Replace(path, + string finalPath = Regex.Replace( + path, Regex.Escape(replacement.EmbyPath), Regex.Replace(replacement.LocalPath ?? string.Empty, "\\$[0-9]+", @"$$$0"), RegexOptions.IgnoreCase); diff --git a/ErsatzTV.Core/ErsatzTV.Core.csproj b/ErsatzTV.Core/ErsatzTV.Core.csproj index 5b89e595a..aef25a4ec 100644 --- a/ErsatzTV.Core/ErsatzTV.Core.csproj +++ b/ErsatzTV.Core/ErsatzTV.Core.csproj @@ -20,7 +20,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs b/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs index 5a5f03cb3..8e2815df7 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs @@ -448,7 +448,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService Option.None, AudioFilter.None); - var videoFormat = GetVideoFormat(playbackSettings); + string videoFormat = GetVideoFormat(playbackSettings); var desiredState = new FrameState( playbackSettings.RealtimeOutput, diff --git a/ErsatzTV.Core/FileSystemLayout.cs b/ErsatzTV.Core/FileSystemLayout.cs index a1dcdae29..b561e3281 100644 --- a/ErsatzTV.Core/FileSystemLayout.cs +++ b/ErsatzTV.Core/FileSystemLayout.cs @@ -62,7 +62,7 @@ public static class FileSystemLayout public static readonly string AudioStreamSelectorScriptsFolder = Path.Combine(ScriptsFolder, "audio-stream-selector"); - + public static readonly string MacOsOldAppDataFolder = Path.Combine( Environment.GetEnvironmentVariable("HOME") ?? string.Empty, ".local", diff --git a/ErsatzTV.Core/Jellyfin/JellyfinPathReplacementService.cs b/ErsatzTV.Core/Jellyfin/JellyfinPathReplacementService.cs index 948ac12e5..c0b8a453c 100644 --- a/ErsatzTV.Core/Jellyfin/JellyfinPathReplacementService.cs +++ b/ErsatzTV.Core/Jellyfin/JellyfinPathReplacementService.cs @@ -86,7 +86,8 @@ public class JellyfinPathReplacementService : IJellyfinPathReplacementService foreach (JellyfinPathReplacement replacement in maybeReplacement) { - string finalPath = Regex.Replace(path, + string finalPath = Regex.Replace( + path, Regex.Escape(replacement.JellyfinPath), Regex.Replace(replacement.LocalPath ?? string.Empty, "\\$[0-9]+", @"$$$0"), RegexOptions.IgnoreCase); diff --git a/ErsatzTV.Core/Plex/PlexPathReplacementService.cs b/ErsatzTV.Core/Plex/PlexPathReplacementService.cs index 2e263ad74..71123b821 100644 --- a/ErsatzTV.Core/Plex/PlexPathReplacementService.cs +++ b/ErsatzTV.Core/Plex/PlexPathReplacementService.cs @@ -52,7 +52,8 @@ public class PlexPathReplacementService : IPlexPathReplacementService foreach (PlexPathReplacement replacement in maybeReplacement) { - string finalPath = Regex.Replace(path, + string finalPath = Regex.Replace( + path, Regex.Escape(replacement.PlexPath), Regex.Replace(replacement.LocalPath ?? string.Empty, "\\$[0-9]+", @"$$$0"), RegexOptions.IgnoreCase); diff --git a/ErsatzTV.Core/Scheduling/BlockScheduling/BlockPlayoutShuffledMediaCollectionEnumerator.cs b/ErsatzTV.Core/Scheduling/BlockScheduling/BlockPlayoutShuffledMediaCollectionEnumerator.cs index 22c159d32..83854da36 100644 --- a/ErsatzTV.Core/Scheduling/BlockScheduling/BlockPlayoutShuffledMediaCollectionEnumerator.cs +++ b/ErsatzTV.Core/Scheduling/BlockScheduling/BlockPlayoutShuffledMediaCollectionEnumerator.cs @@ -16,7 +16,7 @@ public class BlockPlayoutShuffledMediaCollectionEnumerator : IMediaCollectionEnu CollectionEnumeratorState state) { CurrentIncludeInProgramGuide = Option.None; - + _mediaItems = mediaItems; _mediaItemCount = _mediaItems.Sum(i => 1 + Optional(i.Additional).Flatten().Count()); diff --git a/ErsatzTV.Core/Scheduling/CollectionKey.cs b/ErsatzTV.Core/Scheduling/CollectionKey.cs index aaad9cbf3..30dcef217 100644 --- a/ErsatzTV.Core/Scheduling/CollectionKey.cs +++ b/ErsatzTV.Core/Scheduling/CollectionKey.cs @@ -13,7 +13,7 @@ public class CollectionKey : Record public int? MediaItemId { get; set; } public int? PlaylistId { get; set; } public string FakeCollectionKey { get; set; } - + public static CollectionKey ForPlaylistItem(PlaylistItem item) => item.CollectionType switch { diff --git a/ErsatzTV.Core/Scheduling/MediaItemsForCollection.cs b/ErsatzTV.Core/Scheduling/MediaItemsForCollection.cs index 413149192..9119c4c64 100644 --- a/ErsatzTV.Core/Scheduling/MediaItemsForCollection.cs +++ b/ErsatzTV.Core/Scheduling/MediaItemsForCollection.cs @@ -46,36 +46,42 @@ public static class MediaItemsForCollection { result.AddRange(await mediaCollectionRepository.GetMovie(mediaItemId)); } + break; case ProgramScheduleItemCollectionType.Episode: foreach (int mediaItemId in Optional(collectionKey.MediaItemId)) { result.AddRange(await mediaCollectionRepository.GetEpisode(mediaItemId)); } + break; case ProgramScheduleItemCollectionType.MusicVideo: foreach (int mediaItemId in Optional(collectionKey.MediaItemId)) { result.AddRange(await mediaCollectionRepository.GetMusicVideo(mediaItemId)); } + break; case ProgramScheduleItemCollectionType.OtherVideo: foreach (int mediaItemId in Optional(collectionKey.MediaItemId)) { result.AddRange(await mediaCollectionRepository.GetOtherVideo(mediaItemId)); } + break; case ProgramScheduleItemCollectionType.Song: foreach (int mediaItemId in Optional(collectionKey.MediaItemId)) { result.AddRange(await mediaCollectionRepository.GetSong(mediaItemId)); } + break; case ProgramScheduleItemCollectionType.Image: foreach (int mediaItemId in Optional(collectionKey.MediaItemId)) { result.AddRange(await mediaCollectionRepository.GetImage(mediaItemId)); } + break; default: throw new ArgumentOutOfRangeException(nameof(collectionKey)); diff --git a/ErsatzTV.Core/Scheduling/PlaylistEnumerator.cs b/ErsatzTV.Core/Scheduling/PlaylistEnumerator.cs index fae2a273b..8b55c1037 100644 --- a/ErsatzTV.Core/Scheduling/PlaylistEnumerator.cs +++ b/ErsatzTV.Core/Scheduling/PlaylistEnumerator.cs @@ -7,10 +7,52 @@ namespace ErsatzTV.Core.Scheduling; public class PlaylistEnumerator : IMediaCollectionEnumerator { - private IList _sortedEnumerators; - private IList _playAll; private int _enumeratorIndex; private System.Collections.Generic.HashSet _idsToIncludeInEPG; + private IList _playAll; + private IList _sortedEnumerators; + + private PlaylistEnumerator() + { + } + + public void ResetState(CollectionEnumeratorState state) => + // seed doesn't matter here + State.Index = state.Index; + + public CollectionEnumeratorState State { get; private set; } + + public Option Current => _sortedEnumerators[_enumeratorIndex].Current; + + public Option CurrentIncludeInProgramGuide + { + get + { + foreach (MediaItem mediaItem in Current) + { + return _idsToIncludeInEPG.Contains(mediaItem.Id); + } + + return Option.None; + } + } + + public int Count { get; private set; } + + public Option MinimumDuration { get; private set; } + + public void MoveNext() + { + _sortedEnumerators[_enumeratorIndex].MoveNext(); + + // if we aren't playing all, or if we just finished playing all, move to the next enumerator + if (!_playAll[_enumeratorIndex] || _sortedEnumerators[_enumeratorIndex].State.Index == 0) + { + _enumeratorIndex = (_enumeratorIndex + 1) % _sortedEnumerators.Count; + } + + State.Index = (State.Index + 1) % Count; + } public static async Task Create( IMediaCollectionRepository mediaCollectionRepository, @@ -39,7 +81,7 @@ public class PlaylistEnumerator : IMediaCollectionEnumerator result._idsToIncludeInEPG.Add(mediaItem.Id); } } - + var collectionKey = CollectionKey.ForPlaylistItem(playlistItem); if (enumeratorMap.TryGetValue(collectionKey, out IMediaCollectionEnumerator enumerator)) { @@ -78,7 +120,7 @@ public class PlaylistEnumerator : IMediaCollectionEnumerator CollectionKey.ForPlaylistItem(playlistItem)), initState, // TODO: fix this - randomStartPoint: false, + false, cancellationToken); break; case PlaybackOrder.SeasonEpisode: @@ -107,7 +149,7 @@ public class PlaylistEnumerator : IMediaCollectionEnumerator result.State = new CollectionEnumeratorState { Seed = state.Seed }; result._enumeratorIndex = 0; - + // TODO: how do we end up with index > count? if (state.Index < result.Count) { @@ -120,62 +162,19 @@ public class PlaylistEnumerator : IMediaCollectionEnumerator return result; } - private PlaylistEnumerator() - { - } - - public void ResetState(CollectionEnumeratorState state) => - // seed doesn't matter here - State.Index = state.Index; - - public CollectionEnumeratorState State { get; private set; } - - public Option Current => _sortedEnumerators[_enumeratorIndex].Current; - public Option CurrentIncludeInProgramGuide - { - get - { - foreach (MediaItem mediaItem in Current) - { - return _idsToIncludeInEPG.Contains(mediaItem.Id); - } - - return Option.None; - } - } - - public int Count { get; private set; } - - public Option MinimumDuration { get; private set; } + private static int LCM(IEnumerable numbers) => numbers.Aggregate(lcm); - public void MoveNext() - { - _sortedEnumerators[_enumeratorIndex].MoveNext(); - - // if we aren't playing all, or if we just finished playing all, move to the next enumerator - if (!_playAll[_enumeratorIndex] || _sortedEnumerators[_enumeratorIndex].State.Index == 0) - { - _enumeratorIndex = (_enumeratorIndex + 1) % _sortedEnumerators.Count; - } - - State.Index = (State.Index + 1) % Count; - } - - private static int LCM(IEnumerable numbers) - { - return numbers.Aggregate(lcm); - } - - private static int lcm(int a, int b) - { - return Math.Abs(a * b) / GCD(a, b); - } + private static int lcm(int a, int b) => Math.Abs(a * b) / GCD(a, b); private static int GCD(int a, int b) { while (true) { - if (b == 0) return a; + if (b == 0) + { + return a; + } + int a1 = a; a = b; b = a1 % b; diff --git a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs index 99ea135a0..f9a2521f6 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs @@ -19,11 +19,11 @@ public class PlayoutBuilder : IPlayoutBuilder private readonly IArtistRepository _artistRepository; private readonly IConfigElementRepository _configElementRepository; private readonly ILocalFileSystem _localFileSystem; - private ILogger _logger; private readonly IMediaCollectionRepository _mediaCollectionRepository; private readonly IMultiEpisodeShuffleCollectionEnumeratorFactory _multiEpisodeFactory; private readonly ITelevisionRepository _televisionRepository; private Playlist _debugPlaylist; + private ILogger _logger; public PlayoutBuilder( IConfigElementRepository configElementRepository, @@ -959,7 +959,7 @@ public class PlayoutBuilder : IPlayoutBuilder } state ??= new CollectionEnumeratorState { Seed = Random.Next(), Index = 0 }; - + if (collectionKey.CollectionType is ProgramScheduleItemCollectionType.Playlist) { foreach (int playlistId in Optional(collectionKey.PlaylistId)) diff --git a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs index ab822293d..dd7a28edb 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs @@ -107,7 +107,8 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase maybeVideoProfile) : EncoderBase { public override string Name => "h264_amf"; public override StreamKind Kind => StreamKind.Video; - + public override string[] OutputOptions { get @@ -16,7 +16,7 @@ public class EncoderH264Amf(Option maybeVideoProfile) : EncoderBase return [ "-c:v", Name, - "-profile:v", videoProfile.ToLowerInvariant(), + "-profile:v", videoProfile.ToLowerInvariant() ]; } diff --git a/ErsatzTV.FFmpeg/Encoder/EncoderLibx264.cs b/ErsatzTV.FFmpeg/Encoder/EncoderLibx264.cs index 026ca8d2c..f11708b47 100644 --- a/ErsatzTV.FFmpeg/Encoder/EncoderLibx264.cs +++ b/ErsatzTV.FFmpeg/Encoder/EncoderLibx264.cs @@ -6,13 +6,13 @@ public class EncoderLibx264(Option maybeVideoProfile, Option may { public override string Name => "libx264"; public override StreamKind Kind => StreamKind.Video; - + public override string[] OutputOptions { get { var result = new List(base.OutputOptions); - + foreach (string videoProfile in maybeVideoProfile) { result.Add("-profile:v"); diff --git a/ErsatzTV.FFmpeg/Encoder/EncoderLibx265.cs b/ErsatzTV.FFmpeg/Encoder/EncoderLibx265.cs index b390861e0..21f2b6662 100644 --- a/ErsatzTV.FFmpeg/Encoder/EncoderLibx265.cs +++ b/ErsatzTV.FFmpeg/Encoder/EncoderLibx265.cs @@ -18,7 +18,7 @@ public class EncoderLibx265(FrameState currentState, Option maybeVideoPr "-tag:v", "hvc1", "-x265-params", "log-level=error" }; - + foreach (string videoPreset in maybeVideoPreset) { if (!string.IsNullOrWhiteSpace(videoPreset)) diff --git a/ErsatzTV.FFmpeg/Encoder/Nvenc/EncoderH264Nvenc.cs b/ErsatzTV.FFmpeg/Encoder/Nvenc/EncoderH264Nvenc.cs index 8df6fa14a..59eec7f69 100644 --- a/ErsatzTV.FFmpeg/Encoder/Nvenc/EncoderH264Nvenc.cs +++ b/ErsatzTV.FFmpeg/Encoder/Nvenc/EncoderH264Nvenc.cs @@ -12,7 +12,7 @@ public class EncoderH264Nvenc(Option maybeVideoProfile, Option m get { var result = new List(base.OutputOptions); - + foreach (string videoProfile in maybeVideoProfile) { result.Add("-profile:v"); diff --git a/ErsatzTV.FFmpeg/Encoder/Nvenc/EncoderHevcNvenc.cs b/ErsatzTV.FFmpeg/Encoder/Nvenc/EncoderHevcNvenc.cs index 57c013a47..66602af28 100644 --- a/ErsatzTV.FFmpeg/Encoder/Nvenc/EncoderHevcNvenc.cs +++ b/ErsatzTV.FFmpeg/Encoder/Nvenc/EncoderHevcNvenc.cs @@ -5,8 +5,8 @@ namespace ErsatzTV.FFmpeg.Encoder.Nvenc; public class EncoderHevcNvenc : EncoderBase { - private readonly Option _maybeVideoPreset; private readonly bool _bFrames; + private readonly Option _maybeVideoPreset; public EncoderHevcNvenc(IHardwareCapabilities hardwareCapabilities, Option maybeVideoPreset) { @@ -30,7 +30,7 @@ public class EncoderHevcNvenc : EncoderBase "-tag:v", "hvc1", "-b_ref_mode", _bFrames ? "1" : "0" }; - + foreach (string videoPreset in _maybeVideoPreset) { if (!string.IsNullOrWhiteSpace(videoPreset)) @@ -39,7 +39,7 @@ public class EncoderHevcNvenc : EncoderBase result.Add(videoPreset); } } - + return result.ToArray(); } } diff --git a/ErsatzTV.FFmpeg/Encoder/Qsv/EncoderH264Qsv.cs b/ErsatzTV.FFmpeg/Encoder/Qsv/EncoderH264Qsv.cs index 252667e3a..e4d606e70 100644 --- a/ErsatzTV.FFmpeg/Encoder/Qsv/EncoderH264Qsv.cs +++ b/ErsatzTV.FFmpeg/Encoder/Qsv/EncoderH264Qsv.cs @@ -12,13 +12,13 @@ public class EncoderH264Qsv(Option maybeVideoProfile, Option may get { var result = new List { "-c:v", Name, "-low_power", "0", "-look_ahead", "0" }; - + foreach (string videoProfile in maybeVideoProfile) { result.Add("-profile:v"); result.Add(videoProfile.ToLowerInvariant()); } - + foreach (string videoPreset in maybeVideoPreset) { if (!string.IsNullOrWhiteSpace(videoPreset)) diff --git a/ErsatzTV.FFmpeg/Encoder/Qsv/EncoderHevcQsv.cs b/ErsatzTV.FFmpeg/Encoder/Qsv/EncoderHevcQsv.cs index 6db5e7f5f..e023fcb60 100644 --- a/ErsatzTV.FFmpeg/Encoder/Qsv/EncoderHevcQsv.cs +++ b/ErsatzTV.FFmpeg/Encoder/Qsv/EncoderHevcQsv.cs @@ -12,7 +12,7 @@ public class EncoderHevcQsv(Option maybeVideoPreset) : EncoderBase get { var result = new List { "-c:v", Name, "-low_power", "0", "-look_ahead", "0" }; - + foreach (string videoPreset in maybeVideoPreset) { if (!string.IsNullOrWhiteSpace(videoPreset)) diff --git a/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderH264Vaapi.cs b/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderH264Vaapi.cs index a830527ea..2bf5a1431 100644 --- a/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderH264Vaapi.cs +++ b/ErsatzTV.FFmpeg/Encoder/Vaapi/EncoderH264Vaapi.cs @@ -22,7 +22,7 @@ public class EncoderH264Vaapi(Option maybeVideoProfile, RateControlMode result.Add("-sei"); result.Add("-a53_cc"); - + foreach (string videoProfile in maybeVideoProfile) { result.Add("-profile:v"); diff --git a/ErsatzTV.FFmpeg/Encoder/VideoToolbox/EncoderH264VideoToolbox.cs b/ErsatzTV.FFmpeg/Encoder/VideoToolbox/EncoderH264VideoToolbox.cs index f27db6354..a1ed1da18 100644 --- a/ErsatzTV.FFmpeg/Encoder/VideoToolbox/EncoderH264VideoToolbox.cs +++ b/ErsatzTV.FFmpeg/Encoder/VideoToolbox/EncoderH264VideoToolbox.cs @@ -6,7 +6,7 @@ public class EncoderH264VideoToolbox(Option maybeVideoProfile) : Encoder { public override string Name => "h264_videotoolbox"; public override StreamKind Kind => StreamKind.Video; - + public override string[] OutputOptions { get @@ -16,7 +16,7 @@ public class EncoderH264VideoToolbox(Option maybeVideoProfile) : Encoder return [ "-c:v", Name, - "-profile:v", videoProfile.ToLowerInvariant(), + "-profile:v", videoProfile.ToLowerInvariant() ]; } diff --git a/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs b/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs index b769b92d5..6b51c7f5a 100644 --- a/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs +++ b/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs @@ -156,7 +156,7 @@ public abstract class PipelineBuilderBase : IPipelineBuilder isFmp4Hls = segmentTemplate.Contains("m4s"); } } - + if (ffmpegState.OutputFormat == OutputFormatKind.Mp4 || isFmp4Hls) { outputOption = new Mp4OutputOptions(); @@ -574,7 +574,8 @@ public abstract class PipelineBuilderBase : IPipelineBuilder return desiredState.VideoFormat switch { VideoFormat.Hevc => new EncoderLibx265( - currentState with { FrameDataLocation = FrameDataLocation.Software }, desiredState.VideoPreset), + currentState with { FrameDataLocation = FrameDataLocation.Software }, + desiredState.VideoPreset), VideoFormat.H264 => new EncoderLibx264(desiredState.VideoProfile, desiredState.VideoPreset), VideoFormat.Mpeg2Video => new EncoderMpeg2Video(), diff --git a/ErsatzTV.FFmpeg/Preset/AvailablePresets.cs b/ErsatzTV.FFmpeg/Preset/AvailablePresets.cs index 6dd8f3142..fb155ea1c 100644 --- a/ErsatzTV.FFmpeg/Preset/AvailablePresets.cs +++ b/ErsatzTV.FFmpeg/Preset/AvailablePresets.cs @@ -6,9 +6,8 @@ public static class AvailablePresets { public static ICollection ForAccelAndFormat( HardwareAccelerationMode hardwareAccelerationMode, - string videoFormat) - { - return (hardwareAccelerationMode, videoFormat) switch + string videoFormat) => + (hardwareAccelerationMode, videoFormat) switch { (HardwareAccelerationMode.Nvenc, VideoFormat.H264 or VideoFormat.Hevc) => [ @@ -27,5 +26,4 @@ public static class AvailablePresets _ => Array.Empty() }; - } } diff --git a/ErsatzTV.FFmpeg/Preset/VideoPreset.cs b/ErsatzTV.FFmpeg/Preset/VideoPreset.cs index 2bc588652..52b43a5a4 100644 --- a/ErsatzTV.FFmpeg/Preset/VideoPreset.cs +++ b/ErsatzTV.FFmpeg/Preset/VideoPreset.cs @@ -3,11 +3,11 @@ namespace ErsatzTV.FFmpeg.Preset; public static class VideoPreset { public const string Unset = ""; - + // NVENC public const string LowLatencyHighPerformance = "llhp"; public const string LowLatencyHighQuality = "llhq"; - + // x264 public const string VeryFast = "veryfast"; } diff --git a/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj b/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj index 7af1491f6..b8bb2bdbb 100644 --- a/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj +++ b/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj @@ -14,7 +14,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/ErsatzTV.Infrastructure/Data/Configurations/Collection/PlaylistConfiguration.cs b/ErsatzTV.Infrastructure/Data/Configurations/Collection/PlaylistConfiguration.cs index 61e048ff6..23e2da56e 100644 --- a/ErsatzTV.Infrastructure/Data/Configurations/Collection/PlaylistConfiguration.cs +++ b/ErsatzTV.Infrastructure/Data/Configurations/Collection/PlaylistConfiguration.cs @@ -9,7 +9,7 @@ public class PlaylistConfiguration : IEntityTypeConfiguration public void Configure(EntityTypeBuilder builder) { builder.ToTable("Playlist"); - + builder.HasIndex(d => new { d.PlaylistGroupId, d.Name }) .IsUnique(); @@ -17,6 +17,5 @@ public class PlaylistConfiguration : IEntityTypeConfiguration .WithOne(pi => pi.Playlist) .HasForeignKey(pi => pi.PlaylistId) .OnDelete(DeleteBehavior.Cascade); - } } diff --git a/ErsatzTV.Infrastructure/Data/Configurations/Collection/PlaylistItemConfiguration.cs b/ErsatzTV.Infrastructure/Data/Configurations/Collection/PlaylistItemConfiguration.cs index d8d085bb4..f122a89ff 100644 --- a/ErsatzTV.Infrastructure/Data/Configurations/Collection/PlaylistItemConfiguration.cs +++ b/ErsatzTV.Infrastructure/Data/Configurations/Collection/PlaylistItemConfiguration.cs @@ -9,7 +9,7 @@ public class PlaylistItemConfiguration : IEntityTypeConfiguration public void Configure(EntityTypeBuilder builder) { builder.ToTable("PlaylistItem"); - + builder.HasOne(i => i.Collection) .WithMany() .HasForeignKey(i => i.CollectionId) diff --git a/ErsatzTV.Infrastructure/Data/Configurations/ProgramScheduleItemConfiguration.cs b/ErsatzTV.Infrastructure/Data/Configurations/ProgramScheduleItemConfiguration.cs index 20252aea0..956d15034 100644 --- a/ErsatzTV.Infrastructure/Data/Configurations/ProgramScheduleItemConfiguration.cs +++ b/ErsatzTV.Infrastructure/Data/Configurations/ProgramScheduleItemConfiguration.cs @@ -33,7 +33,7 @@ public class ProgramScheduleItemConfiguration : IEntityTypeConfiguration i.SmartCollectionId) .OnDelete(DeleteBehavior.Cascade) .IsRequired(false); - + builder.HasOne(i => i.Playlist) .WithMany() .HasForeignKey(i => i.PlaylistId) diff --git a/ErsatzTV.Infrastructure/Data/Configurations/Scheduling/DecoConfiguration.cs b/ErsatzTV.Infrastructure/Data/Configurations/Scheduling/DecoConfiguration.cs index d5d81e36d..6438ac7e9 100644 --- a/ErsatzTV.Infrastructure/Data/Configurations/Scheduling/DecoConfiguration.cs +++ b/ErsatzTV.Infrastructure/Data/Configurations/Scheduling/DecoConfiguration.cs @@ -24,7 +24,7 @@ public class DecoConfiguration : IEntityTypeConfiguration .HasForeignKey(d => d.WatermarkId) .OnDelete(DeleteBehavior.SetNull) .IsRequired(false); - + builder.HasOne(d => d.DeadAirFallbackCollection) .WithMany() .HasForeignKey(d => d.DeadAirFallbackCollectionId) diff --git a/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs index 1dab1d849..26f7a1fb5 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs @@ -47,7 +47,6 @@ public class MediaCollectionRepository : IMediaCollectionRepository case ProgramScheduleItemCollectionType.Collection: foreach (int collectionId in Optional(playlistItem.CollectionId)) { - mediaItems.AddRange(await GetMovieItems(dbContext, collectionId)); mediaItems.AddRange(await GetShowItems(dbContext, collectionId)); mediaItems.AddRange(await GetSeasonItems(dbContext, collectionId)); @@ -100,7 +99,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.Movie: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -132,7 +131,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.Song: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -140,7 +139,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.Image: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -171,7 +170,6 @@ public class MediaCollectionRepository : IMediaCollectionRepository case ProgramScheduleItemCollectionType.Collection: foreach (int collectionId in Optional(playlistItem.CollectionId)) { - mediaItems.AddRange(await GetMovieItems(dbContext, collectionId)); mediaItems.AddRange(await GetShowItems(dbContext, collectionId)); mediaItems.AddRange(await GetSeasonItems(dbContext, collectionId)); @@ -224,7 +222,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.Movie: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -256,7 +254,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.Song: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -264,7 +262,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.Image: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -501,7 +499,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository return result; } - + public async Task> GetPlaylistItems(int id) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); @@ -531,7 +529,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.TelevisionShow: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -539,7 +537,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.TelevisionSeason: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -547,7 +545,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.Artist: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -563,7 +561,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.SmartCollection: foreach (int smartCollectionId in Optional(playlistItem.SmartCollectionId)) { @@ -571,7 +569,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.Movie: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -579,7 +577,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.Episode: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -603,7 +601,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.Song: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -611,7 +609,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } break; - + case ProgramScheduleItemCollectionType.Image: foreach (int mediaItemId in Optional(playlistItem.MediaItemId)) { @@ -897,7 +895,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository return await GetMovieItems(dbContext, ids); } - + private static Task> GetMovieItems(TvContext dbContext, IEnumerable movieIds) => dbContext.Movies .Include(m => m.MovieMetadata) diff --git a/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj b/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj index b406bf809..0342659fe 100644 --- a/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj +++ b/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj @@ -13,8 +13,8 @@ - - + + @@ -24,7 +24,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ErsatzTV.Infrastructure/Plex/PlexEtag.cs b/ErsatzTV.Infrastructure/Plex/PlexEtag.cs index 23f084341..9744da6aa 100644 --- a/ErsatzTV.Infrastructure/Plex/PlexEtag.cs +++ b/ErsatzTV.Infrastructure/Plex/PlexEtag.cs @@ -38,7 +38,7 @@ public class PlexEtag { bw.Write((byte)FieldKey.Key); bw.Write(part.Key); - + bw.Write((byte)FieldKey.PartId); bw.Write(part.Id); @@ -219,7 +219,7 @@ public class PlexEtag { bw.Write((byte)FieldKey.Key); bw.Write(part.Key); - + bw.Write((byte)FieldKey.PartId); bw.Write(part.Id); diff --git a/ErsatzTV.Infrastructure/Scheduling/MultiEpisodeShuffleCollectionEnumerator.cs b/ErsatzTV.Infrastructure/Scheduling/MultiEpisodeShuffleCollectionEnumerator.cs index ffc876aa8..42a4d9d94 100644 --- a/ErsatzTV.Infrastructure/Scheduling/MultiEpisodeShuffleCollectionEnumerator.cs +++ b/ErsatzTV.Infrastructure/Scheduling/MultiEpisodeShuffleCollectionEnumerator.cs @@ -27,7 +27,7 @@ public class MultiEpisodeShuffleCollectionEnumerator : IMediaCollectionEnumerato CancellationToken cancellationToken) { CurrentIncludeInProgramGuide = Option.None; - + _logger = logger; _cancellationToken = cancellationToken; diff --git a/ErsatzTV.Infrastructure/Search/CustomMultiFieldQueryParser.cs b/ErsatzTV.Infrastructure/Search/CustomMultiFieldQueryParser.cs index 1e3620157..67d0c102d 100644 --- a/ErsatzTV.Infrastructure/Search/CustomMultiFieldQueryParser.cs +++ b/ErsatzTV.Infrastructure/Search/CustomMultiFieldQueryParser.cs @@ -12,9 +12,6 @@ namespace ErsatzTV.Infrastructure.Search; public class CustomMultiFieldQueryParser : MultiFieldQueryParser { - private readonly LuceneVersion _matchVersion; - private readonly Analyzer _analyzer; - private static readonly List NumericFields = [ LuceneSearchIndex.MinutesField, @@ -26,6 +23,9 @@ public class CustomMultiFieldQueryParser : MultiFieldQueryParser LuceneSearchIndex.VideoBitDepthField ]; + private readonly Analyzer _analyzer; + private readonly LuceneVersion _matchVersion; + public CustomMultiFieldQueryParser( LuceneVersion matchVersion, string[] fields, @@ -102,14 +102,14 @@ public class CustomMultiFieldQueryParser : MultiFieldQueryParser { AllowLeadingWildcard = true }; - + string queryToParse = string.IsNullOrWhiteSpace(field) ? $"\"{queryText}\"" : $"{field}:\"{queryText}\""; return parser.Parse(queryToParse); } - + return base.GetFieldQuery(field, queryText, slop); } diff --git a/ErsatzTV.Infrastructure/Search/LuceneSearchIndex.cs b/ErsatzTV.Infrastructure/Search/LuceneSearchIndex.cs index 9ea77a087..ad0a68c72 100644 --- a/ErsatzTV.Infrastructure/Search/LuceneSearchIndex.cs +++ b/ErsatzTV.Infrastructure/Search/LuceneSearchIndex.cs @@ -732,7 +732,7 @@ public sealed class LuceneSearchIndex : ISearchIndex { doc.Add(new TextField(ShowStudioField, studio.Name, Field.Store.NO)); } - + if (!string.IsNullOrWhiteSpace(showMetadata.ContentRating)) { foreach (string contentRating in (showMetadata.ContentRating ?? string.Empty).Split("/") @@ -1023,7 +1023,7 @@ public sealed class LuceneSearchIndex : ISearchIndex { doc.Add(new TextField(ShowStudioField, studio.Name, Field.Store.NO)); } - + if (!string.IsNullOrWhiteSpace(showMetadata.ContentRating)) { foreach (string contentRating in (showMetadata.ContentRating ?? string.Empty).Split("/") @@ -1033,7 +1033,7 @@ public sealed class LuceneSearchIndex : ISearchIndex } } } - + if (!string.IsNullOrWhiteSpace(metadata.Title)) { doc.Add(new TextField(TitleField, metadata.Title, Field.Store.NO)); diff --git a/ErsatzTV.Infrastructure/Search/Models/ElasticSearchItem.cs b/ErsatzTV.Infrastructure/Search/Models/ElasticSearchItem.cs index 7e9fc18c8..524b77481 100644 --- a/ErsatzTV.Infrastructure/Search/Models/ElasticSearchItem.cs +++ b/ErsatzTV.Infrastructure/Search/Models/ElasticSearchItem.cs @@ -117,7 +117,7 @@ public class ElasticSearchItem : MinimalElasticSearchItem [JsonPropertyName(LuceneSearchIndex.ShowStudioField)] public List ShowStudio { get; set; } - + [JsonPropertyName(LuceneSearchIndex.ShowContentRatingField)] public List ShowContentRating { get; set; } diff --git a/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs b/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs index 2730bce02..adcad4ca9 100644 --- a/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs +++ b/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs @@ -4,17 +4,15 @@ using Lucene.Net.Analysis.Miscellaneous; using Lucene.Net.Analysis.Standard; using Lucene.Net.QueryParsers.Classic; using Lucene.Net.Search; +using Serilog; using Query = Lucene.Net.Search.Query; namespace ErsatzTV.Infrastructure.Search; public static class SearchQueryParser { - static SearchQueryParser() - { - BooleanQuery.MaxClauseCount = 1024 * 4; - } - + static SearchQueryParser() => BooleanQuery.MaxClauseCount = 1024 * 4; + internal static Analyzer AnalyzerWrapper() { using var defaultAnalyzer = new CustomAnalyzer(LuceneSearchIndex.AppLuceneVersion); @@ -47,7 +45,7 @@ public static class SearchQueryParser public static Query ParseQuery(string query) { using Analyzer analyzerWrapper = AnalyzerWrapper(); - + QueryParser parser = new CustomMultiFieldQueryParser( LuceneSearchIndex.AppLuceneVersion, [LuceneSearchIndex.TitleField], @@ -55,7 +53,7 @@ public static class SearchQueryParser parser.AllowLeadingWildcard = true; Query result = ParseQuery(query, parser); - Serilog.Log.Logger.Debug("Search query parsed from [{Query}] to [{ParsedQuery}]", query, result.ToString()); + Log.Logger.Debug("Search query parsed from [{Query}] to [{ParsedQuery}]", query, result.ToString()); return result; } diff --git a/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj b/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj index eb9a12163..a5443612b 100644 --- a/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj +++ b/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj @@ -15,7 +15,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/ErsatzTV.Scanner/Core/Metadata/ImageFolderScanner.cs b/ErsatzTV.Scanner/Core/Metadata/ImageFolderScanner.cs index 378d7b890..477243b5c 100644 --- a/ErsatzTV.Scanner/Core/Metadata/ImageFolderScanner.cs +++ b/ErsatzTV.Scanner/Core/Metadata/ImageFolderScanner.cs @@ -21,10 +21,10 @@ public class ImageFolderScanner : LocalFolderScanner, IImageFolderScanner private readonly IClient _client; private readonly IImageRepository _imageRepository; private readonly ILibraryRepository _libraryRepository; - private readonly IMediaItemRepository _mediaItemRepository; private readonly ILocalFileSystem _localFileSystem; private readonly ILocalMetadataProvider _localMetadataProvider; private readonly ILogger _logger; + private readonly IMediaItemRepository _mediaItemRepository; private readonly IMediator _mediator; public ImageFolderScanner( diff --git a/ErsatzTV.Scanner/Core/Metadata/MusicVideoFolderScanner.cs b/ErsatzTV.Scanner/Core/Metadata/MusicVideoFolderScanner.cs index 6e7699612..7ef2c664a 100644 --- a/ErsatzTV.Scanner/Core/Metadata/MusicVideoFolderScanner.cs +++ b/ErsatzTV.Scanner/Core/Metadata/MusicVideoFolderScanner.cs @@ -21,11 +21,11 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan private readonly IArtistRepository _artistRepository; private readonly IClient _client; private readonly ILibraryRepository _libraryRepository; - private readonly IMediaItemRepository _mediaItemRepository; private readonly ILocalFileSystem _localFileSystem; private readonly ILocalMetadataProvider _localMetadataProvider; private readonly ILocalSubtitlesProvider _localSubtitlesProvider; private readonly ILogger _logger; + private readonly IMediaItemRepository _mediaItemRepository; private readonly IMediator _mediator; private readonly IMusicVideoRepository _musicVideoRepository; diff --git a/ErsatzTV.Scanner/Core/Metadata/OtherVideoFolderScanner.cs b/ErsatzTV.Scanner/Core/Metadata/OtherVideoFolderScanner.cs index 90279d455..da0260c91 100644 --- a/ErsatzTV.Scanner/Core/Metadata/OtherVideoFolderScanner.cs +++ b/ErsatzTV.Scanner/Core/Metadata/OtherVideoFolderScanner.cs @@ -20,11 +20,11 @@ public class OtherVideoFolderScanner : LocalFolderScanner, IOtherVideoFolderScan { private readonly IClient _client; private readonly ILibraryRepository _libraryRepository; - private readonly IMediaItemRepository _mediaItemRepository; private readonly ILocalFileSystem _localFileSystem; private readonly ILocalMetadataProvider _localMetadataProvider; private readonly ILocalSubtitlesProvider _localSubtitlesProvider; private readonly ILogger _logger; + private readonly IMediaItemRepository _mediaItemRepository; private readonly IMediator _mediator; private readonly IOtherVideoRepository _otherVideoRepository; @@ -158,7 +158,9 @@ public class OtherVideoFolderScanner : LocalFolderScanner, IOtherVideoFolderScan { if (allFiles.Any(allTrashedItems.Contains)) { - _logger.LogDebug("Previously trashed items are now present in folder {Folder}", otherVideoFolder); + _logger.LogDebug( + "Previously trashed items are now present in folder {Folder}", + otherVideoFolder); } else { diff --git a/ErsatzTV.Scanner/Core/Metadata/SongFolderScanner.cs b/ErsatzTV.Scanner/Core/Metadata/SongFolderScanner.cs index 8ea58e11d..6f78a6aab 100644 --- a/ErsatzTV.Scanner/Core/Metadata/SongFolderScanner.cs +++ b/ErsatzTV.Scanner/Core/Metadata/SongFolderScanner.cs @@ -20,10 +20,10 @@ public class SongFolderScanner : LocalFolderScanner, ISongFolderScanner { private readonly IClient _client; private readonly ILibraryRepository _libraryRepository; - private readonly IMediaItemRepository _mediaItemRepository; private readonly ILocalFileSystem _localFileSystem; private readonly ILocalMetadataProvider _localMetadataProvider; private readonly ILogger _logger; + private readonly IMediaItemRepository _mediaItemRepository; private readonly IMediator _mediator; private readonly ISongRepository _songRepository; @@ -140,7 +140,7 @@ public class SongFolderScanner : LocalFolderScanner, ISongFolderScanner libraryPath, maybeParentFolder, songFolder); - + if (knownFolder.Etag == etag) { if (allFiles.Any(allTrashedItems.Contains)) diff --git a/ErsatzTV.Scanner/Core/Metadata/TelevisionFolderScanner.cs b/ErsatzTV.Scanner/Core/Metadata/TelevisionFolderScanner.cs index 6fbe96129..81be24bb3 100644 --- a/ErsatzTV.Scanner/Core/Metadata/TelevisionFolderScanner.cs +++ b/ErsatzTV.Scanner/Core/Metadata/TelevisionFolderScanner.cs @@ -21,11 +21,11 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan private readonly IClient _client; private readonly IFallbackMetadataProvider _fallbackMetadataProvider; private readonly ILibraryRepository _libraryRepository; - private readonly IMediaItemRepository _mediaItemRepository; private readonly ILocalFileSystem _localFileSystem; private readonly ILocalMetadataProvider _localMetadataProvider; private readonly ILocalSubtitlesProvider _localSubtitlesProvider; private readonly ILogger _logger; + private readonly IMediaItemRepository _mediaItemRepository; private readonly IMediator _mediator; private readonly IMetadataRepository _metadataRepository; private readonly ITelevisionRepository _televisionRepository; @@ -88,7 +88,7 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan { await _libraryRepository.UpdatePath(libraryPath, normalizedLibraryPath); } - + ImmutableHashSet allTrashedItems = await _mediaItemRepository.GetAllTrashedItems(libraryPath); var allShowFolders = _localFileSystem.ListSubdirectories(libraryPath.Path) diff --git a/ErsatzTV.Scanner/Core/Plex/PlexTelevisionLibraryScanner.cs b/ErsatzTV.Scanner/Core/Plex/PlexTelevisionLibraryScanner.cs index e16fc0550..e23933e8b 100644 --- a/ErsatzTV.Scanner/Core/Plex/PlexTelevisionLibraryScanner.cs +++ b/ErsatzTV.Scanner/Core/Plex/PlexTelevisionLibraryScanner.cs @@ -433,7 +433,7 @@ public class PlexTelevisionLibraryScanner : result.IsUpdated = true; } } - + if (fullMetadata.SortTitle != existingMetadata.SortTitle || fullMetadata.Title != existingMetadata.Title) { existingMetadata.Title = fullMetadata.Title; diff --git a/ErsatzTV/Controllers/IptvController.cs b/ErsatzTV/Controllers/IptvController.cs index 887b75bb1..24669b57d 100644 --- a/ErsatzTV/Controllers/IptvController.cs +++ b/ErsatzTV/Controllers/IptvController.cs @@ -101,7 +101,11 @@ public class IptvController : ControllerBase FFmpegProcessRequest request = mode switch { "ts-legacy" => new GetConcatProcessByChannelNumber(Request.Scheme, Request.Host.ToString(), channelNumber), - _ => new GetWrappedProcessByChannelNumber(Request.Scheme, Request.Host.ToString(), Request.Query["access_token"], channelNumber) + _ => new GetWrappedProcessByChannelNumber( + Request.Scheme, + Request.Host.ToString(), + Request.Query["access_token"], + channelNumber) }; return await _mediator.Send(request) @@ -271,7 +275,7 @@ public class IptvController : ControllerBase var variantPlaylist = $"{Request.Scheme}://{Request.Host}/iptv/session/{channelNumber}/{file}{AccessTokenQuery()}"; - + try { if (mode == "segmenter-v2") @@ -290,7 +294,7 @@ public class IptvController : ControllerBase ex, "Failed to return ffmpeg multi-variant playlist; falling back to generated playlist"); } - + Option maybeResolution = await _mediator.Send(new GetChannelResolution(channelNumber)); string resolution = string.Empty; foreach (ResolutionViewModel res in maybeResolution) diff --git a/ErsatzTV/ErsatzTV.csproj b/ErsatzTV/ErsatzTV.csproj index 261174290..73f1bfe3b 100644 --- a/ErsatzTV/ErsatzTV.csproj +++ b/ErsatzTV/ErsatzTV.csproj @@ -20,7 +20,7 @@ - + @@ -33,7 +33,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ErsatzTV/Pages/Artist.razor b/ErsatzTV/Pages/Artist.razor index 190cc4621..02886a5a3 100644 --- a/ErsatzTV/Pages/Artist.razor +++ b/ErsatzTV/Pages/Artist.razor @@ -1,16 +1,16 @@ @page "/media/music/artists/{ArtistId:int}" -@using ErsatzTV.Extensions +@using System.Globalization @using ErsatzTV.Application.Artists @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.ProgramSchedules -@using System.Globalization +@using ErsatzTV.Extensions @implements IDisposable -@inject IMediator _mediator -@inject IDialogService _dialog -@inject NavigationManager _navigationManager -@inject ILogger _logger -@inject ISnackbar _snackbar +@inject IMediator Mediator +@inject IDialogService Dialog +@inject NavigationManager NavigationManager +@inject ILogger Logger +@inject ISnackbar Snackbar
@@ -223,7 +223,7 @@ private async Task RefreshData() { - await _mediator.Send(new GetArtistById(ArtistId), _cts.Token).IfSomeAsync( + await Mediator.Send(new GetArtistById(ArtistId), _cts.Token).IfSomeAsync( vm => { _artist = vm; @@ -233,7 +233,7 @@ _sortedMoods = _artist.Moods.OrderBy(m => m).ToList(); }); - _musicVideos = await _mediator.Send(new GetMusicVideoCards(ArtistId, 1, 100), _cts.Token); + _musicVideos = await Mediator.Send(new GetMusicVideoCards(ArtistId, 1, 100), _cts.Token); } private async Task AddToCollection() @@ -241,12 +241,12 @@ var parameters = new DialogParameters { { "EntityType", "artist" }, { "EntityName", _artist.Name } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Collection", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is MediaCollectionViewModel collection) { - await _mediator.Send(new AddArtistToCollection(collection.Id, ArtistId), _cts.Token); - _navigationManager.NavigateTo($"media/collections/{collection.Id}"); + await Mediator.Send(new AddArtistToCollection(collection.Id, ArtistId), _cts.Token); + NavigationManager.NavigateTo($"media/collections/{collection.Id}"); } } @@ -255,12 +255,12 @@ var parameters = new DialogParameters { { "EntityType", "artist" }, { "EntityName", _artist.Name } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Schedule", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Schedule", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is ProgramScheduleViewModel schedule) { - await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, 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"); + await Mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, 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"); } } @@ -269,19 +269,19 @@ var parameters = new DialogParameters { { "EntityType", "music video" }, { "EntityName", musicVideo.Title } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Collection", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is MediaCollectionViewModel collection) { var request = new AddMusicVideoToCollection(collection.Id, musicVideo.MusicVideoId); - Either addResult = await _mediator.Send(request, _cts.Token); + Either addResult = await Mediator.Send(request, _cts.Token); addResult.Match( Left: error => { - _snackbar.Add($"Unexpected error adding music video to collection: {error.Value}"); - _logger.LogError("Unexpected error adding music video to collection: {Error}", error.Value); + Snackbar.Add($"Unexpected error adding music video to collection: {error.Value}"); + Logger.LogError("Unexpected error adding music video to collection: {Error}", error.Value); }, - Right: _ => _snackbar.Add($"Added {musicVideo.Title} to collection {collection.Name}", Severity.Success)); + Right: _ => Snackbar.Add($"Added {musicVideo.Title} to collection {collection.Name}", Severity.Success)); } } diff --git a/ErsatzTV/Pages/ArtistList.razor b/ErsatzTV/Pages/ArtistList.razor index ce836b856..b9ffdb51a 100644 --- a/ErsatzTV/Pages/ArtistList.razor +++ b/ErsatzTV/Pages/ArtistList.razor @@ -1,12 +1,11 @@ @page "/media/music/artists" @page "/media/music/artists/page/{PageNumber:int}" -@using ErsatzTV.Extensions @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Search +@using ErsatzTV.Extensions @inherits MultiSelectBase -@inject NavigationManager _navigationManager -@inject ChannelWriter _channel +@inject NavigationManager NavigationManager
@@ -86,7 +85,7 @@ PageNumber = 1; } - _query = _navigationManager.Uri.GetSearchQuery(); + _query = NavigationManager.Uri.GetSearchQuery(); await RefreshData(); } @@ -106,7 +105,7 @@ uri = $"{uri}?{key}={value}"; } - _navigationManager.NavigateTo(uri); + NavigationManager.NavigateTo(uri); } private void NextPage() @@ -118,7 +117,7 @@ uri = $"{uri}?{key}={value}"; } - _navigationManager.NavigateTo(uri); + NavigationManager.NavigateTo(uri); } private void SelectClicked(MediaCardViewModel card, MouseEventArgs e) diff --git a/ErsatzTV/Pages/BlockEditor.razor b/ErsatzTV/Pages/BlockEditor.razor index b7fafc2c6..2ff4af37c 100644 --- a/ErsatzTV/Pages/BlockEditor.razor +++ b/ErsatzTV/Pages/BlockEditor.razor @@ -1,8 +1,8 @@ @page "/blocks/{Id:int}" -@using ErsatzTV.Application.Scheduling -@using ErsatzTV.Application.Search @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaItems +@using ErsatzTV.Application.Scheduling +@using ErsatzTV.Application.Search @using ErsatzTV.Core.Domain.Scheduling @implements IDisposable @inject NavigationManager NavigationManager diff --git a/ErsatzTV/Pages/BlockPlayoutEditor.razor b/ErsatzTV/Pages/BlockPlayoutEditor.razor index 9012fe25f..bf098d2d2 100644 --- a/ErsatzTV/Pages/BlockPlayoutEditor.razor +++ b/ErsatzTV/Pages/BlockPlayoutEditor.razor @@ -1,89 +1,88 @@ @page "/playouts/block/{Id:int}" -@using ErsatzTV.Application.Scheduling @using ErsatzTV.Application.Channels +@using ErsatzTV.Application.Scheduling @implements IDisposable @inject NavigationManager NavigationManager -@inject ILogger Logger @inject ISnackbar Snackbar @inject IMediator Mediator @inject IEntityLocker EntityLocker; -Edit Block Playout - @_channelName - - - - - Playout Templates - - - - - Edit Templates - - - - - - - Playout Items and History - - - -
- - Erase Items - -
-
- - Erase Items and History + Edit Block Playout - @_channelName + + + + + Playout Templates + + + + + Edit Templates -
-
-
- - - - Default Deco - - - - - - - @if (_enableDefaultDeco) - { - - - @foreach (DecoGroupViewModel decoGroup in _decoGroups) - { - @decoGroup.Name - } - + + + + + + Playout Items and History + + + +
+ + Erase Items + +
+
+ + Erase Items and History + +
+
+
+ + + + Default Deco + + + + + - - - @foreach (DecoViewModel deco in _decos) - { - @deco.Name - } - - - } - - - - Save Changes - - - -
+ @if (_enableDefaultDeco) + { + + + @foreach (DecoGroupViewModel decoGroup in _decoGroups) + { + @decoGroup.Name + } + + + + + @foreach (DecoViewModel deco in _decos) + { + @deco.Name + } + + + } + + + + Save Changes + + + +
@code { @@ -119,10 +118,10 @@ { _channelName = name; } - + _decoGroups.Clear(); _decoGroups.AddRange(await Mediator.Send(new GetAllDecoGroups(), _cts.Token)); - + Option maybeDefaultDeco = await Mediator.Send(new GetDecoByPlayoutId(Id), _cts.Token); foreach (DecoViewModel defaultDeco in maybeDefaultDeco) { @@ -132,6 +131,7 @@ _defaultDeco = defaultDeco; } } + private async Task UpdateDefaultDecoTemplateGroupItems(DecoGroupViewModel decoGroup) { _selectedDefaultDecoGroup = decoGroup; @@ -154,4 +154,5 @@ int? decoId = _enableDefaultDeco ? _defaultDeco?.Id : null; await Mediator.Send(new UpdateDefaultDeco(Id, decoId), _cts.Token); } + } \ No newline at end of file diff --git a/ErsatzTV/Pages/Blocks.razor b/ErsatzTV/Pages/Blocks.razor index bb3256218..9ddfddb08 100644 --- a/ErsatzTV/Pages/Blocks.razor +++ b/ErsatzTV/Pages/Blocks.razor @@ -1,6 +1,6 @@ @page "/blocks" -@using S = System.Collections.Generic @using ErsatzTV.Application.Scheduling +@using S = System.Collections.Generic @implements IDisposable @inject ILogger Logger @inject ISnackbar Snackbar diff --git a/ErsatzTV/Pages/ChannelEditor.razor b/ErsatzTV/Pages/ChannelEditor.razor index a7ddb7c2d..2291e4a08 100644 --- a/ErsatzTV/Pages/ChannelEditor.razor +++ b/ErsatzTV/Pages/ChannelEditor.razor @@ -1,14 +1,14 @@ @page "/channels/{Id:int?}" @page "/channels/add" -@using static Prelude +@using ErsatzTV.Application.Channels @using ErsatzTV.Application.FFmpegProfiles @using ErsatzTV.Application.Filler @using ErsatzTV.Application.Images @using ErsatzTV.Application.MediaItems @using ErsatzTV.Application.Templates @using ErsatzTV.Application.Watermarks -@using ErsatzTV.Application.Channels @using ErsatzTV.Core.Domain.Filler +@using static Prelude @implements IDisposable @inject NavigationManager NavigationManager @inject ILogger Logger diff --git a/ErsatzTV/Pages/Channels.razor b/ErsatzTV/Pages/Channels.razor index feb147023..315580b90 100644 --- a/ErsatzTV/Pages/Channels.razor +++ b/ErsatzTV/Pages/Channels.razor @@ -1,9 +1,9 @@ @page "/channels" +@using System.Globalization @using ErsatzTV.Application.Channels @using ErsatzTV.Application.Configuration @using ErsatzTV.Application.FFmpegProfiles @using ErsatzTV.Core.Interfaces.FFmpeg -@using System.Globalization @implements IDisposable @inject IDialogService Dialog @inject IMediator Mediator diff --git a/ErsatzTV/Pages/CollectionEditor.razor b/ErsatzTV/Pages/CollectionEditor.razor index 0beab332a..f39436600 100644 --- a/ErsatzTV/Pages/CollectionEditor.razor +++ b/ErsatzTV/Pages/CollectionEditor.razor @@ -2,10 +2,10 @@ @page "/media/collections/add" @using ErsatzTV.Application.MediaCollections @implements IDisposable -@inject NavigationManager _navigationManager -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject IMediator _mediator +@inject NavigationManager NavigationManager +@inject ILogger Logger +@inject ISnackbar Snackbar +@inject IMediator Mediator
@@ -47,7 +47,7 @@ { if (IsEdit) { - Option maybeCollection = await _mediator.Send(new GetCollectionById(Id), _cts.Token); + Option maybeCollection = await Mediator.Send(new GetCollectionById(Id), _cts.Token); maybeCollection.IfSome( collection => { @@ -74,15 +74,15 @@ _messageStore.Clear(); if (_editContext.Validate()) { - Seq errorMessage = IsEdit ? (await _mediator.Send(new UpdateCollection(Id, _model.Name), _cts.Token)).LeftToSeq() : (await _mediator.Send(new CreateCollection(_model.Name), _cts.Token)).LeftToSeq(); + Seq errorMessage = IsEdit ? (await Mediator.Send(new UpdateCollection(Id, _model.Name), _cts.Token)).LeftToSeq() : (await Mediator.Send(new CreateCollection(_model.Name), _cts.Token)).LeftToSeq(); errorMessage.HeadOrNone().Match( error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Error saving collection: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Error saving collection: {Error}", error.Value); }, - () => _navigationManager.NavigateTo(_model.Id > 0 ? $"media/collections/{_model.Id}" : "media/collections")); + () => NavigationManager.NavigateTo(_model.Id > 0 ? $"media/collections/{_model.Id}" : "media/collections")); } } diff --git a/ErsatzTV/Pages/Collections.razor b/ErsatzTV/Pages/Collections.razor index d6a23f0bc..4f0dfb206 100644 --- a/ErsatzTV/Pages/Collections.razor +++ b/ErsatzTV/Pages/Collections.razor @@ -1,7 +1,7 @@ @page "/media/collections" -@using ErsatzTV.Extensions -@using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Configuration +@using ErsatzTV.Application.MediaCollections +@using ErsatzTV.Extensions @implements IDisposable @inject IDialogService Dialog @inject IMediator Mediator diff --git a/ErsatzTV/Pages/DecoEditor.razor b/ErsatzTV/Pages/DecoEditor.razor index efd6898ae..d1689d9af 100644 --- a/ErsatzTV/Pages/DecoEditor.razor +++ b/ErsatzTV/Pages/DecoEditor.razor @@ -1,10 +1,10 @@ @page "/decos/{Id:int}" -@using ErsatzTV.Application.Scheduling -@using ErsatzTV.Application.Watermarks +@using ErsatzTV.Application.Artists @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaItems +@using ErsatzTV.Application.Scheduling @using ErsatzTV.Application.Television -@using ErsatzTV.Application.Artists +@using ErsatzTV.Application.Watermarks @using ErsatzTV.Core.Domain.Scheduling @implements IDisposable @inject NavigationManager NavigationManager @@ -13,154 +13,154 @@ @inject IMediator Mediator - - Edit Deco - - - - - - - Save Changes - - - - - - - Watermark - - - - - Inherit - Disable - Override - - - (none) - @foreach (WatermarkViewModel watermark in _watermarks) - { - @watermark.Name - } - - - - - - - - - - Dead Air Fallback -   - - - - - When no playout item is found for the current time, *one* item will be randomly selected from this collection and looped and cut to exactly fit until the start of the next playout item. - This replaces the "Channel is Offline" image that would otherwise display. - - - - - - - Inherit - Disable - Override - - - @foreach (ProgramScheduleItemCollectionType collectionType in Enum.GetValues()) - { - @collectionType - } - - @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.Collection) - { - - @foreach (MediaCollectionViewModel collection in _mediaCollections) - { - @collection.Name - } + + Edit Deco + + + + + + + Save Changes + + + + + + + Watermark + + + + + Inherit + Disable + Override - } - @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.MultiCollection) - { - - @foreach (MultiCollectionViewModel collection in _multiCollections) + + (none) + @foreach (WatermarkViewModel watermark in _watermarks) { - @collection.Name + @watermark.Name } - } - @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.SmartCollection) - { - - @foreach (SmartCollectionViewModel collection in _smartCollections) - { - @collection.Name - } + + + + + + + + + Dead Air Fallback +   + + + + + When no playout item is found for the current time, *one* item will be randomly selected from this collection and looped and cut to exactly fit until the start of the next playout item. + This replaces the "Channel is Offline" image that would otherwise display. + + + + + + + Inherit + Disable + Override - } - @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.TelevisionShow) - { - - @foreach (NamedMediaItemViewModel show in _televisionShows) + + @foreach (ProgramScheduleItemCollectionType collectionType in Enum.GetValues()) { - @show.Name + @collectionType } - } - @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.TelevisionSeason) - { - - @foreach (NamedMediaItemViewModel season in _televisionSeasons) - { - @season.Name - } - - } - @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.Artist) - { - - @foreach (NamedMediaItemViewModel artist in _artists) - { - @artist.Name - } - - } - - - + @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.Collection) + { + + @foreach (MediaCollectionViewModel collection in _mediaCollections) + { + @collection.Name + } + + } + @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.MultiCollection) + { + + @foreach (MultiCollectionViewModel collection in _multiCollections) + { + @collection.Name + } + + } + @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.SmartCollection) + { + + @foreach (SmartCollectionViewModel collection in _smartCollections) + { + @collection.Name + } + + } + @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.TelevisionShow) + { + + @foreach (NamedMediaItemViewModel show in _televisionShows) + { + @show.Name + } + + } + @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.TelevisionSeason) + { + + @foreach (NamedMediaItemViewModel season in _televisionSeasons) + { + @season.Name + } + + } + @if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.Artist) + { + + @foreach (NamedMediaItemViewModel artist in _artists) + { + @artist.Name + } + + } + + + @code { @@ -273,4 +273,5 @@ }, () => NavigationManager.NavigateTo("/decos")); } + } \ No newline at end of file diff --git a/ErsatzTV/Pages/DecoTemplateEditor.razor b/ErsatzTV/Pages/DecoTemplateEditor.razor index 71aba8dcd..496fa78e7 100644 --- a/ErsatzTV/Pages/DecoTemplateEditor.razor +++ b/ErsatzTV/Pages/DecoTemplateEditor.razor @@ -1,6 +1,6 @@ @page "/deco-templates/{Id:int}" -@using ErsatzTV.Application.Scheduling @using System.Globalization +@using ErsatzTV.Application.Scheduling @implements IDisposable @inject NavigationManager NavigationManager @inject ILogger Logger diff --git a/ErsatzTV/Pages/DecoTemplates.razor b/ErsatzTV/Pages/DecoTemplates.razor index 79d7428cd..a858cc335 100644 --- a/ErsatzTV/Pages/DecoTemplates.razor +++ b/ErsatzTV/Pages/DecoTemplates.razor @@ -1,6 +1,6 @@ @page "/deco-templates" -@using S = System.Collections.Generic @using ErsatzTV.Application.Scheduling +@using S = System.Collections.Generic @implements IDisposable @inject ILogger Logger @inject ISnackbar Snackbar diff --git a/ErsatzTV/Pages/Decos.razor b/ErsatzTV/Pages/Decos.razor index 96505c761..9b5a6b926 100644 --- a/ErsatzTV/Pages/Decos.razor +++ b/ErsatzTV/Pages/Decos.razor @@ -1,6 +1,6 @@ @page "/decos" -@using S = System.Collections.Generic @using ErsatzTV.Application.Scheduling +@using S = System.Collections.Generic @implements IDisposable @inject ILogger Logger @inject ISnackbar Snackbar diff --git a/ErsatzTV/Pages/EmbyLibrariesEditor.razor b/ErsatzTV/Pages/EmbyLibrariesEditor.razor index c306dd6ec..48069a44d 100644 --- a/ErsatzTV/Pages/EmbyLibrariesEditor.razor +++ b/ErsatzTV/Pages/EmbyLibrariesEditor.razor @@ -1,9 +1,9 @@ @page "/media/sources/emby/{Id:int}/libraries" -@using ErsatzTV.Application.MediaSources @using ErsatzTV.Application.Emby +@using ErsatzTV.Application.MediaSources @implements IDisposable -@inject IMediator _mediator -@inject ChannelWriter _scannerWorkerChannel +@inject IMediator Mediator +@inject ChannelWriter ScannerWorkerChannel new EmbyLibraryPreference(l.Id, l.ShouldSyncItems)).ToList()); private Task> GetLibrariesBySourceId(int mediaSourceId) => - _mediator.Send(new GetEmbyLibrariesBySourceId(Id)) + Mediator.Send(new GetEmbyLibrariesBySourceId(Id)) .Map(list => list.Map(ProjectToEditViewModel).OrderBy(x => x.MediaKind).ThenBy(x => x.Name).ToList()); private Task> GetMediaSourceById(int mediaSourceId) => - _mediator.Send(new GetEmbyMediaSourceById(Id)) + Mediator.Send(new GetEmbyMediaSourceById(Id)) .MapT(vm => new RemoteMediaSourceViewModel(vm.Id, vm.Name, vm.Address)); private RemoteMediaSourceLibraryEditViewModel ProjectToEditViewModel(EmbyLibraryViewModel library) => new() @@ -47,8 +47,8 @@ private async Task SynchronizeLibraryByIdIfNeeded(RemoteMediaSourceLibrariesEditor.SynchronizeParameters parameters) { - await _scannerWorkerChannel.WriteAsync(new SynchronizeEmbyLibraries(parameters.MediaSourceId), _cts.Token); - await _scannerWorkerChannel.WriteAsync(new SynchronizeEmbyLibraryByIdIfNeeded(parameters.LibraryId), _cts.Token); + await ScannerWorkerChannel.WriteAsync(new SynchronizeEmbyLibraries(parameters.MediaSourceId), _cts.Token); + await ScannerWorkerChannel.WriteAsync(new SynchronizeEmbyLibraryByIdIfNeeded(parameters.LibraryId), _cts.Token); return Unit.Default; } diff --git a/ErsatzTV/Pages/EmbyMediaSourceEditor.razor b/ErsatzTV/Pages/EmbyMediaSourceEditor.razor index f0ea332c2..78146e8b2 100644 --- a/ErsatzTV/Pages/EmbyMediaSourceEditor.razor +++ b/ErsatzTV/Pages/EmbyMediaSourceEditor.razor @@ -1,11 +1,8 @@ @page "/media/sources/emby/edit" -@using ErsatzTV.Core.Emby @using ErsatzTV.Application.Emby +@using ErsatzTV.Core.Emby @implements IDisposable -@inject IMediator _mediator -@inject NavigationManager _navigationManager -@inject ISnackbar _snackbar -@inject ILogger _logger +@inject IMediator Mediator LoadSecrets(RemoteMediaSourceEditViewModel viewModel) { - EmbySecrets secrets = await _mediator.Send(new GetEmbySecrets(), _cts.Token); + EmbySecrets secrets = await Mediator.Send(new GetEmbySecrets(), _cts.Token); viewModel.Address = secrets.Address; viewModel.ApiKey = secrets.ApiKey; return Unit.Default; @@ -32,7 +29,7 @@ private async Task> SaveSecrets(RemoteMediaSourceEditViewModel viewModel) { var secrets = new EmbySecrets { Address = viewModel.Address, ApiKey = viewModel.ApiKey }; - return await _mediator.Send(new SaveEmbySecrets(secrets), _cts.Token); + return await Mediator.Send(new SaveEmbySecrets(secrets), _cts.Token); } } \ No newline at end of file diff --git a/ErsatzTV/Pages/EmbyMediaSources.razor b/ErsatzTV/Pages/EmbyMediaSources.razor index 50dddfcbb..36a66c74f 100644 --- a/ErsatzTV/Pages/EmbyMediaSources.razor +++ b/ErsatzTV/Pages/EmbyMediaSources.razor @@ -1,10 +1,10 @@ @page "/media/sources/emby" -@using ErsatzTV.Core.Interfaces.Emby @using ErsatzTV.Application.Emby @using ErsatzTV.Core.Emby +@using ErsatzTV.Core.Interfaces.Emby @implements IDisposable -@inject IEmbySecretStore _embySecretStore -@inject ChannelWriter _scannerWorkerChannel +@inject IEmbySecretStore EmbySecretStore +@inject ChannelWriter ScannerWorkerChannel + SecretStore="@EmbySecretStore"/> @code { private readonly CancellationTokenSource _cts = new(); @@ -26,6 +26,6 @@ } private async Task RefreshLibraries(int mediaSourceId) => - await _scannerWorkerChannel.WriteAsync(new SynchronizeEmbyLibraries(mediaSourceId), _cts.Token); + await ScannerWorkerChannel.WriteAsync(new SynchronizeEmbyLibraries(mediaSourceId), _cts.Token); } \ No newline at end of file diff --git a/ErsatzTV/Pages/EmbyPathReplacementsEditor.razor b/ErsatzTV/Pages/EmbyPathReplacementsEditor.razor index c40cf3d33..31cefc3bc 100644 --- a/ErsatzTV/Pages/EmbyPathReplacementsEditor.razor +++ b/ErsatzTV/Pages/EmbyPathReplacementsEditor.razor @@ -1,11 +1,8 @@ @page "/media/sources/emby/{Id:int}/paths" -@using ErsatzTV.Application.MediaSources @using ErsatzTV.Application.Emby +@using ErsatzTV.Application.MediaSources @implements IDisposable -@inject NavigationManager _navigationManager -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject IMediator _mediator +@inject IMediator Mediator > GetMediaSourceById(int id) => - _mediator.Send(new GetEmbyMediaSourceById(Id), _cts.Token) + Mediator.Send(new GetEmbyMediaSourceById(Id), _cts.Token) .MapT(vm => new RemoteMediaSourceViewModel(vm.Id, vm.Name, vm.Address)); private Task> GetPathReplacementsBySourceId(int mediaSourceId) => - _mediator.Send(new GetEmbyPathReplacementsBySourceId(Id), _cts.Token) + Mediator.Send(new GetEmbyPathReplacementsBySourceId(Id), _cts.Token) .Map(list => list.Map(ProjectToEditViewModel).ToList()); private RemoteMediaSourcePathReplacementEditViewModel ProjectToEditViewModel(EmbyPathReplacementViewModel item) => diff --git a/ErsatzTV/Pages/EpisodeList.razor b/ErsatzTV/Pages/EpisodeList.razor index 8e859f365..e55def449 100644 --- a/ErsatzTV/Pages/EpisodeList.razor +++ b/ErsatzTV/Pages/EpisodeList.razor @@ -1,12 +1,11 @@ @page "/media/tv/episodes" @page "/media/tv/episodes/page/{PageNumber:int}" -@using ErsatzTV.Extensions @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Search +@using ErsatzTV.Extensions @inherits MultiSelectBase -@inject NavigationManager _navigationManager -@inject ChannelWriter _channel +@inject NavigationManager NavigationManager
@@ -93,7 +92,7 @@ PageNumber = 1; } - _query = _navigationManager.Uri.GetSearchQuery(); + _query = NavigationManager.Uri.GetSearchQuery(); await RefreshData(); } @@ -113,7 +112,7 @@ uri = $"{uri}?{key}={value}"; } - _navigationManager.NavigateTo(uri); + NavigationManager.NavigateTo(uri); } private void NextPage() @@ -125,7 +124,7 @@ uri = $"{uri}?{key}={value}"; } - _navigationManager.NavigateTo(uri); + NavigationManager.NavigateTo(uri); } private void SelectClicked(MediaCardViewModel card, MouseEventArgs e) diff --git a/ErsatzTV/Pages/FFmpegEditor.razor b/ErsatzTV/Pages/FFmpegEditor.razor index 1ef9f9d32..834196424 100644 --- a/ErsatzTV/Pages/FFmpegEditor.razor +++ b/ErsatzTV/Pages/FFmpegEditor.razor @@ -1,13 +1,13 @@ @page "/ffmpeg/{Id:int}" @page "/ffmpeg/add" -@using Microsoft.Extensions.Caching.Memory -@using ErsatzTV.Application.Resolutions -@using ErsatzTV.Application.FFmpegProfiles @using System.Runtime.InteropServices +@using ErsatzTV.Application.FFmpegProfiles +@using ErsatzTV.Application.Resolutions @using ErsatzTV.Core.FFmpeg @using ErsatzTV.FFmpeg @using ErsatzTV.FFmpeg.Format @using ErsatzTV.FFmpeg.Preset +@using Microsoft.Extensions.Caching.Memory @implements IDisposable @inject NavigationManager NavigationManager @inject ILogger Logger @@ -63,7 +63,7 @@ main high diff --git a/ErsatzTV/Pages/FillerPresetEditor.razor b/ErsatzTV/Pages/FillerPresetEditor.razor index ba375b5e7..14b311e73 100644 --- a/ErsatzTV/Pages/FillerPresetEditor.razor +++ b/ErsatzTV/Pages/FillerPresetEditor.razor @@ -1,16 +1,16 @@ @page "/media/filler/presets/{Id:int}/edit" @page "/media/filler/presets/add" +@using ErsatzTV.Application.Artists +@using ErsatzTV.Application.Filler @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaItems @using ErsatzTV.Application.Television -@using ErsatzTV.Application.Artists -@using ErsatzTV.Application.Filler @using ErsatzTV.Core.Domain.Filler @implements IDisposable -@inject NavigationManager _navigationManager -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject IMediator _mediator +@inject NavigationManager NavigationManager +@inject ILogger Logger +@inject ISnackbar Snackbar +@inject IMediator Mediator
@@ -160,22 +160,22 @@ protected override async Task OnParametersSetAsync() { - _mediaCollections = await _mediator.Send(new GetAllCollections(), _cts.Token) + _mediaCollections = await Mediator.Send(new GetAllCollections(), _cts.Token) .Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()); - _multiCollections = await _mediator.Send(new GetAllMultiCollections(), _cts.Token) + _multiCollections = await Mediator.Send(new GetAllMultiCollections(), _cts.Token) .Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()); - _smartCollections = await _mediator.Send(new GetAllSmartCollections(), _cts.Token) + _smartCollections = await Mediator.Send(new GetAllSmartCollections(), _cts.Token) .Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()); - _televisionShows = await _mediator.Send(new GetAllTelevisionShows(), _cts.Token) + _televisionShows = await Mediator.Send(new GetAllTelevisionShows(), _cts.Token) .Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()); - _televisionSeasons = await _mediator.Send(new GetAllTelevisionSeasons(), _cts.Token) + _televisionSeasons = await Mediator.Send(new GetAllTelevisionSeasons(), _cts.Token) .Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()); - _artists = await _mediator.Send(new GetAllArtists(), _cts.Token) + _artists = await Mediator.Send(new GetAllArtists(), _cts.Token) .Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()); if (IsEdit) { - Option maybeFillerPreset = await _mediator.Send(new GetFillerPresetById(Id), _cts.Token); + Option maybeFillerPreset = await Mediator.Send(new GetFillerPresetById(Id), _cts.Token); maybeFillerPreset.IfSome( fillerPreset => { @@ -225,16 +225,16 @@ { IRequest> request = IsEdit ? _model.ToEdit() : _model.ToUpdate(); - Seq errorMessage = await _mediator.Send(request, _cts.Token) + Seq errorMessage = await Mediator.Send(request, _cts.Token) .Map(result => result.LeftToSeq()); errorMessage.HeadOrNone().Match( error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Error saving filler preset: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Error saving filler preset: {Error}", error.Value); }, - () => _navigationManager.NavigateTo("media/filler/presets")); + () => NavigationManager.NavigateTo("media/filler/presets")); } } diff --git a/ErsatzTV/Pages/FillerPresets.razor b/ErsatzTV/Pages/FillerPresets.razor index 6db9ca50d..3cc91d231 100644 --- a/ErsatzTV/Pages/FillerPresets.razor +++ b/ErsatzTV/Pages/FillerPresets.razor @@ -1,10 +1,10 @@ @page "/media/filler/presets" -@using ErsatzTV.Application.Filler @using ErsatzTV.Application.Configuration +@using ErsatzTV.Application.Filler @using ErsatzTV.Core.Domain.Filler @implements IDisposable -@inject IDialogService _dialog -@inject IMediator _mediator +@inject IDialogService Dialog +@inject IMediator Mediator
@@ -80,7 +80,7 @@ _cts.Dispose(); } - protected override async Task OnParametersSetAsync() => _fillerPresetsRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.FillerPresetsPageSize), _cts.Token) + protected override async Task OnParametersSetAsync() => _fillerPresetsRowsPerPage = await Mediator.Send(new GetConfigElementByKey(ConfigElementKey.FillerPresetsPageSize), _cts.Token) .Map(maybeRows => maybeRows.Match(ce => int.TryParse(ce.Value, out int rows) ? rows : 10, () => 10)); private async Task DeleteFillerPreset(FillerPresetViewModel fillerPreset) @@ -88,11 +88,11 @@ var parameters = new DialogParameters { { "EntityType", "filler preset" }, { "EntityName", fillerPreset.Name } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Delete Filler Preset", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Delete Filler Preset", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled) { - await _mediator.Send(new DeleteFillerPreset(fillerPreset.Id), _cts.Token); + await Mediator.Send(new DeleteFillerPreset(fillerPreset.Id), _cts.Token); if (_fillerPresetsTable != null) { await _fillerPresetsTable.ReloadServerData(); @@ -102,9 +102,9 @@ private async Task> ServerReloadFillerPresets(TableState state) { - await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.FillerPresetsPageSize, state.PageSize.ToString()), _cts.Token); + await Mediator.Send(new SaveConfigElementByKey(ConfigElementKey.FillerPresetsPageSize, state.PageSize.ToString()), _cts.Token); - PagedFillerPresetsViewModel data = await _mediator.Send(new GetPagedFillerPresets(state.Page, state.PageSize), _cts.Token); + PagedFillerPresetsViewModel data = await Mediator.Send(new GetPagedFillerPresets(state.Page, state.PageSize), _cts.Token); return new TableData { TotalItems = data.TotalCount, Items = data.Page }; } diff --git a/ErsatzTV/Pages/ImageBrowser.razor b/ErsatzTV/Pages/ImageBrowser.razor index 165b16095..273036ac7 100644 --- a/ErsatzTV/Pages/ImageBrowser.razor +++ b/ErsatzTV/Pages/ImageBrowser.razor @@ -1,7 +1,7 @@ @page "/media/browser/images" -@using S = System.Collections.Generic -@using ErsatzTV.Application.Images @using System.Net +@using ErsatzTV.Application.Images +@using S = System.Collections.Generic @implements IDisposable @inject IDialogService Dialog @inject IMediator Mediator diff --git a/ErsatzTV/Pages/ImageList.razor b/ErsatzTV/Pages/ImageList.razor index 9be93a22b..85e34900e 100644 --- a/ErsatzTV/Pages/ImageList.razor +++ b/ErsatzTV/Pages/ImageList.razor @@ -1,9 +1,9 @@ @page "/media/images" @page "/media/images/page/{PageNumber:int}" -@using ErsatzTV.Extensions @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Search +@using ErsatzTV.Extensions @inherits MultiSelectBase @inject NavigationManager NavigationManager diff --git a/ErsatzTV/Pages/Index.razor b/ErsatzTV/Pages/Index.razor index 8c4f61ffb..8158c840d 100644 --- a/ErsatzTV/Pages/Index.razor +++ b/ErsatzTV/Pages/Index.razor @@ -1,9 +1,9 @@ @page "/" -@using Microsoft.Extensions.Caching.Memory @using System.Reflection +@using ErsatzTV.Application.Health @using ErsatzTV.Core.Health @using ErsatzTV.Core.Interfaces.GitHub -@using ErsatzTV.Application.Health +@using Microsoft.Extensions.Caching.Memory @implements IDisposable @inject IGitHubApiClient GitHubApiClient @inject IMemoryCache MemoryCache diff --git a/ErsatzTV/Pages/JellyfinLibrariesEditor.razor b/ErsatzTV/Pages/JellyfinLibrariesEditor.razor index 258436674..a1b711ea9 100644 --- a/ErsatzTV/Pages/JellyfinLibrariesEditor.razor +++ b/ErsatzTV/Pages/JellyfinLibrariesEditor.razor @@ -1,9 +1,9 @@ @page "/media/sources/jellyfin/{Id:int}/libraries" -@using ErsatzTV.Application.MediaSources @using ErsatzTV.Application.Jellyfin +@using ErsatzTV.Application.MediaSources @implements IDisposable -@inject IMediator _mediator -@inject ChannelWriter _scannerWorkerChannel +@inject IMediator Mediator +@inject ChannelWriter ScannerWorkerChannel new JellyfinLibraryPreference(l.Id, l.ShouldSyncItems)).ToList()); private async Task> GetLibrariesBySourceId(int mediaSourceId) => - await _mediator.Send(new GetJellyfinLibrariesBySourceId(Id), _cts.Token) + await Mediator.Send(new GetJellyfinLibrariesBySourceId(Id), _cts.Token) .Map(list => list.Map(ProjectToEditViewModel).OrderBy(x => x.MediaKind).ThenBy(x => x.Name).ToList()); private async Task> GetMediaSourceById(int mediaSourceId) => - await _mediator.Send(new GetJellyfinMediaSourceById(Id), _cts.Token) + await Mediator.Send(new GetJellyfinMediaSourceById(Id), _cts.Token) .MapT(vm => new RemoteMediaSourceViewModel(vm.Id, vm.Name, vm.Address)); private RemoteMediaSourceLibraryEditViewModel ProjectToEditViewModel(JellyfinLibraryViewModel library) => new() @@ -47,8 +47,8 @@ private async Task SynchronizeLibraryByIdIfNeeded(RemoteMediaSourceLibrariesEditor.SynchronizeParameters parameters) { - await _scannerWorkerChannel.WriteAsync(new SynchronizeJellyfinLibraries(parameters.MediaSourceId), _cts.Token); - await _scannerWorkerChannel.WriteAsync(new SynchronizeJellyfinLibraryByIdIfNeeded(parameters.LibraryId), _cts.Token); + await ScannerWorkerChannel.WriteAsync(new SynchronizeJellyfinLibraries(parameters.MediaSourceId), _cts.Token); + await ScannerWorkerChannel.WriteAsync(new SynchronizeJellyfinLibraryByIdIfNeeded(parameters.LibraryId), _cts.Token); return Unit.Default; } diff --git a/ErsatzTV/Pages/JellyfinMediaSourceEditor.razor b/ErsatzTV/Pages/JellyfinMediaSourceEditor.razor index d4004e1d9..a440018fc 100644 --- a/ErsatzTV/Pages/JellyfinMediaSourceEditor.razor +++ b/ErsatzTV/Pages/JellyfinMediaSourceEditor.razor @@ -1,11 +1,8 @@ @page "/media/sources/jellyfin/edit" -@using ErsatzTV.Core.Jellyfin @using ErsatzTV.Application.Jellyfin +@using ErsatzTV.Core.Jellyfin @implements IDisposable -@inject IMediator _mediator -@inject NavigationManager _navigationManager -@inject ISnackbar _snackbar -@inject ILogger _logger +@inject IMediator Mediator LoadSecrets(RemoteMediaSourceEditViewModel viewModel) { - JellyfinSecrets secrets = await _mediator.Send(new GetJellyfinSecrets(), _cts.Token); + JellyfinSecrets secrets = await Mediator.Send(new GetJellyfinSecrets(), _cts.Token); viewModel.Address = secrets.Address; viewModel.ApiKey = secrets.ApiKey; return Unit.Default; @@ -32,7 +29,7 @@ private async Task> SaveSecrets(RemoteMediaSourceEditViewModel viewModel) { var secrets = new JellyfinSecrets { Address = viewModel.Address, ApiKey = viewModel.ApiKey }; - return await _mediator.Send(new SaveJellyfinSecrets(secrets), _cts.Token); + return await Mediator.Send(new SaveJellyfinSecrets(secrets), _cts.Token); } } \ No newline at end of file diff --git a/ErsatzTV/Pages/JellyfinMediaSources.razor b/ErsatzTV/Pages/JellyfinMediaSources.razor index 11b63c863..dcde3228f 100644 --- a/ErsatzTV/Pages/JellyfinMediaSources.razor +++ b/ErsatzTV/Pages/JellyfinMediaSources.razor @@ -1,10 +1,10 @@ @page "/media/sources/jellyfin" -@using ErsatzTV.Core.Interfaces.Jellyfin @using ErsatzTV.Application.Jellyfin +@using ErsatzTV.Core.Interfaces.Jellyfin @using ErsatzTV.Core.Jellyfin @implements IDisposable -@inject IJellyfinSecretStore _jellyfinSecretStore -@inject ChannelWriter _scannerWorkerChannel +@inject IJellyfinSecretStore JellyfinSecretStore +@inject ChannelWriter ScannerWorkerChannel + SecretStore="@JellyfinSecretStore"/> @code { private readonly CancellationTokenSource _cts = new(); @@ -26,6 +26,6 @@ } private async Task RefreshLibraries(int mediaSourceId) => - await _scannerWorkerChannel.WriteAsync(new SynchronizeJellyfinLibraries(mediaSourceId), _cts.Token); + await ScannerWorkerChannel.WriteAsync(new SynchronizeJellyfinLibraries(mediaSourceId), _cts.Token); } \ No newline at end of file diff --git a/ErsatzTV/Pages/JellyfinPathReplacementsEditor.razor b/ErsatzTV/Pages/JellyfinPathReplacementsEditor.razor index 1e892a29e..95ff216a0 100644 --- a/ErsatzTV/Pages/JellyfinPathReplacementsEditor.razor +++ b/ErsatzTV/Pages/JellyfinPathReplacementsEditor.razor @@ -1,11 +1,8 @@ @page "/media/sources/jellyfin/{Id:int}/paths" -@using ErsatzTV.Application.MediaSources @using ErsatzTV.Application.Jellyfin +@using ErsatzTV.Application.MediaSources @implements IDisposable -@inject NavigationManager _navigationManager -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject IMediator _mediator +@inject IMediator Mediator > GetMediaSourceById(int id) => - await _mediator.Send(new GetJellyfinMediaSourceById(Id), _cts.Token) + await Mediator.Send(new GetJellyfinMediaSourceById(Id), _cts.Token) .MapT(vm => new RemoteMediaSourceViewModel(vm.Id, vm.Name, vm.Address)); private async Task> GetPathReplacementsBySourceId(int mediaSourceId) => - await _mediator.Send(new GetJellyfinPathReplacementsBySourceId(Id), _cts.Token) + await Mediator.Send(new GetJellyfinPathReplacementsBySourceId(Id), _cts.Token) .Map(list => list.Map(ProjectToEditViewModel).ToList()); private RemoteMediaSourcePathReplacementEditViewModel ProjectToEditViewModel(JellyfinPathReplacementViewModel item) => diff --git a/ErsatzTV/Pages/Libraries.razor b/ErsatzTV/Pages/Libraries.razor index c003c9682..2fb4d1cbd 100644 --- a/ErsatzTV/Pages/Libraries.razor +++ b/ErsatzTV/Pages/Libraries.razor @@ -1,12 +1,12 @@ @page "/media/libraries" -@using PlexLibraryViewModel = ErsatzTV.Application.Libraries.PlexLibraryViewModel +@using ErsatzTV.Application.Emby +@using ErsatzTV.Application.Jellyfin @using ErsatzTV.Application.Libraries @using ErsatzTV.Application.MediaSources @using ErsatzTV.Application.Plex @using ErsatzTV.Core.Metadata @using MediatR.Courier -@using ErsatzTV.Application.Jellyfin -@using ErsatzTV.Application.Emby +@using PlexLibraryViewModel = ErsatzTV.Application.Libraries.PlexLibraryViewModel @implements IDisposable @inject IMediator Mediator @inject IEntityLocker Locker diff --git a/ErsatzTV/Pages/LocalLibraries.razor b/ErsatzTV/Pages/LocalLibraries.razor index 5ee59a17a..19db8e017 100644 --- a/ErsatzTV/Pages/LocalLibraries.razor +++ b/ErsatzTV/Pages/LocalLibraries.razor @@ -1,13 +1,9 @@ @page "/media/sources/local" @using ErsatzTV.Application.Libraries @implements IDisposable -@inject IDialogService _dialog -@inject IMediator _mediator -@inject IEntityLocker _locker -@inject ChannelWriter _workerChannel -@inject ChannelWriter _plexWorkerChannel -@inject ChannelWriter _jellyfinWorkerChannel -@inject ChannelWriter _embyWorkerChannel +@inject IDialogService Dialog +@inject IMediator Mediator +@inject IEntityLocker Locker @@ -31,13 +27,13 @@
@@ -55,18 +51,18 @@ private IList _libraries; - protected override void OnInitialized() => _locker.OnLibraryChanged += LockChanged; + protected override void OnInitialized() => Locker.OnLibraryChanged += LockChanged; protected override async Task OnParametersSetAsync() => await LoadLibraries(_cts.Token); - private async Task LoadLibraries(CancellationToken cancellationToken) => _libraries = await _mediator.Send(new GetAllLocalLibraries(), cancellationToken); + private async Task LoadLibraries(CancellationToken cancellationToken) => _libraries = await Mediator.Send(new GetAllLocalLibraries(), cancellationToken); private void LockChanged(object sender, EventArgs e) => InvokeAsync(StateHasChanged); private async Task DeleteLibrary(LocalLibraryViewModel library) { - int count = await _mediator.Send(new CountMediaItemsByLibrary(library.Id), _cts.Token); + int count = await Mediator.Send(new CountMediaItemsByLibrary(library.Id), _cts.Token); var parameters = new DialogParameters { { "EntityType", "library" }, @@ -76,18 +72,18 @@ }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Delete Library", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Delete Library", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled) { - await _mediator.Send(new DeleteLocalLibrary(library.Id), _cts.Token); + await Mediator.Send(new DeleteLocalLibrary(library.Id), _cts.Token); await LoadLibraries(_cts.Token); } } void IDisposable.Dispose() { - _locker.OnLibraryChanged -= LockChanged; + Locker.OnLibraryChanged -= LockChanged; _cts.Cancel(); _cts.Dispose(); diff --git a/ErsatzTV/Pages/LocalLibraryEditor.razor b/ErsatzTV/Pages/LocalLibraryEditor.razor index 2621d315c..bdb3b9070 100644 --- a/ErsatzTV/Pages/LocalLibraryEditor.razor +++ b/ErsatzTV/Pages/LocalLibraryEditor.razor @@ -2,12 +2,12 @@ @page "/media/sources/local/add" @using ErsatzTV.Application.Libraries @implements IDisposable -@inject IDialogService _dialog -@inject IEntityLocker _locker -@inject IMediator _mediator -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject NavigationManager _navigationManager +@inject IDialogService Dialog +@inject IEntityLocker Locker +@inject IMediator Mediator +@inject ILogger Logger +@inject ISnackbar Snackbar +@inject NavigationManager NavigationManager
@@ -56,7 +56,7 @@
@@ -89,7 +89,7 @@ { if (IsEdit) { - Option maybeLibrary = await _mediator.Send(new GetLocalLibraryById(Id), _cts.Token); + Option maybeLibrary = await Mediator.Send(new GetLocalLibraryById(Id), _cts.Token); await maybeLibrary.Match( async library => { @@ -101,7 +101,7 @@ }, () => { - _navigationManager.NavigateTo("404"); + NavigationManager.NavigateTo("404"); return Task.CompletedTask; }); } @@ -116,7 +116,7 @@ protected override void OnInitialized() { - _locker.OnLibraryChanged += LockChanged; + Locker.OnLibraryChanged += LockChanged; _editContext = new EditContext(_model); _messageStore = new ValidationMessageStore(_editContext); @@ -128,7 +128,7 @@ private async Task LoadLibraryPaths() { _model.HasChanges = false; - _model.Paths = await _mediator.Send(new GetLocalLibraryPaths(Id), _cts.Token) + _model.Paths = await Mediator.Send(new GetLocalLibraryPaths(Id), _cts.Token) .Map( list => list.Map( vm => new LocalLibraryPathEditViewModel @@ -143,18 +143,18 @@ var parameters = new DialogParameters { { "MediaKind", _model.MediaKind }, { "SourceLibraryId", Id } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Move Local Library Path", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Move Local Library Path", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is LocalLibraryViewModel library) { var request = new MoveLocalLibraryPath(libraryPath.Id, library.Id); - Either moveResult = await _mediator.Send(request, _cts.Token); + Either moveResult = await Mediator.Send(request, _cts.Token); moveResult.Match( - _ => _navigationManager.NavigateTo($"media/sources/local/{library.Id}/edit"), + _ => NavigationManager.NavigateTo($"media/sources/local/{library.Id}/edit"), error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Unexpected error moving local library path: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Unexpected error moving local library path: {Error}", error.Value); }); } } @@ -167,7 +167,7 @@ _model.Paths.Remove(libraryPath); } - int count = await _mediator.Send(new CountMediaItemsByLibraryPath(libraryPath.Id), _cts.Token); + int count = await Mediator.Send(new CountMediaItemsByLibraryPath(libraryPath.Id), _cts.Token); var parameters = new DialogParameters { { "EntityType", "library path" }, @@ -177,7 +177,7 @@ }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Delete Library Path", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Delete Library Path", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled) { @@ -207,13 +207,13 @@ if (_editContext.Validate()) { Either result = IsEdit - ? await _mediator.Send( + ? await Mediator.Send( new UpdateLocalLibrary( _model.Id, _model.Name, _model.Paths.Map(p => new UpdateLocalLibraryPath(p.Id, p.Path)).ToList()), _cts.Token) - : await _mediator.Send( + : await Mediator.Send( new CreateLocalLibrary( _model.Name, _model.MediaKind, @@ -221,11 +221,11 @@ _cts.Token); result.Match( - _ => _navigationManager.NavigateTo("media/sources/local"), + _ => NavigationManager.NavigateTo("media/sources/local"), error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Unexpected error saving local library: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Unexpected error saving local library: {Error}", error.Value); }); } } @@ -236,7 +236,7 @@ void IDisposable.Dispose() { - _locker.OnLibraryChanged -= LockChanged; + Locker.OnLibraryChanged -= LockChanged; _cts.Cancel(); _cts.Dispose(); diff --git a/ErsatzTV/Pages/LocalLibraryPathEditor.razor b/ErsatzTV/Pages/LocalLibraryPathEditor.razor index f74c819d0..adc7054cb 100644 --- a/ErsatzTV/Pages/LocalLibraryPathEditor.razor +++ b/ErsatzTV/Pages/LocalLibraryPathEditor.razor @@ -2,12 +2,12 @@ @using ErsatzTV.Application.Libraries @using ErsatzTV.Application.MediaSources @implements IDisposable -@inject NavigationManager _navigationManager -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject IMediator _mediator -@inject IEntityLocker _locker -@inject ChannelWriter _scannerWorkerChannel; +@inject NavigationManager NavigationManager +@inject ILogger Logger +@inject ISnackbar Snackbar +@inject IMediator Mediator +@inject IEntityLocker Locker +@inject ChannelWriter ScannerWorkerChannel @_library.Name - Add Local Library Path @@ -50,10 +50,10 @@ protected override async Task OnParametersSetAsync() { - Option maybeLibrary = await _mediator.Send(new GetLocalLibraryById(Id), _cts.Token); + Option maybeLibrary = await Mediator.Send(new GetLocalLibraryById(Id), _cts.Token); maybeLibrary.Match( library => _library = library, - () => _navigationManager.NavigateTo("404")); + () => NavigationManager.NavigateTo("404")); } protected override void OnInitialized() @@ -68,20 +68,20 @@ if (_editContext.Validate()) { var command = new CreateLocalLibraryPath(_library.Id, _model.Path); - Either result = await _mediator.Send(command, _cts.Token); + Either result = await Mediator.Send(command, _cts.Token); await result.Match( Left: error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Unexpected error saving local library path: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Unexpected error saving local library path: {Error}", error.Value); return Task.CompletedTask; }, Right: async _ => { - if (_locker.LockLibrary(_library.Id)) + if (Locker.LockLibrary(_library.Id)) { - await _scannerWorkerChannel.WriteAsync(new ScanLocalLibraryIfNeeded(_library.Id), _cts.Token); - _navigationManager.NavigateTo("media/libraries"); + await ScannerWorkerChannel.WriteAsync(new ScanLocalLibraryIfNeeded(_library.Id), _cts.Token); + NavigationManager.NavigateTo("media/libraries"); } }); } diff --git a/ErsatzTV/Pages/Logs.razor b/ErsatzTV/Pages/Logs.razor index 3d2ef11cf..2114f22a2 100644 --- a/ErsatzTV/Pages/Logs.razor +++ b/ErsatzTV/Pages/Logs.razor @@ -1,6 +1,6 @@ @page "/system/logs" -@using ErsatzTV.Application.Logs @using ErsatzTV.Application.Configuration +@using ErsatzTV.Application.Logs @implements IDisposable @inject IMediator Mediator diff --git a/ErsatzTV/Pages/Movie.razor b/ErsatzTV/Pages/Movie.razor index fd0dc8f89..17455aef9 100644 --- a/ErsatzTV/Pages/Movie.razor +++ b/ErsatzTV/Pages/Movie.razor @@ -1,10 +1,10 @@ @page "/media/movies/{MovieId:int}" -@using LanguageExt.UnsafeValueAccess -@using ErsatzTV.Extensions -@using ErsatzTV.Application.Movies +@using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaItems -@using ErsatzTV.Application.MediaCards +@using ErsatzTV.Application.Movies +@using ErsatzTV.Extensions +@using LanguageExt.UnsafeValueAccess @implements IDisposable @inject IMediator Mediator @inject IDialogService Dialog diff --git a/ErsatzTV/Pages/MovieList.razor b/ErsatzTV/Pages/MovieList.razor index 3597aefe1..26388d1a9 100644 --- a/ErsatzTV/Pages/MovieList.razor +++ b/ErsatzTV/Pages/MovieList.razor @@ -3,10 +3,10 @@ @inherits MultiSelectBase @inject NavigationManager NavigationManager @inject PersistentComponentState ApplicationState -@using ErsatzTV.Extensions @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Search +@using ErsatzTV.Extensions @implements IDisposable diff --git a/ErsatzTV/Pages/MultiCollectionEditor.razor b/ErsatzTV/Pages/MultiCollectionEditor.razor index dae0e28e2..c84ad39ad 100644 --- a/ErsatzTV/Pages/MultiCollectionEditor.razor +++ b/ErsatzTV/Pages/MultiCollectionEditor.razor @@ -2,10 +2,10 @@ @page "/media/multi-collections/add" @using ErsatzTV.Application.MediaCollections @implements IDisposable -@inject IMediator _mediator -@inject NavigationManager _navigationManager -@inject ISnackbar _snackbar -@inject ILogger _logger +@inject IMediator Mediator +@inject NavigationManager NavigationManager +@inject ISnackbar Snackbar +@inject ILogger Logger
@@ -43,7 +43,7 @@ HelperText="Disabled collections are already present in this multi collection"> @foreach (SmartCollectionViewModel collection in _smartCollections) { - @collection.Name @@ -131,15 +131,15 @@ protected override async Task OnParametersSetAsync() { - _collections = await _mediator.Send(new GetAllCollections(), _cts.Token) + _collections = await Mediator.Send(new GetAllCollections(), _cts.Token) .Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()); - _smartCollections = await _mediator.Send(new GetAllSmartCollections(), _cts.Token) + _smartCollections = await Mediator.Send(new GetAllSmartCollections(), _cts.Token) .Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()); if (IsEdit) { - Option maybeCollection = await _mediator.Send(new GetMultiCollectionById(Id), _cts.Token); + Option maybeCollection = await Mediator.Send(new GetMultiCollectionById(Id), _cts.Token); maybeCollection.IfSome( collection => { @@ -185,15 +185,15 @@ _messageStore.Clear(); if (_editContext.Validate()) { - Seq errorMessage = IsEdit ? (await _mediator.Send(new UpdateMultiCollection(Id, _model.Name, GetUpdateItems()), _cts.Token)).LeftToSeq() : (await _mediator.Send(new CreateMultiCollection(_model.Name, GetCreateItems()), _cts.Token)).LeftToSeq(); + Seq errorMessage = IsEdit ? (await Mediator.Send(new UpdateMultiCollection(Id, _model.Name, GetUpdateItems()), _cts.Token)).LeftToSeq() : (await Mediator.Send(new CreateMultiCollection(_model.Name, GetCreateItems()), _cts.Token)).LeftToSeq(); errorMessage.HeadOrNone().Match( error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Error saving collection: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Error saving collection: {Error}", error.Value); }, - () => _navigationManager.NavigateTo("media/collections")); + () => NavigationManager.NavigateTo("media/collections")); } } diff --git a/ErsatzTV/Pages/MultiSelectBase.cs b/ErsatzTV/Pages/MultiSelectBase.cs index 5daabe4d2..ca28ee767 100644 --- a/ErsatzTV/Pages/MultiSelectBase.cs +++ b/ErsatzTV/Pages/MultiSelectBase.cs @@ -91,7 +91,7 @@ public class MultiSelectBase : FragmentNavigationBase SelectedItems.OfType().Map(ov => ov.OtherVideoId).ToList(), SelectedItems.OfType().Map(s => s.SongId).ToList(), SelectedItems.OfType().Map(i => i.ImageId).ToList()); - + protected Task AddSelectionToPlaylist() => AddItemsToPlaylist( SelectedItems.OfType().Map(m => m.MovieId).ToList(), SelectedItems.OfType().Map(s => s.TelevisionShowId).ToList(), @@ -185,7 +185,7 @@ public class MultiSelectBase : FragmentNavigationBase ClearSelection(); } } - + protected async Task AddItemsToPlaylist( List movieIds, List showIds, diff --git a/ErsatzTV/Pages/MusicVideoList.razor b/ErsatzTV/Pages/MusicVideoList.razor index a8a059833..d964a2fc4 100644 --- a/ErsatzTV/Pages/MusicVideoList.razor +++ b/ErsatzTV/Pages/MusicVideoList.razor @@ -1,12 +1,11 @@ @page "/media/music/videos" @page "/media/music/videos/page/{PageNumber:int}" -@using ErsatzTV.Extensions @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Search +@using ErsatzTV.Extensions @inherits MultiSelectBase -@inject NavigationManager _navigationManager -@inject ChannelWriter _channel +@inject NavigationManager NavigationManager
@@ -93,7 +92,7 @@ PageNumber = 1; } - _query = _navigationManager.Uri.GetSearchQuery(); + _query = NavigationManager.Uri.GetSearchQuery(); await RefreshData(); } @@ -113,7 +112,7 @@ uri = $"{uri}?{key}={value}"; } - _navigationManager.NavigateTo(uri); + NavigationManager.NavigateTo(uri); } private void NextPage() @@ -125,7 +124,7 @@ uri = $"{uri}?{key}={value}"; } - _navigationManager.NavigateTo(uri); + NavigationManager.NavigateTo(uri); } private void SelectClicked(MediaCardViewModel card, MouseEventArgs e) diff --git a/ErsatzTV/Pages/OtherVideoList.razor b/ErsatzTV/Pages/OtherVideoList.razor index 7d297d5a5..59879ea97 100644 --- a/ErsatzTV/Pages/OtherVideoList.razor +++ b/ErsatzTV/Pages/OtherVideoList.razor @@ -1,9 +1,9 @@ @page "/media/other/videos" @page "/media/other/videos/page/{PageNumber:int}" -@using ErsatzTV.Extensions @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Search +@using ErsatzTV.Extensions @inherits MultiSelectBase @inject NavigationManager NavigationManager diff --git a/ErsatzTV/Pages/PlaylistEditor.razor b/ErsatzTV/Pages/PlaylistEditor.razor index 85ebe0bff..6dd8fbf2f 100644 --- a/ErsatzTV/Pages/PlaylistEditor.razor +++ b/ErsatzTV/Pages/PlaylistEditor.razor @@ -1,8 +1,8 @@ @page "/media/playlists/{Id:int}" -@using ErsatzTV.Application.Scheduling -@using ErsatzTV.Application.Search @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaItems +@using ErsatzTV.Application.Scheduling +@using ErsatzTV.Application.Search @implements IDisposable @inject NavigationManager NavigationManager @inject ILogger Logger diff --git a/ErsatzTV/Pages/Playlists.razor b/ErsatzTV/Pages/Playlists.razor index 22c019a94..8e178517a 100644 --- a/ErsatzTV/Pages/Playlists.razor +++ b/ErsatzTV/Pages/Playlists.razor @@ -1,6 +1,6 @@ @page "/media/playlists" -@using S = System.Collections.Generic @using ErsatzTV.Application.MediaCollections +@using S = System.Collections.Generic @implements IDisposable @inject ILogger Logger @inject ISnackbar Snackbar diff --git a/ErsatzTV/Pages/PlayoutAlternateSchedulesEditor.razor b/ErsatzTV/Pages/PlayoutAlternateSchedulesEditor.razor index 580d264c6..205fec59e 100644 --- a/ErsatzTV/Pages/PlayoutAlternateSchedulesEditor.razor +++ b/ErsatzTV/Pages/PlayoutAlternateSchedulesEditor.razor @@ -1,9 +1,9 @@ @page "/playouts/{Id:int}/alternate-schedules" @using System.Globalization -@using ErsatzTV.Application.ProgramSchedules -@using ErsatzTV.Application.Playouts -@using ErsatzTV.Application.Channels @using System.Text +@using ErsatzTV.Application.Channels +@using ErsatzTV.Application.Playouts +@using ErsatzTV.Application.ProgramSchedules @implements IDisposable @inject NavigationManager NavigationManager @inject ILogger Logger diff --git a/ErsatzTV/Pages/PlayoutTemplatesEditor.razor b/ErsatzTV/Pages/PlayoutTemplatesEditor.razor index cbb76f43a..418848616 100644 --- a/ErsatzTV/Pages/PlayoutTemplatesEditor.razor +++ b/ErsatzTV/Pages/PlayoutTemplatesEditor.razor @@ -1,9 +1,9 @@ @page "/playouts/{Id:int}/templates" @using System.Globalization -@using ErsatzTV.Application.Scheduling +@using System.Text @using ErsatzTV.Application.Channels +@using ErsatzTV.Application.Scheduling @using ErsatzTV.Core.Domain.Scheduling -@using System.Text @implements IDisposable @inject NavigationManager NavigationManager @inject ILogger Logger @@ -11,285 +11,285 @@ @inject IMediator Mediator - - - @_channelName Templates - - In priority order from top to bottom - - - - - - - - - - - - Template - Days of the Week - Days of the Month - Months - - - - - - - - @context.Template?.Name - - - - - @ToDaysOfWeekString(context.DaysOfWeek) - - - - - @ToDaysOfMonthString(context.DaysOfMonth) - - - - - @ToMonthsOfYearString(context.MonthsOfYear) - - - - - - - - - - - - - - - - - - Add Template - - - Save Changes - - - Preview Calendar - - - @if (_selectedItem is not null) - { - - -
-
- - - - @foreach (TemplateGroupViewModel templateGroup in _templateGroups) - { - - @templateGroup.Name - - } - - - @foreach (TemplateViewModel template in _templates) - { - @template.Name - } - - - - - - - @foreach (DecoTemplateGroupViewModel decoTemplateGroup in _decoTemplateGroups) - { - - @decoTemplateGroup.Name - - } - - - @foreach (DecoTemplateViewModel decoTemplate in _decoTemplates) - { - @decoTemplate.Name - } - - - - - - - @if (_selectedItem.LimitToDateRange) + + + @_channelName Templates + + In priority order from top to bottom + + + + + + + + + + + + Template + Days of the Week + Days of the Month + Months + + + + + + + + @context.Template?.Name + + + + + @ToDaysOfWeekString(context.DaysOfWeek) + + + + + @ToDaysOfMonthString(context.DaysOfMonth) + + + + + @ToMonthsOfYearString(context.MonthsOfYear) + + + + + + + + + + + + + + + + + + Add Template + + + Save Changes + + + Preview Calendar + + +@if (_selectedItem is not null) +{ + + +
+
+ + + + @foreach (TemplateGroupViewModel templateGroup in _templateGroups) { - - - - @foreach (int month in Enumerable.Range(1, 12)) - { - @_dtf.GetMonthName(month) - } - - - - - @foreach (int day in Enumerable.Range(1, 31)) - { - @day.ToString() - } - - - - - - - @foreach (int month in Enumerable.Range(1, 12)) - { - @_dtf.GetMonthName(month) - } - - - - - @foreach (int day in Enumerable.Range(1, 31)) - { - @day.ToString() - } - - - + + @templateGroup.Name + } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Weekdays - - - Weekends - - - All - - - None - - - -
-
- - - - @foreach (int day in Enumerable.Range(1, 31)) - { - - - - } + + + @foreach (TemplateViewModel template in _templates) + { + @template.Name + } + + + + + + + @foreach (DecoTemplateGroupViewModel decoTemplateGroup in _decoTemplateGroups) + { + + @decoTemplateGroup.Name + + } + + + @foreach (DecoTemplateViewModel decoTemplate in _decoTemplates) + { + @decoTemplate.Name + } + + + + + + + @if (_selectedItem.LimitToDateRange) + { + + + + @foreach (int month in Enumerable.Range(1, 12)) + { + @_dtf.GetMonthName(month) + } + + + + + @foreach (int day in Enumerable.Range(1, 31)) + { + @day.ToString() + } + + - - - - All - - - None - - - -
-
- - - - - - @foreach (int month in Enumerable.Range(2, 11)) + + + + @foreach (int month in Enumerable.Range(1, 12)) + { + @_dtf.GetMonthName(month) + } + + + + + @foreach (int day in Enumerable.Range(1, 31)) + { + @day.ToString() + } + + + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Weekdays + + + Weekends + + + All + + + None + + + +
+
+ + + + @foreach (int day in Enumerable.Range(1, 31)) { - - - + + + } - - - - All - - - None - - - -
+ + + + + All + + + None + + +
-
- } - else - { - - - - } +
+ + + + + + @foreach (int month in Enumerable.Range(2, 11)) + { + + + + } + + + + All + + + None + + + +
+
+ +} +else +{ + + + +} @code { @@ -330,7 +330,7 @@ _decoTemplateGroups.Clear(); _decoTemplateGroups.AddRange(await Mediator.Send(new GetAllDecoTemplateGroups(), _cts.Token)); - + List results = await Mediator.Send(new GetPlayoutTemplates(Id), _cts.Token); _items = results.Map(ProjectToEditViewModel).ToList(); if (_items.Count == 1) @@ -380,7 +380,7 @@ { await UpdateTemplateGroupItems(group); } - + foreach (DecoTemplateGroupViewModel group in Optional(_decoTemplateGroups.Find(group => group.Id == _selectedItem?.DecoTemplate?.DecoTemplateGroupId))) { await UpdateDecoTemplateGroupItems(group); diff --git a/ErsatzTV/Pages/Playouts.razor b/ErsatzTV/Pages/Playouts.razor index fbb1e27fb..6bb85c852 100644 --- a/ErsatzTV/Pages/Playouts.razor +++ b/ErsatzTV/Pages/Playouts.razor @@ -1,11 +1,11 @@ @page "/playouts" -@using ErsatzTV.Application.Playouts @using ErsatzTV.Application.Configuration +@using ErsatzTV.Application.Playouts @using ErsatzTV.Core.Scheduling @implements IDisposable @inject IDialogService Dialog @inject IMediator Mediator -@inject ChannelWriter WorkerChannel; +@inject ChannelWriter WorkerChannel @inject IEntityLocker EntityLocker; diff --git a/ErsatzTV/Pages/PlexLibrariesEditor.razor b/ErsatzTV/Pages/PlexLibrariesEditor.razor index decd5e014..2ebc4c6ea 100644 --- a/ErsatzTV/Pages/PlexLibrariesEditor.razor +++ b/ErsatzTV/Pages/PlexLibrariesEditor.razor @@ -2,8 +2,8 @@ @using ErsatzTV.Application.MediaSources @using ErsatzTV.Application.Plex @implements IDisposable -@inject IMediator _mediator -@inject ChannelWriter _scannerWorkerChannel +@inject IMediator Mediator +@inject ChannelWriter ScannerWorkerChannel new PlexLibraryPreference(l.Id, l.ShouldSyncItems)).ToList()); private async Task> GetLibrariesBySourceId(int mediaSourceId) => - await _mediator.Send(new GetPlexLibrariesBySourceId(Id), _cts.Token) + await Mediator.Send(new GetPlexLibrariesBySourceId(Id), _cts.Token) .Map(list => list.Map(ProjectToEditViewModel).OrderBy(x => x.MediaKind).ThenBy(x => x.Name).ToList()); private async Task> GetMediaSourceById(int mediaSourceId) => - await _mediator.Send(new GetPlexMediaSourceById(Id), _cts.Token) + await Mediator.Send(new GetPlexMediaSourceById(Id), _cts.Token) .MapT(vm => new RemoteMediaSourceViewModel(vm.Id, vm.Name, vm.Address)); public void Dispose() @@ -47,7 +47,7 @@ private async Task SynchronizeLibraryByIdIfNeeded(RemoteMediaSourceLibrariesEditor.SynchronizeParameters parameters) { - await _scannerWorkerChannel.WriteAsync(new SynchronizePlexLibraryByIdIfNeeded(parameters.LibraryId), _cts.Token); + await ScannerWorkerChannel.WriteAsync(new SynchronizePlexLibraryByIdIfNeeded(parameters.LibraryId), _cts.Token); return Unit.Default; } diff --git a/ErsatzTV/Pages/PlexMediaSources.razor b/ErsatzTV/Pages/PlexMediaSources.razor index 32b828e8d..14c7e6ba5 100644 --- a/ErsatzTV/Pages/PlexMediaSources.razor +++ b/ErsatzTV/Pages/PlexMediaSources.razor @@ -2,14 +2,14 @@ @using ErsatzTV.Application.Plex @using ErsatzTV.Core.Interfaces.Plex @implements IDisposable -@inject IDialogService _dialog -@inject IMediator _mediator -@inject IEntityLocker _locker -@inject ISnackbar _snackbar -@inject ILogger _logger -@inject IJSRuntime _jsRuntime -@inject IPlexSecretStore _plexSecretStore -@inject ChannelWriter _scannerWorkerChannel +@inject IDialogService Dialog +@inject IMediator Mediator +@inject IEntityLocker Locker +@inject ISnackbar Snackbar +@inject ILogger Logger +@inject IJSRuntime JsRuntime +@inject IPlexSecretStore PlexSecretStore +@inject ChannelWriter ScannerWorkerChannel @@ -33,7 +33,7 @@
@@ -56,7 +56,7 @@ Sign out of plex @@ -66,7 +66,7 @@ Sign in to plex @@ -77,7 +77,7 @@ Fix Plex Credentials @@ -93,24 +93,24 @@ protected override async Task OnParametersSetAsync() => await LoadMediaSources(); protected override void OnInitialized() => - _locker.OnPlexChanged += PlexChanged; + Locker.OnPlexChanged += PlexChanged; private async Task LoadMediaSources() { - _isAuthorized = await _plexSecretStore.GetUserAuthTokens().Map(list => Optional(list).Flatten().Any()); - _mediaSources = await _mediator.Send(new GetAllPlexMediaSources()); + _isAuthorized = await PlexSecretStore.GetUserAuthTokens().Map(list => Optional(list).Flatten().Any()); + _mediaSources = await Mediator.Send(new GetAllPlexMediaSources()); } private async Task SignOutOfPlex() { var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small }; - IDialogReference dialog = await _dialog.ShowAsync("Sign out of Plex", options); + IDialogReference dialog = await Dialog.ShowAsync("Sign out of Plex", options); DialogResult result = await dialog.Result; if (!result.Canceled) { - if (_locker.LockPlex()) + if (Locker.LockPlex()) { - await _mediator.Send(new SignOutOfPlex()); + await Mediator.Send(new SignOutOfPlex()); await LoadMediaSources(); } } @@ -118,15 +118,15 @@ private async Task AddPlexMediaSource() { - if (_locker.LockPlex()) + if (Locker.LockPlex()) { - Either maybeUrl = await _mediator.Send(new StartPlexPinFlow()); + Either maybeUrl = await Mediator.Send(new StartPlexPinFlow()); await maybeUrl.Match( async url => { try { - await _jsRuntime.InvokeAsync("open", new object[] { url, "_blank" }); + await JsRuntime.InvokeAsync("open", new object[] { url, "_blank" }); } catch (Exception) { @@ -135,9 +135,9 @@ }, error => { - _locker.UnlockPlex(); - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Unexpected error generating plex auth app url: {Error}", error.Value); + Locker.UnlockPlex(); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Unexpected error generating plex auth app url: {Error}", error.Value); return Task.CompletedTask; }); } @@ -150,8 +150,8 @@ } private async Task RefreshLibraries(int mediaSourceId) => - await _scannerWorkerChannel.WriteAsync(new SynchronizePlexLibraries(mediaSourceId)); + await ScannerWorkerChannel.WriteAsync(new SynchronizePlexLibraries(mediaSourceId)); - void IDisposable.Dispose() => _locker.OnPlexChanged -= PlexChanged; + void IDisposable.Dispose() => Locker.OnPlexChanged -= PlexChanged; } \ No newline at end of file diff --git a/ErsatzTV/Pages/PlexPathReplacementsEditor.razor b/ErsatzTV/Pages/PlexPathReplacementsEditor.razor index 366b600d7..45883db2d 100644 --- a/ErsatzTV/Pages/PlexPathReplacementsEditor.razor +++ b/ErsatzTV/Pages/PlexPathReplacementsEditor.razor @@ -2,10 +2,7 @@ @using ErsatzTV.Application.MediaSources @using ErsatzTV.Application.Plex @implements IDisposable -@inject NavigationManager _navigationManager -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject IMediator _mediator +@inject IMediator Mediator > GetMediaSourceById(int id) => - await _mediator.Send(new GetPlexMediaSourceById(Id), _cts.Token) + await Mediator.Send(new GetPlexMediaSourceById(Id), _cts.Token) .MapT(vm => new RemoteMediaSourceViewModel(vm.Id, vm.Name, vm.Address)); private async Task> GetPathReplacementsBySourceId(int mediaSourceId) => - await _mediator.Send(new GetPlexPathReplacementsBySourceId(Id), _cts.Token) + await Mediator.Send(new GetPlexPathReplacementsBySourceId(Id), _cts.Token) .Map(list => list.Map(ProjectToEditViewModel).ToList()); private RemoteMediaSourcePathReplacementEditViewModel ProjectToEditViewModel(PlexPathReplacementViewModel item) => diff --git a/ErsatzTV/Pages/ScheduleItemsEditor.razor b/ErsatzTV/Pages/ScheduleItemsEditor.razor index a31e02b4d..fd427f101 100644 --- a/ErsatzTV/Pages/ScheduleItemsEditor.razor +++ b/ErsatzTV/Pages/ScheduleItemsEditor.razor @@ -92,300 +92,299 @@ @if (_selectedItem is not null) { - -
-
- - - - Dynamic - @if (!_schedule.ShuffleScheduleItems) - { - Fixed - } - - - - Collection - Television Show - Television Season - Artist - Multi Collection - Smart Collection - Playlist - - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Collection) - { - - - - Only the first 10 items are shown - - - - } - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.MultiCollection) - { - - - - Only the first 10 items are shown - - - - } - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.SmartCollection) - { - - - - Only the first 10 items are shown - - - - } - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionShow) - { - - - - Only the first 10 items are shown - - - - } - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionSeason) - { - - - - Only the first 20 items are shown - - - - } - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Artist) + +
+
+ + + + Dynamic + @if (!_schedule.ShuffleScheduleItems) + { + Fixed + } + + + + Collection + Television Show + Television Season + Artist + Multi Collection + Smart Collection + Playlist + + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Collection) + { + + + + Only the first 10 items are shown + + + + } + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.MultiCollection) + { + + + + Only the first 10 items are shown + + + + } + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.SmartCollection) + { + + + + Only the first 10 items are shown + + + + } + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionShow) + { + + + + Only the first 10 items are shown + + + + } + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionSeason) + { + + + + Only the first 20 items are shown + + + + } + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Artist) + { + + + + Only the first 10 items are shown + + + + } + @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Playlist) + { + + @foreach (PlaylistGroupViewModel playlistGroup in _playlistGroups) { - - - - Only the first 10 items are shown - - - + @playlistGroup.Name } - @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Playlist) + + + @foreach (PlaylistViewModel playlist in _playlists) { - - @foreach (PlaylistGroupViewModel playlistGroup in _playlistGroups) - { - @playlistGroup.Name - } - - - @foreach (PlaylistViewModel playlist in _playlists) - { - @playlist.Name - } - - + @playlist.Name } - - @switch (_selectedItem.CollectionType) - { - case ProgramScheduleItemCollectionType.MultiCollection: - Shuffle - Shuffle In Order - break; - case ProgramScheduleItemCollectionType.Collection: - case ProgramScheduleItemCollectionType.SmartCollection: - Chronological - Random - Shuffle - Shuffle In Order - break; - case ProgramScheduleItemCollectionType.TelevisionShow: - Chronological - Season, Episode - Random - Shuffle - Multi-Episode Shuffle - break; - case ProgramScheduleItemCollectionType.Playlist: - break; - default: - Chronological - Random - Shuffle - break; - } - - - @if (!_schedule.ShuffleScheduleItems) - { - Flood - } - One - Multiple - Duration - - - - - - - - - - - - (none) - Ordered Groups - Shuffled Groups - - - (none) - Offline - Filler - - - - - Normal - Filler - - - -
-
- - - - @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PreRoll)) - { - @filler.Name - } - - - @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.MidRoll)) - { - @filler.Name - } - - - @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PostRoll)) - { - @filler.Name - } - - - @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Tail)) - { - @filler.Name - } - - - @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Fallback)) - { - @filler.Name - } - - - - - - - @foreach (WatermarkViewModel watermark in _watermarks) - { - @watermark.Name - } - - - (none) - @foreach (LanguageCodeViewModel culture in _availableCultures) - { - @culture.EnglishName - } - - - - (none) - @foreach (LanguageCodeViewModel culture in _availableCultures) - { - @culture.EnglishName - } - - - None - Forced - Default - Any - - - -
-
+ + } + + @switch (_selectedItem.CollectionType) + { + case ProgramScheduleItemCollectionType.MultiCollection: + Shuffle + Shuffle In Order + break; + case ProgramScheduleItemCollectionType.Collection: + case ProgramScheduleItemCollectionType.SmartCollection: + Chronological + Random + Shuffle + Shuffle In Order + break; + case ProgramScheduleItemCollectionType.TelevisionShow: + Chronological + Season, Episode + Random + Shuffle + Multi-Episode Shuffle + break; + case ProgramScheduleItemCollectionType.Playlist: + break; + default: + Chronological + Random + Shuffle + break; + } + + + @if (!_schedule.ShuffleScheduleItems) + { + Flood + } + One + Multiple + Duration + + + + + + + + + + + + (none) + Ordered Groups + Shuffled Groups + + + (none) + Offline + Filler + + + + + Normal + Filler + +
+
+
+
+ + + + @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PreRoll)) + { + @filler.Name + } + + + @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.MidRoll)) + { + @filler.Name + } + + + @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PostRoll)) + { + @filler.Name + } + + + @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Tail)) + { + @filler.Name + } + + + @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Fallback)) + { + @filler.Name + } + + + + + + + @foreach (WatermarkViewModel watermark in _watermarks) + { + @watermark.Name + } + + + (none) + @foreach (LanguageCodeViewModel culture in _availableCultures) + { + @culture.EnglishName + } + + + + (none) + @foreach (LanguageCodeViewModel culture in _availableCultures) + { + @culture.EnglishName + } + + + None + Forced + Default + Any + + + +
+
} @@ -657,4 +656,5 @@ } } } + } \ No newline at end of file diff --git a/ErsatzTV/Pages/Schedules.razor b/ErsatzTV/Pages/Schedules.razor index c99ff9976..119f335f5 100644 --- a/ErsatzTV/Pages/Schedules.razor +++ b/ErsatzTV/Pages/Schedules.razor @@ -1,6 +1,6 @@ @page "/schedules" -@using ErsatzTV.Application.ProgramSchedules @using ErsatzTV.Application.Configuration +@using ErsatzTV.Application.ProgramSchedules @using NaturalSort.Extension @implements IDisposable @inject IDialogService Dialog diff --git a/ErsatzTV/Pages/Search.razor b/ErsatzTV/Pages/Search.razor index 3279eeeee..10e26e7a9 100644 --- a/ErsatzTV/Pages/Search.razor +++ b/ErsatzTV/Pages/Search.razor @@ -1,12 +1,11 @@ @page "/search" @inherits MultiSelectBase -@inject NavigationManager _navigationManager -@inject ChannelWriter _channel +@inject NavigationManager NavigationManager @inject PersistentComponentState ApplicationState -@using ErsatzTV.Extensions @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Search +@using ErsatzTV.Extensions @implements IDisposable @@ -42,47 +41,47 @@ @_query if (_movies?.Count > 0) { - @_movies.Count Movies + @_movies.Count Movies } if (_shows?.Count > 0) { - @_shows.Count Shows + @_shows.Count Shows } if (_seasons?.Count > 0) { - @_seasons.Count Seasons + @_seasons.Count Seasons } if (_episodes?.Count > 0) { - @_episodes.Count Episodes + @_episodes.Count Episodes } if (_artists?.Count > 0) { - @_artists.Count Artists + @_artists.Count Artists } if (_musicVideos?.Count > 0) { - @_musicVideos.Count Music Videos + @_musicVideos.Count Music Videos } if (_otherVideos?.Count > 0) { - @_otherVideos.Count Other Videos + @_otherVideos.Count Other Videos } if (_songs?.Count > 0) { - @_songs.Count Songs + @_songs.Count Songs } if (_images?.Count > 0) { - @_images.Count Images + @_images.Count Images }
@@ -95,7 +94,7 @@ - -@inject NavigationManager _navigationManager -@inject ChannelWriter _channel +@inject NavigationManager NavigationManager
@@ -93,7 +92,7 @@ PageNumber = 1; } - _query = _navigationManager.Uri.GetSearchQuery(); + _query = NavigationManager.Uri.GetSearchQuery(); await RefreshData(); } @@ -113,7 +112,7 @@ uri = $"{uri}?{key}={value}"; } - _navigationManager.NavigateTo(uri); + NavigationManager.NavigateTo(uri); } private void NextPage() @@ -125,7 +124,7 @@ uri = $"{uri}?{key}={value}"; } - _navigationManager.NavigateTo(uri); + NavigationManager.NavigateTo(uri); } private void SelectClicked(MediaCardViewModel card, MouseEventArgs e) diff --git a/ErsatzTV/Pages/TelevisionEpisodeList.razor b/ErsatzTV/Pages/TelevisionEpisodeList.razor index a75529d0b..f82803320 100644 --- a/ErsatzTV/Pages/TelevisionEpisodeList.razor +++ b/ErsatzTV/Pages/TelevisionEpisodeList.razor @@ -1,17 +1,17 @@ @page "/media/tv/seasons/{SeasonId:int}" -@using ErsatzTV.Extensions -@using ErsatzTV.Application.Television @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaItems @using ErsatzTV.Application.ProgramSchedules +@using ErsatzTV.Application.Television +@using ErsatzTV.Extensions @implements IDisposable -@inject IMediator _mediator -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject IDialogService _dialog -@inject NavigationManager _navigationManager -@inject IJSRuntime _jsRuntime +@inject IMediator Mediator +@inject ILogger Logger +@inject ISnackbar Snackbar +@inject IDialogService Dialog +@inject NavigationManager NavigationManager +@inject IJSRuntime JsRuntime
@@ -213,7 +213,7 @@ { try { - await _navigationManager.NavigateToFragmentAsync(_jsRuntime); + await NavigationManager.NavigateToFragmentAsync(JsRuntime); } catch (Exception) { @@ -226,10 +226,10 @@ private async Task RefreshData() { - await _mediator.Send(new GetTelevisionSeasonById(SeasonId), _cts.Token) + 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() @@ -237,26 +237,26 @@ var parameters = new DialogParameters { { "EntityType", "season" }, { "EntityName", $"{_season.Title} - {_season.Name}" } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Collection", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is MediaCollectionViewModel collection) { - await _mediator.Send(new AddSeasonToCollection(collection.Id, SeasonId), _cts.Token); - _navigationManager.NavigateTo($"media/collections/{collection.Id}"); + await Mediator.Send(new AddSeasonToCollection(collection.Id, SeasonId), _cts.Token); + NavigationManager.NavigateTo($"media/collections/{collection.Id}"); } } - + private async Task AddToPlaylist() { var parameters = new DialogParameters { { "EntityType", "season" }, { "EntityName", $"{_season.Title} - {_season.Name}" } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Playlist", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Playlist", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is PlaylistViewModel playlist) { - await _mediator.Send(new AddSeasonToPlaylist(playlist.Id, SeasonId), _cts.Token); - _navigationManager.NavigateTo($"media/playlists/{playlist.Id}"); + await Mediator.Send(new AddSeasonToPlaylist(playlist.Id, SeasonId), _cts.Token); + NavigationManager.NavigateTo($"media/playlists/{playlist.Id}"); } } @@ -265,12 +265,12 @@ var parameters = new DialogParameters { { "EntityType", "season" }, { "EntityName", $"{_season.Title} - {_season.Name}" } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Schedule", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Schedule", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is ProgramScheduleViewModel schedule) { - await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, 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"); + await Mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, 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"); } } @@ -279,58 +279,58 @@ var parameters = new DialogParameters { { "EntityType", "episode" }, { "EntityName", episode.Title } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Collection", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is MediaCollectionViewModel collection) { var request = new AddEpisodeToCollection(collection.Id, episode.EpisodeId); - Either addResult = await _mediator.Send(request, _cts.Token); + Either addResult = await Mediator.Send(request, _cts.Token); 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); + 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: _ => Snackbar.Add($"Added {episode.Title} to collection {collection.Name}", Severity.Success)); } } - + private async Task AddEpisodeToPlaylist(TelevisionEpisodeCardViewModel episode) { var parameters = new DialogParameters { { "EntityType", "episode" }, { "EntityName", episode.Title } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Playlist", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Playlist", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is PlaylistViewModel playlist) { var request = new AddEpisodeToPlaylist(playlist.Id, episode.EpisodeId); - Either addResult = await _mediator.Send(request, _cts.Token); + Either addResult = await Mediator.Send(request, _cts.Token); addResult.Match( Left: error => { - _snackbar.Add($"Unexpected error adding episode to playlist: {error.Value}"); - _logger.LogError("Unexpected error adding episode to playlist: {Error}", error.Value); + Snackbar.Add($"Unexpected error adding episode to playlist: {error.Value}"); + Logger.LogError("Unexpected error adding episode to playlist: {Error}", error.Value); }, - Right: _ => _snackbar.Add($"Added {episode.Title} to playlist {playlist.Name}", Severity.Success)); + Right: _ => Snackbar.Add($"Added {episode.Title} to playlist {playlist.Name}", Severity.Success)); } } private async Task ShowInfo(TelevisionEpisodeCardViewModel episode) { - Either maybeInfo = await _mediator.Send(new GetMediaItemInfo(episode.EpisodeId)); + Either maybeInfo = await Mediator.Send(new GetMediaItemInfo(episode.EpisodeId)); foreach (BaseError error in maybeInfo.LeftToSeq()) { - _snackbar.Add("Unexpected error loading media info"); - _logger.LogError("Unexpected error loading media info: {Error}", error.Value); + 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( + IDialogReference dialog = await Dialog.ShowAsync( $"{episode.ShowTitle} - s{episode.Season:00}e{episode.Episode:00} - {episode.Title}", parameters, options); diff --git a/ErsatzTV/Pages/TelevisionSeasonList.razor b/ErsatzTV/Pages/TelevisionSeasonList.razor index 5d44426b6..ce591fb54 100644 --- a/ErsatzTV/Pages/TelevisionSeasonList.razor +++ b/ErsatzTV/Pages/TelevisionSeasonList.razor @@ -1,17 +1,16 @@ @page "/media/tv/shows/{ShowId:int}" -@using ErsatzTV.Extensions -@using ErsatzTV.Application.Television @using System.Globalization @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.ProgramSchedules +@using ErsatzTV.Application.Television +@using ErsatzTV.Extensions @implements IDisposable -@inject IMediator _mediator -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject IDialogService _dialog -@inject NavigationManager _navigationManager -@inject ChannelWriter _channel +@inject IMediator Mediator +@inject ILogger Logger +@inject ISnackbar Snackbar +@inject IDialogService Dialog +@inject NavigationManager NavigationManager
@@ -198,7 +197,7 @@ private async Task RefreshData() { - await _mediator.Send(new GetTelevisionShowById(ShowId), _cts.Token) + await Mediator.Send(new GetTelevisionShowById(ShowId), _cts.Token) .IfSomeAsync( vm => { @@ -210,7 +209,7 @@ _sortedTags = _show.Tags.OrderBy(t => t).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() @@ -218,12 +217,12 @@ var parameters = new DialogParameters { { "EntityType", "show" }, { "EntityName", _show.Title } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Collection", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is MediaCollectionViewModel collection) { - await _mediator.Send(new AddShowToCollection(collection.Id, ShowId), _cts.Token); - _navigationManager.NavigateTo($"media/collections/{collection.Id}"); + await Mediator.Send(new AddShowToCollection(collection.Id, ShowId), _cts.Token); + NavigationManager.NavigateTo($"media/collections/{collection.Id}"); } } @@ -232,12 +231,12 @@ var parameters = new DialogParameters { { "EntityType", "show" }, { "EntityName", _show.Title } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Playlist", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Playlist", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is PlaylistViewModel playlist) { - await _mediator.Send(new AddShowToPlaylist(playlist.Id, ShowId), _cts.Token); - _navigationManager.NavigateTo($"media/playlists/{playlist.Id}"); + await Mediator.Send(new AddShowToPlaylist(playlist.Id, ShowId), _cts.Token); + NavigationManager.NavigateTo($"media/playlists/{playlist.Id}"); } } @@ -246,12 +245,12 @@ var parameters = new DialogParameters { { "EntityType", "show" }, { "EntityName", _show.Title } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Schedule", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Schedule", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is ProgramScheduleViewModel schedule) { - await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, 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"); + await Mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, 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"); } } @@ -262,19 +261,19 @@ var parameters = new DialogParameters { { "EntityType", "season" }, { "EntityName", season.Title } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Add To Collection", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Add To Collection", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is MediaCollectionViewModel collection) { var request = new AddSeasonToCollection(collection.Id, season.TelevisionSeasonId); - Either addResult = await _mediator.Send(request, _cts.Token); + Either addResult = await Mediator.Send(request, _cts.Token); 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); + 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: _ => Snackbar.Add($"Added {season.Title} to collection {collection.Name}", Severity.Success)); } } } diff --git a/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor b/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor index 3e289ee65..a44b7ba6d 100644 --- a/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor +++ b/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor @@ -1,12 +1,11 @@ @page "/media/tv/seasons" @page "/media/tv/seasons/page/{PageNumber:int}" -@using ErsatzTV.Extensions @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Search +@using ErsatzTV.Extensions @inherits MultiSelectBase -@inject NavigationManager _navigationManager -@inject ChannelWriter _channel +@inject NavigationManager NavigationManager
@@ -85,7 +84,7 @@ PageNumber = 1; } - _query = _navigationManager.Uri.GetSearchQuery(); + _query = NavigationManager.Uri.GetSearchQuery(); await RefreshData(); } @@ -105,7 +104,7 @@ uri = $"{uri}?{key}={value}"; } - _navigationManager.NavigateTo(uri); + NavigationManager.NavigateTo(uri); } private void NextPage() @@ -117,7 +116,7 @@ uri = $"{uri}?{key}={value}"; } - _navigationManager.NavigateTo(uri); + NavigationManager.NavigateTo(uri); } private void SelectClicked(MediaCardViewModel card, MouseEventArgs e) diff --git a/ErsatzTV/Pages/TelevisionShowList.razor b/ErsatzTV/Pages/TelevisionShowList.razor index 1e54e40b2..87560d177 100644 --- a/ErsatzTV/Pages/TelevisionShowList.razor +++ b/ErsatzTV/Pages/TelevisionShowList.razor @@ -3,10 +3,10 @@ @inherits MultiSelectBase @inject NavigationManager NavigationManager @inject PersistentComponentState ApplicationState -@using ErsatzTV.Extensions @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Search +@using ErsatzTV.Extensions @implements IDisposable diff --git a/ErsatzTV/Pages/TemplateEditor.razor b/ErsatzTV/Pages/TemplateEditor.razor index f46152b16..70ac50067 100644 --- a/ErsatzTV/Pages/TemplateEditor.razor +++ b/ErsatzTV/Pages/TemplateEditor.razor @@ -1,6 +1,6 @@ @page "/templates/{Id:int}" -@using ErsatzTV.Application.Scheduling @using System.Globalization +@using ErsatzTV.Application.Scheduling @implements IDisposable @inject NavigationManager NavigationManager @inject ILogger Logger diff --git a/ErsatzTV/Pages/Templates.razor b/ErsatzTV/Pages/Templates.razor index 16a4e8d8e..82385482e 100644 --- a/ErsatzTV/Pages/Templates.razor +++ b/ErsatzTV/Pages/Templates.razor @@ -1,6 +1,6 @@ @page "/templates" -@using S = System.Collections.Generic @using ErsatzTV.Application.Scheduling +@using S = System.Collections.Generic @implements IDisposable @inject ILogger Logger @inject ISnackbar Snackbar diff --git a/ErsatzTV/Pages/TraktLists.razor b/ErsatzTV/Pages/TraktLists.razor index 8e8f2a167..4c8e1a7ef 100644 --- a/ErsatzTV/Pages/TraktLists.razor +++ b/ErsatzTV/Pages/TraktLists.razor @@ -1,19 +1,17 @@ @page "/media/trakt/lists" -@using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Configuration +@using ErsatzTV.Application.MediaCollections @implements IDisposable -@inject IDialogService _dialog -@inject IMediator _mediator -@inject ISnackbar _snackbar -@inject ILogger _logger -@inject IEntityLocker _locker -@inject ChannelWriter _workerChannel +@inject IDialogService Dialog +@inject IMediator Mediator +@inject IEntityLocker Locker +@inject ChannelWriter WorkerChannel
Add Trakt List @@ -47,19 +45,19 @@
@@ -85,9 +83,9 @@ _cts.Dispose(); } - protected override void OnInitialized() => _locker.OnTraktChanged += LockChanged; + protected override void OnInitialized() => Locker.OnTraktChanged += LockChanged; - protected override async Task OnParametersSetAsync() => _traktListsRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.TraktListsPageSize), _cts.Token) + protected override async Task OnParametersSetAsync() => _traktListsRowsPerPage = await Mediator.Send(new GetConfigElementByKey(ConfigElementKey.TraktListsPageSize), _cts.Token) .Map(maybeRows => maybeRows.Match(ce => int.TryParse(ce.Value, out int rows) ? rows : 10, () => 10)); private void LockChanged(object sender, EventArgs e) => @@ -95,7 +93,7 @@ async () => { StateHasChanged(); - if (_traktListsTable != null && !_locker.IsTraktLocked()) + if (_traktListsTable != null && !Locker.IsTraktLocked()) { await _traktListsTable.ReloadServerData(); } @@ -103,28 +101,28 @@ private async Task MatchListItems(TraktListViewModel traktList) { - if (_locker.LockTrakt()) + if (Locker.LockTrakt()) { - await _workerChannel.WriteAsync(new MatchTraktListItems(traktList.Id), _cts.Token); + await WorkerChannel.WriteAsync(new MatchTraktListItems(traktList.Id), _cts.Token); } } private async Task DeleteTraktList(TraktListViewModel traktList) { - if (_locker.LockTrakt()) + if (Locker.LockTrakt()) { var parameters = new DialogParameters { { "EntityType", "Trakt List" }, { "EntityName", traktList.Name } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Delete Trakt List", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Delete Trakt List", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled) { - await _workerChannel.WriteAsync(new DeleteTraktList(traktList.Id), _cts.Token); + await WorkerChannel.WriteAsync(new DeleteTraktList(traktList.Id), _cts.Token); } else { - _locker.UnlockTrakt(); + Locker.UnlockTrakt(); } } } @@ -133,9 +131,9 @@ { try { - await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.TraktListsPageSize, state.PageSize.ToString()), _cts.Token); + await Mediator.Send(new SaveConfigElementByKey(ConfigElementKey.TraktListsPageSize, state.PageSize.ToString()), _cts.Token); - PagedTraktListsViewModel data = await _mediator.Send(new GetPagedTraktLists(state.Page, state.PageSize), _cts.Token); + PagedTraktListsViewModel data = await Mediator.Send(new GetPagedTraktLists(state.Page, state.PageSize), _cts.Token); return new TableData { TotalItems = data.TotalCount, Items = data.Page }; } catch (Exception) @@ -150,18 +148,18 @@ private async Task AddTraktList() { - if (_locker.LockTrakt()) + if (Locker.LockTrakt()) { var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small }; - IDialogReference dialog = await _dialog.ShowAsync("Add Trakt List", options); + IDialogReference dialog = await Dialog.ShowAsync("Add Trakt List", options); DialogResult result = await dialog.Result; if (!result.Canceled && result.Data is string url) { - await _workerChannel.WriteAsync(new AddTraktList(url), _cts.Token); + await WorkerChannel.WriteAsync(new AddTraktList(url), _cts.Token); } else { - _locker.UnlockTrakt(); + Locker.UnlockTrakt(); } } } diff --git a/ErsatzTV/Pages/Trash.razor b/ErsatzTV/Pages/Trash.razor index f5e452f85..61fd7f520 100644 --- a/ErsatzTV/Pages/Trash.razor +++ b/ErsatzTV/Pages/Trash.razor @@ -1,10 +1,10 @@ @page "/media/trash" -@using ErsatzTV.Extensions +@using ErsatzTV.Application.Maintenance @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.Search -@using ErsatzTV.Application.Maintenance +@using ErsatzTV.Extensions @inherits MultiSelectBase -@inject NavigationManager _navigationManager +@inject NavigationManager NavigationManager
@@ -31,47 +31,47 @@ { if (_movies?.Count > 0) { - @_movies.Count Movies + @_movies.Count Movies } if (_shows?.Count > 0) { - @_shows.Count Shows + @_shows.Count Shows } if (_seasons?.Count > 0) { - @_seasons.Count Seasons + @_seasons.Count Seasons } if (_episodes?.Count > 0) { - @_episodes.Count Episodes + @_episodes.Count Episodes } if (_artists?.Count > 0) { - @_artists.Count Artists + @_artists.Count Artists } if (_musicVideos?.Count > 0) { - @_musicVideos.Count Music Videos + @_musicVideos.Count Music Videos } if (_otherVideos?.Count > 0) { - @_otherVideos.Count Other Videos + @_otherVideos.Count Other Videos } if (_songs?.Count > 0) { - @_songs.Count Songs + @_songs.Count Songs } if (_images?.Count > 0) { - @_images.Count Images + @_images.Count Images } if (IsNotEmpty) diff --git a/ErsatzTV/Pages/Troubleshooting.razor b/ErsatzTV/Pages/Troubleshooting.razor index ed49a922e..895fb1503 100644 --- a/ErsatzTV/Pages/Troubleshooting.razor +++ b/ErsatzTV/Pages/Troubleshooting.razor @@ -1,8 +1,8 @@ @page "/system/troubleshooting" -@using ErsatzTV.Application.Troubleshooting -@using ErsatzTV.Application.Troubleshooting.Queries @using System.Text.Json @using System.Text.Json.Serialization +@using ErsatzTV.Application.Troubleshooting +@using ErsatzTV.Application.Troubleshooting.Queries @implements IDisposable @inject IMediator Mediator @inject IJSRuntime JsRuntime diff --git a/ErsatzTV/Pages/WatermarkEditor.razor b/ErsatzTV/Pages/WatermarkEditor.razor index 68a3c1102..a126b98f3 100644 --- a/ErsatzTV/Pages/WatermarkEditor.razor +++ b/ErsatzTV/Pages/WatermarkEditor.razor @@ -1,8 +1,8 @@ @page "/watermarks/{Id:int}" @page "/watermarks/add" +@using ErsatzTV.Application.Images @using ErsatzTV.Application.Watermarks @using ErsatzTV.FFmpeg.State -@using ErsatzTV.Application.Images @implements IDisposable @inject NavigationManager NavigationManager @inject ILogger Logger diff --git a/ErsatzTV/Pages/Watermarks.razor b/ErsatzTV/Pages/Watermarks.razor index 98b96412e..8e2784d7a 100644 --- a/ErsatzTV/Pages/Watermarks.razor +++ b/ErsatzTV/Pages/Watermarks.razor @@ -1,11 +1,9 @@ @page "/watermarks" @using ErsatzTV.Application.Watermarks @implements IDisposable -@inject IDialogService _dialog -@inject IMediator _mediator -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject NavigationManager _navigationManager +@inject IDialogService Dialog +@inject IMediator Mediator +@inject NavigationManager NavigationManager @@ -84,18 +82,18 @@ protected override async Task OnParametersSetAsync() => await LoadWatermarksAsync(); private async Task LoadWatermarksAsync() => - _watermarks = await _mediator.Send(new GetAllWatermarks(), _cts.Token); + _watermarks = await Mediator.Send(new GetAllWatermarks(), _cts.Token); private async Task DeleteWatermarkAsync(WatermarkViewModel watermark) { var parameters = new DialogParameters { { "EntityType", "watermark" }, { "EntityName", watermark.Name } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Delete Watermark", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Delete Watermark", parameters, options); DialogResult result = await dialog.Result; if (!result.Canceled) { - await _mediator.Send(new DeleteWatermark(watermark.Id), _cts.Token); + await Mediator.Send(new DeleteWatermark(watermark.Id), _cts.Token); await LoadWatermarksAsync(); } } @@ -105,11 +103,11 @@ var parameters = new DialogParameters { { "WatermarkId", watermark.Id } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; - IDialogReference dialog = await _dialog.ShowAsync("Copy Watermark", parameters, options); + IDialogReference dialog = await Dialog.ShowAsync("Copy Watermark", parameters, options); DialogResult dialogResult = await dialog.Result; if (!dialogResult.Canceled && dialogResult.Data is WatermarkViewModel data) { - _navigationManager.NavigateTo($"/watermarks/{data.Id}"); + NavigationManager.NavigateTo($"/watermarks/{data.Id}"); } } diff --git a/ErsatzTV/Shared/AddToCollectionDialog.razor b/ErsatzTV/Shared/AddToCollectionDialog.razor index 15ed4315b..a020946db 100644 --- a/ErsatzTV/Shared/AddToCollectionDialog.razor +++ b/ErsatzTV/Shared/AddToCollectionDialog.razor @@ -1,10 +1,10 @@ -@using Microsoft.Extensions.Caching.Memory -@using ErsatzTV.Application.MediaCollections +@using ErsatzTV.Application.MediaCollections +@using Microsoft.Extensions.Caching.Memory @implements IDisposable -@inject IMediator _mediator -@inject IMemoryCache _memoryCache -@inject ISnackbar _snackbar -@inject ILogger _logger +@inject IMediator Mediator +@inject IMemoryCache MemoryCache +@inject ISnackbar Snackbar +@inject ILogger Logger @@ -83,10 +83,10 @@ protected override async Task OnParametersSetAsync() { - _collections = await _mediator.Send(new GetAllCollections(), _cts.Token) + _collections = await Mediator.Send(new GetAllCollections(), _cts.Token) .Map(list => new[] { _newCollection }.Append(list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase)).ToList()); - if (_memoryCache.TryGetValue("AddToCollectionDialog.SelectedCollectionId", out int id)) + if (MemoryCache.TryGetValue("AddToCollectionDialog.SelectedCollectionId", out int id)) { _selectedCollection = _collections.SingleOrDefault(c => c.Id == id) ?? _newCollection; } @@ -108,24 +108,24 @@ if (_selectedCollection == _newCollection) { Either maybeResult = - await _mediator.Send(new CreateCollection(_newCollectionName), _cts.Token); + await Mediator.Send(new CreateCollection(_newCollectionName), _cts.Token); maybeResult.Match( collection => { - _memoryCache.Set("AddToCollectionDialog.SelectedCollectionId", collection.Id); + MemoryCache.Set("AddToCollectionDialog.SelectedCollectionId", collection.Id); MudDialog.Close(DialogResult.Ok(collection)); }, error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Error creating new collection: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Error creating new collection: {Error}", error.Value); MudDialog.Close(DialogResult.Cancel()); }); } else { - _memoryCache.Set("AddToCollectionDialog.SelectedCollectionId", _selectedCollection.Id); + MemoryCache.Set("AddToCollectionDialog.SelectedCollectionId", _selectedCollection.Id); MudDialog.Close(DialogResult.Ok(_selectedCollection)); } } diff --git a/ErsatzTV/Shared/AddToPlaylistDialog.razor b/ErsatzTV/Shared/AddToPlaylistDialog.razor index d56088941..12085f26e 100644 --- a/ErsatzTV/Shared/AddToPlaylistDialog.razor +++ b/ErsatzTV/Shared/AddToPlaylistDialog.razor @@ -1,5 +1,5 @@ -@using Microsoft.Extensions.Caching.Memory -@using ErsatzTV.Application.MediaCollections +@using ErsatzTV.Application.MediaCollections +@using Microsoft.Extensions.Caching.Memory @implements IDisposable @inject IMediator Mediator @inject IMemoryCache MemoryCache @@ -98,7 +98,7 @@ } private string FormatText() => $"Select the playlist to add the {EntityType} {EntityName}"; - + private async Task UpdatePlaylistGroupItems(PlaylistGroupViewModel playlistGroup) { _selectedPlaylistGroup = playlistGroup; diff --git a/ErsatzTV/Shared/AddToScheduleDialog.razor b/ErsatzTV/Shared/AddToScheduleDialog.razor index e58f21dd0..c6a852abb 100644 --- a/ErsatzTV/Shared/AddToScheduleDialog.razor +++ b/ErsatzTV/Shared/AddToScheduleDialog.razor @@ -1,7 +1,7 @@ @using ErsatzTV.Application.ProgramSchedules @using NaturalSort.Extension @implements IDisposable -@inject IMediator _mediator +@inject IMediator Mediator
@@ -57,7 +57,7 @@ } protected override async Task OnParametersSetAsync() => - _schedules = await _mediator.Send(new GetAllProgramSchedules(), _cts.Token) + _schedules = await Mediator.Send(new GetAllProgramSchedules(), _cts.Token) .Map(list => list.OrderBy(vm => vm.Name, new NaturalSortComparer(StringComparison.CurrentCultureIgnoreCase)).ToList()); private string FormatText() => $"Select the schedule to add the {EntityType} {EntityName}"; diff --git a/ErsatzTV/Shared/AddTraktListDialog.razor b/ErsatzTV/Shared/AddTraktListDialog.razor index 10a277282..c99bf1a07 100644 --- a/ErsatzTV/Shared/AddTraktListDialog.razor +++ b/ErsatzTV/Shared/AddTraktListDialog.razor @@ -1,10 +1,4 @@ -@using Microsoft.Extensions.Caching.Memory -@inject IMediator _mediator -@inject IMemoryCache _memoryCache -@inject ISnackbar _snackbar -@inject ILogger _logger - - + diff --git a/ErsatzTV/Shared/CopyFFmpegProfileDialog.razor b/ErsatzTV/Shared/CopyFFmpegProfileDialog.razor index 73616f562..268b7a11d 100644 --- a/ErsatzTV/Shared/CopyFFmpegProfileDialog.razor +++ b/ErsatzTV/Shared/CopyFFmpegProfileDialog.razor @@ -1,8 +1,8 @@ @using ErsatzTV.Application.FFmpegProfiles @implements IDisposable -@inject IMediator _mediator -@inject ISnackbar _snackbar -@inject ILogger _logger +@inject IMediator Mediator +@inject ISnackbar Snackbar +@inject ILogger Logger @@ -57,14 +57,14 @@ } Either maybeResult = - await _mediator.Send(new CopyFFmpegProfile(FFmpegProfileId, _newFFmpegProfileName), _cts.Token); + await Mediator.Send(new CopyFFmpegProfile(FFmpegProfileId, _newFFmpegProfileName), _cts.Token); maybeResult.Match( ffmpegProfile => { MudDialog.Close(DialogResult.Ok(ffmpegProfile)); }, error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Error copying FFmpeg Profile: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Error copying FFmpeg Profile: {Error}", error.Value); MudDialog.Close(DialogResult.Cancel()); }); } diff --git a/ErsatzTV/Shared/CopyWatermarkDialog.razor b/ErsatzTV/Shared/CopyWatermarkDialog.razor index d61096f86..9649a4a25 100644 --- a/ErsatzTV/Shared/CopyWatermarkDialog.razor +++ b/ErsatzTV/Shared/CopyWatermarkDialog.razor @@ -1,8 +1,8 @@ @using ErsatzTV.Application.Watermarks @implements IDisposable -@inject IMediator _mediator -@inject ISnackbar _snackbar -@inject ILogger _logger +@inject IMediator Mediator +@inject ISnackbar Snackbar +@inject ILogger Logger @@ -57,14 +57,14 @@ } Either maybeResult = - await _mediator.Send(new CopyWatermark(WatermarkId, _newWatermarkName), _cts.Token); + await Mediator.Send(new CopyWatermark(WatermarkId, _newWatermarkName), _cts.Token); maybeResult.Match( watermark => { MudDialog.Close(DialogResult.Ok(watermark)); }, error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Error copying Watermark: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Error copying Watermark: {Error}", error.Value); MudDialog.Close(DialogResult.Cancel()); }); } diff --git a/ErsatzTV/Shared/DeleteFromDatabaseDialog.razor b/ErsatzTV/Shared/DeleteFromDatabaseDialog.razor index e8252ce7a..be94595d7 100644 --- a/ErsatzTV/Shared/DeleteFromDatabaseDialog.razor +++ b/ErsatzTV/Shared/DeleteFromDatabaseDialog.razor @@ -1,6 +1,4 @@ -@inject IMediator _mediator - -
+
diff --git a/ErsatzTV/Shared/LetterBar.razor b/ErsatzTV/Shared/LetterBar.razor index 7637a4dcb..13ded7826 100644 --- a/ErsatzTV/Shared/LetterBar.razor +++ b/ErsatzTV/Shared/LetterBar.razor @@ -1,5 +1,5 @@ -@using ErsatzTV.Extensions -@using ErsatzTV.Core.Search +@using ErsatzTV.Core.Search +@using ErsatzTV.Extensions
# diff --git a/ErsatzTV/Shared/MainLayout.razor b/ErsatzTV/Shared/MainLayout.razor index 111656cb9..0beb12db6 100644 --- a/ErsatzTV/Shared/MainLayout.razor +++ b/ErsatzTV/Shared/MainLayout.razor @@ -1,8 +1,8 @@ @inherits LayoutComponentBase @using System.Reflection -@using ErsatzTV.Extensions @using ErsatzTV.Application.Search @using ErsatzTV.Core.Interfaces.Search +@using ErsatzTV.Extensions @implements IDisposable @inject NavigationManager NavigationManager @inject IMediator Mediator diff --git a/ErsatzTV/Shared/MediaCard.razor b/ErsatzTV/Shared/MediaCard.razor index ec943012a..5432f42b0 100644 --- a/ErsatzTV/Shared/MediaCard.razor +++ b/ErsatzTV/Shared/MediaCard.razor @@ -1,5 +1,5 @@ -@using static Prelude -@using ErsatzTV.Application.MediaCards +@using ErsatzTV.Application.MediaCards +@using static Prelude @inject IMediator Mediator
diff --git a/ErsatzTV/Shared/MediaItemInfoDialog.razor b/ErsatzTV/Shared/MediaItemInfoDialog.razor index 88f2e913b..9fbbc392c 100644 --- a/ErsatzTV/Shared/MediaItemInfoDialog.razor +++ b/ErsatzTV/Shared/MediaItemInfoDialog.razor @@ -1,6 +1,6 @@ -@using ErsatzTV.Application.MediaItems -@using System.Text.Json +@using System.Text.Json @using System.Text.Json.Serialization +@using ErsatzTV.Application.MediaItems @inject IJSRuntime JsRuntime
diff --git a/ErsatzTV/Shared/MoveLocalLibraryPathDialog.razor b/ErsatzTV/Shared/MoveLocalLibraryPathDialog.razor index 4bb9829e6..5e4e486a2 100644 --- a/ErsatzTV/Shared/MoveLocalLibraryPathDialog.razor +++ b/ErsatzTV/Shared/MoveLocalLibraryPathDialog.razor @@ -1,10 +1,10 @@ -@using Microsoft.Extensions.Caching.Memory -@using ErsatzTV.Application.Libraries +@using ErsatzTV.Application.Libraries +@using Microsoft.Extensions.Caching.Memory @implements IDisposable -@inject IMediator _mediator -@inject IMemoryCache _memoryCache -@inject ISnackbar _snackbar -@inject ILogger _logger +@inject IMediator Mediator +@inject IMemoryCache MemoryCache +@inject ISnackbar Snackbar +@inject ILogger Logger @@ -72,11 +72,11 @@ { _newLibrary = new LocalLibraryViewModel(-1, "(New Library)", MediaKind, -1); - _libraries = await _mediator.Send(new GetAllLocalLibraries(), _cts.Token) + _libraries = await Mediator.Send(new GetAllLocalLibraries(), _cts.Token) .Map(list => list.Filter(ll => ll.MediaKind == MediaKind && ll.Id != SourceLibraryId)) .Map(list => new[] { _newLibrary }.Append(list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase)).ToList()); - if (_memoryCache.TryGetValue("MoveLocalLibraryPathDialog.SelectedLibraryId", out int id)) + if (MemoryCache.TryGetValue("MoveLocalLibraryPathDialog.SelectedLibraryId", out int id)) { _selectedLibrary = _libraries.SingleOrDefault(c => c.Id == id) ?? _newLibrary; } @@ -96,24 +96,24 @@ if (_selectedLibrary == _newLibrary) { Either maybeResult = - await _mediator.Send(new CreateLocalLibrary(_newLibraryName, MediaKind, new List()), _cts.Token); + await Mediator.Send(new CreateLocalLibrary(_newLibraryName, MediaKind, new List()), _cts.Token); maybeResult.Match( collection => { - _memoryCache.Set("MoveLocalLibraryPathDialog.SelectedLibraryId", collection.Id); + MemoryCache.Set("MoveLocalLibraryPathDialog.SelectedLibraryId", collection.Id); MudDialog.Close(DialogResult.Ok(collection)); }, error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Error creating new local library: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Error creating new local library: {Error}", error.Value); MudDialog.Close(DialogResult.Cancel()); }); } else { - _memoryCache.Set("MoveLocalLibraryPathDialog.SelectedLibraryId", _selectedLibrary.Id); + MemoryCache.Set("MoveLocalLibraryPathDialog.SelectedLibraryId", _selectedLibrary.Id); MudDialog.Close(DialogResult.Ok(_selectedLibrary)); } } diff --git a/ErsatzTV/Shared/RemoteMediaSourceEditor.razor b/ErsatzTV/Shared/RemoteMediaSourceEditor.razor index 54a6d192e..f92d215d1 100644 --- a/ErsatzTV/Shared/RemoteMediaSourceEditor.razor +++ b/ErsatzTV/Shared/RemoteMediaSourceEditor.razor @@ -1,7 +1,7 @@ -@inject IMediator _mediator -@inject NavigationManager _navigationManager -@inject ISnackbar _snackbar -@inject ILogger _logger +@inject IMediator Mediator +@inject NavigationManager NavigationManager +@inject ISnackbar Snackbar +@inject ILogger Logger @Name Media Source @@ -53,11 +53,11 @@ { Either result = await SaveSecrets(_model); result.Match( - _ => _navigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}"), + _ => NavigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}"), error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Error saving {MediaSource} secrets: {Error}", Name, error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Error saving {MediaSource} secrets: {Error}", Name, error.Value); }); } } diff --git a/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor b/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor index f1b42e1dd..52be2558a 100644 --- a/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor +++ b/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor @@ -1,10 +1,10 @@ @using ErsatzTV.Application.MediaSources @implements IDisposable -@inject IMediator _mediator -@inject NavigationManager _navigationManager -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject IEntityLocker _locker +@inject IMediator Mediator +@inject NavigationManager NavigationManager +@inject ILogger Logger +@inject ISnackbar Snackbar +@inject IEntityLocker Locker @@ -87,7 +87,7 @@ }, () => { - _navigationManager.NavigateTo("404"); + NavigationManager.NavigateTo("404"); return Task.CompletedTask; }); } @@ -95,26 +95,26 @@ private async Task SaveChanges() { IRequest> request = GetUpdateLibraryRequest(_libraries); - Seq errorMessages = await _mediator.Send(request, _cts.Token).Map(e => e.LeftToSeq()); + Seq errorMessages = await Mediator.Send(request, _cts.Token).Map(e => e.LeftToSeq()); await errorMessages.HeadOrNone().Match( error => { - _snackbar.Add($"Unexpected error saving {Name.ToLowerInvariant()} libraries: {error.Value}", Severity.Error); - _logger.LogError("Unexpected error saving {MediaSource} libraries: {Error}", Name, error.Value); + Snackbar.Add($"Unexpected error saving {Name.ToLowerInvariant()} libraries: {error.Value}", Severity.Error); + Logger.LogError("Unexpected error saving {MediaSource} libraries: {Error}", Name, error.Value); return Task.CompletedTask; }, async () => { foreach (int libraryId in _libraries.Filter(l => l.ShouldSyncItems).Map(l => l.Id)) { - if (_locker.LockLibrary(libraryId)) + if (Locker.LockLibrary(libraryId)) { await SynchronizeLibraryByIdIfNeeded(new SynchronizeParameters(libraryId, Id)); } } - _navigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}"); + NavigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}"); }); } diff --git a/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor b/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor index cc11d0d9d..aacb43636 100644 --- a/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor +++ b/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor @@ -1,9 +1,9 @@ @using ErsatzTV.Application.MediaSources @implements IDisposable -@inject NavigationManager _navigationManager -@inject ILogger _logger -@inject ISnackbar _snackbar -@inject IMediator _mediator +@inject NavigationManager NavigationManager +@inject ILogger Logger +@inject ISnackbar Snackbar +@inject IMediator Mediator @@ -110,7 +110,7 @@ }, () => { - _navigationManager.NavigateTo("404"); + NavigationManager.NavigateTo("404"); return Task.CompletedTask; }); } @@ -130,16 +130,16 @@ private async Task SaveChanges() { - Seq errorMessages = await _mediator.Send(GetUpdatePathReplacementsRequest(_pathReplacements), _cts.Token) + Seq errorMessages = await Mediator.Send(GetUpdatePathReplacementsRequest(_pathReplacements), _cts.Token) .Map(e => e.LeftToSeq()); errorMessages.HeadOrNone().Match( error => { - _snackbar.Add($"Unexpected error saving path replacements: {error.Value}", Severity.Error); - _logger.LogError("Unexpected error saving path replacements: {Error}", error.Value); + Snackbar.Add($"Unexpected error saving path replacements: {error.Value}", Severity.Error); + Logger.LogError("Unexpected error saving path replacements: {Error}", error.Value); }, - () => _navigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}")); + () => NavigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}")); } } \ No newline at end of file diff --git a/ErsatzTV/Shared/RemoveFromCollectionDialog.razor b/ErsatzTV/Shared/RemoveFromCollectionDialog.razor index 3205621e9..9d0180925 100644 --- a/ErsatzTV/Shared/RemoveFromCollectionDialog.razor +++ b/ErsatzTV/Shared/RemoveFromCollectionDialog.razor @@ -1,6 +1,4 @@ -@inject IMediator _mediator - -
+
diff --git a/ErsatzTV/Shared/SaveAsSmartCollectionDialog.razor b/ErsatzTV/Shared/SaveAsSmartCollectionDialog.razor index f1bba73ef..4973f2b03 100644 --- a/ErsatzTV/Shared/SaveAsSmartCollectionDialog.razor +++ b/ErsatzTV/Shared/SaveAsSmartCollectionDialog.razor @@ -1,10 +1,10 @@ -@using Microsoft.Extensions.Caching.Memory -@using ErsatzTV.Application.MediaCollections +@using ErsatzTV.Application.MediaCollections +@using Microsoft.Extensions.Caching.Memory @implements IDisposable -@inject IMediator _mediator -@inject IMemoryCache _memoryCache -@inject ISnackbar _snackbar -@inject ILogger _logger +@inject IMediator Mediator +@inject IMemoryCache MemoryCache +@inject ISnackbar Snackbar +@inject ILogger Logger @@ -64,10 +64,10 @@ protected override async Task OnParametersSetAsync() { - _collections = await _mediator.Send(new GetAllSmartCollections(), _cts.Token) + _collections = await Mediator.Send(new GetAllSmartCollections(), _cts.Token) .Map(list => new[] { _newCollection }.Append(list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase)).ToList()); - if (_memoryCache.TryGetValue("SaveAsSmartCollectionDialog.SelectedCollectionId", out int id)) + if (MemoryCache.TryGetValue("SaveAsSmartCollectionDialog.SelectedCollectionId", out int id)) { _selectedCollection = _collections.SingleOrDefault(c => c.Id == id) ?? _newCollection; } @@ -87,24 +87,24 @@ if (_selectedCollection == _newCollection) { Either maybeResult = - await _mediator.Send(new CreateSmartCollection(string.Empty, _newCollectionName), _cts.Token); + await Mediator.Send(new CreateSmartCollection(string.Empty, _newCollectionName), _cts.Token); maybeResult.Match( collection => { - _memoryCache.Set("SaveAsSmartCollectionDialog.SelectedCollectionId", collection.Id); + MemoryCache.Set("SaveAsSmartCollectionDialog.SelectedCollectionId", collection.Id); MudDialog.Close(DialogResult.Ok(collection)); }, error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Error creating new collection: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Error creating new collection: {Error}", error.Value); MudDialog.Close(DialogResult.Cancel()); }); } else { - _memoryCache.Set("SaveAsSmartCollectionDialog.SelectedCollectionId", _selectedCollection.Id); + MemoryCache.Set("SaveAsSmartCollectionDialog.SelectedCollectionId", _selectedCollection.Id); MudDialog.Close(DialogResult.Ok(_selectedCollection)); } } diff --git a/ErsatzTV/Shared/SchedulePlayoutReset.razor b/ErsatzTV/Shared/SchedulePlayoutReset.razor index 0bede1ebc..d47667c95 100644 --- a/ErsatzTV/Shared/SchedulePlayoutReset.razor +++ b/ErsatzTV/Shared/SchedulePlayoutReset.razor @@ -1,8 +1,8 @@ @using ErsatzTV.Application.Playouts @implements IDisposable -@inject IMediator _mediator -@inject ISnackbar _snackbar -@inject ILogger _logger +@inject IMediator Mediator +@inject ISnackbar Snackbar +@inject ILogger Logger @@ -68,14 +68,14 @@ private async Task Submit() { Either maybeResult = - await _mediator.Send(new UpdatePlayout(PlayoutId, _resetTime), _cts.Token); + await Mediator.Send(new UpdatePlayout(PlayoutId, _resetTime), _cts.Token); maybeResult.Match( playout => { MudDialog.Close(DialogResult.Ok(playout)); }, error => { - _snackbar.Add(error.Value, Severity.Error); - _logger.LogError("Error updating Playout: {Error}", error.Value); + Snackbar.Add(error.Value, Severity.Error); + Logger.LogError("Error updating Playout: {Error}", error.Value); MudDialog.Close(DialogResult.Cancel()); }); } diff --git a/ErsatzTV/Startup.cs b/ErsatzTV/Startup.cs index b44d10c8f..7f1ce3932 100644 --- a/ErsatzTV/Startup.cs +++ b/ErsatzTV/Startup.cs @@ -329,7 +329,7 @@ public class Startup "https://discord.gg/hHaJm3yGy6"); CopyMacOsConfigFolderIfNeeded(); - + List directoriesToCreate = [ FileSystemLayout.AppDataFolder, @@ -447,11 +447,8 @@ public class Startup .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://api.trakt.tv")); services.Configure(Configuration.GetSection("Trakt")); - - services.AddResponseCompression(options => - { - options.EnableForHttps = true; - }); + + services.AddResponseCompression(options => { options.EnableForHttps = true; }); CustomServices(services); } @@ -520,7 +517,7 @@ public class Startup app.UseStaticFiles(); var extensionProvider = new FileExtensionContentTypeProvider(); - + // fix static file M3U8 mime type extensionProvider.Mappings.Add(".m3u8", "application/vnd.apple.mpegurl"); @@ -733,7 +730,7 @@ public class Startup services.AddSingleton( provider => provider.GetRequiredService>().Writer); } - + private static void CopyMacOsConfigFolderIfNeeded() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) @@ -761,13 +758,13 @@ public class Startup "Migrating config data from {OldFolder} to {NewFolder}", FileSystemLayout.MacOsOldAppDataFolder, FileSystemLayout.AppDataFolder); - + try { // delete new config folder if (Directory.Exists(FileSystemLayout.AppDataFolder)) { - Directory.Delete(FileSystemLayout.AppDataFolder, recursive: true); + Directory.Delete(FileSystemLayout.AppDataFolder, true); } // move old config folder to new config folder diff --git a/ErsatzTV/ViewModels/PlaylistItemEditViewModel.cs b/ErsatzTV/ViewModels/PlaylistItemEditViewModel.cs index 72e433101..617e0df38 100644 --- a/ErsatzTV/ViewModels/PlaylistItemEditViewModel.cs +++ b/ErsatzTV/ViewModels/PlaylistItemEditViewModel.cs @@ -61,7 +61,7 @@ public class PlaylistItemEditViewModel : INotifyPropertyChanged ProgramScheduleItemCollectionType.Image => "Image", _ => string.Empty }; - + public string ItemName => CollectionType switch { ProgramScheduleItemCollectionType.Collection => Collection?.Name, diff --git a/ErsatzTV/ViewModels/PlayoutTemplateEditViewModel.cs b/ErsatzTV/ViewModels/PlayoutTemplateEditViewModel.cs index bc9b0c4e6..c419c5900 100644 --- a/ErsatzTV/ViewModels/PlayoutTemplateEditViewModel.cs +++ b/ErsatzTV/ViewModels/PlayoutTemplateEditViewModel.cs @@ -7,15 +7,17 @@ namespace ErsatzTV.ViewModels; public class PlayoutTemplateEditViewModel { - private int _startMonth; - private int _startDay; - private int _endMonth; private int _endDay; + private int _endMonth; + private int _startDay; + private int _startMonth; public int Id { get; set; } public int Index { get; set; } public TemplateViewModel Template { get; set; } + [CanBeNull] public DecoTemplateViewModel DecoTemplate { get; set; } + public List DaysOfWeek { get; set; } public List DaysOfMonth { get; set; } public List MonthsOfYear { get; set; } @@ -48,7 +50,7 @@ public class PlayoutTemplateEditViewModel public bool AppliesToDate(DateTime date) { // share the PlayoutTemplateSelector logic - + var template = new PlayoutTemplate { DaysOfWeek = DaysOfWeek, @@ -58,7 +60,7 @@ public class PlayoutTemplateEditViewModel StartMonth = StartMonth, StartDay = StartDay, EndMonth = EndMonth, - EndDay = EndDay, + EndDay = EndDay }; TimeSpan offset = TimeZoneInfo.Local.GetUtcOffset(