Browse Source

add option to skip missing items in playouts (#795)

pull/796/head
Jason Dove 3 years ago committed by GitHub
parent
commit
59c793b9be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 5
      ErsatzTV.Application/Configuration/Commands/UpdatePlayoutDaysToBuild.cs
  3. 5
      ErsatzTV.Application/Configuration/Commands/UpdatePlayoutSettings.cs
  4. 21
      ErsatzTV.Application/Configuration/Commands/UpdatePlayoutSettingsHandler.cs
  5. 7
      ErsatzTV.Application/Configuration/PlayoutSettingsViewModel.cs
  6. 3
      ErsatzTV.Application/Configuration/Queries/GetPlayoutDaysToBuild.cs
  7. 16
      ErsatzTV.Application/Configuration/Queries/GetPlayoutDaysToBuildHandler.cs
  8. 3
      ErsatzTV.Application/Configuration/Queries/GetPlayoutSettings.cs
  9. 26
      ErsatzTV.Application/Configuration/Queries/GetPlayoutSettingsHandler.cs
  10. 190
      ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs
  11. 1
      ErsatzTV.Core/Domain/ConfigElementKey.cs
  12. 39
      ErsatzTV.Core/Scheduling/PlayoutBuilder.cs
  13. 19
      ErsatzTV/Pages/Settings.razor

1
CHANGELOG.md

@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Add `metadata_kind` field to search index to allow searching for items with a particular metdata source - Add `metadata_kind` field to search index to allow searching for items with a particular metdata source
- Valid metadata kinds are `fallback`, `sidecar` (NFO), `external` (from a media server) and `embedded` (songs) - Valid metadata kinds are `fallback`, `sidecar` (NFO), `external` (from a media server) and `embedded` (songs)
- Add autocomplete functionality to search bar to quickly navigate to channels, ffmpeg profiles, collections and schedules by name - Add autocomplete functionality to search bar to quickly navigate to channels, ffmpeg profiles, collections and schedules by name
- Add global setting to skip missing (file-not-found or unavailable) items when building playouts
### Changed ### Changed
- Replace invalid (control) characters in NFO metadata with replacement character `<EFBFBD>` before parsing - Replace invalid (control) characters in NFO metadata with replacement character `<EFBFBD>` before parsing

5
ErsatzTV.Application/Configuration/Commands/UpdatePlayoutDaysToBuild.cs

@ -1,5 +0,0 @@
using ErsatzTV.Core;
namespace ErsatzTV.Application.Configuration;
public record UpdatePlayoutDaysToBuild(int DaysToBuild) : IRequest<Either<BaseError, Unit>>;

5
ErsatzTV.Application/Configuration/Commands/UpdatePlayoutSettings.cs

@ -0,0 +1,5 @@
using ErsatzTV.Core;
namespace ErsatzTV.Application.Configuration;
public record UpdatePlayoutSettings(PlayoutSettingsViewModel PlayoutSettings) : IRequest<Either<BaseError, Unit>>;

21
ErsatzTV.Application/Configuration/Commands/UpdatePlayoutDaysToBuildHandler.cs → ErsatzTV.Application/Configuration/Commands/UpdatePlayoutSettingsHandler.cs

@ -9,13 +9,13 @@ using Microsoft.EntityFrameworkCore;
namespace ErsatzTV.Application.Configuration; namespace ErsatzTV.Application.Configuration;
public class UpdatePlayoutDaysToBuildHandler : IRequestHandler<UpdatePlayoutDaysToBuild, Either<BaseError, Unit>> public class UpdatePlayoutSettingsHandler : IRequestHandler<UpdatePlayoutSettings, Either<BaseError, Unit>>
{ {
private readonly IConfigElementRepository _configElementRepository; private readonly IConfigElementRepository _configElementRepository;
private readonly IDbContextFactory<TvContext> _dbContextFactory; private readonly IDbContextFactory<TvContext> _dbContextFactory;
private readonly ChannelWriter<IBackgroundServiceRequest> _workerChannel; private readonly ChannelWriter<IBackgroundServiceRequest> _workerChannel;
public UpdatePlayoutDaysToBuildHandler( public UpdatePlayoutSettingsHandler(
IConfigElementRepository configElementRepository, IConfigElementRepository configElementRepository,
IDbContextFactory<TvContext> dbContextFactory, IDbContextFactory<TvContext> dbContextFactory,
ChannelWriter<IBackgroundServiceRequest> workerChannel) ChannelWriter<IBackgroundServiceRequest> workerChannel)
@ -26,17 +26,20 @@ public class UpdatePlayoutDaysToBuildHandler : IRequestHandler<UpdatePlayoutDays
} }
public async Task<Either<BaseError, Unit>> Handle( public async Task<Either<BaseError, Unit>> Handle(
UpdatePlayoutDaysToBuild request, UpdatePlayoutSettings request,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
await using TvContext dbContext = _dbContextFactory.CreateDbContext(); await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Unit> validation = await Validate(request); Validation<BaseError, Unit> validation = await Validate(request);
return await validation.Apply<Unit, Unit>(_ => ApplyUpdate(dbContext, request.DaysToBuild)); return await validation.Apply<Unit, Unit>(_ => ApplyUpdate(dbContext, request.PlayoutSettings));
} }
private async Task<Unit> ApplyUpdate(TvContext dbContext, int daysToBuild) private async Task<Unit> ApplyUpdate(TvContext dbContext, PlayoutSettingsViewModel playoutSettings)
{ {
await _configElementRepository.Upsert(ConfigElementKey.PlayoutDaysToBuild, daysToBuild); await _configElementRepository.Upsert(ConfigElementKey.PlayoutDaysToBuild, playoutSettings.DaysToBuild);
await _configElementRepository.Upsert(
ConfigElementKey.PlayoutSkipMissingItems,
playoutSettings.SkipMissingItems);
// continue all playouts to proper number of days // continue all playouts to proper number of days
List<Playout> playouts = await dbContext.Playouts List<Playout> playouts = await dbContext.Playouts
@ -50,8 +53,8 @@ public class UpdatePlayoutDaysToBuildHandler : IRequestHandler<UpdatePlayoutDays
return Unit.Default; return Unit.Default;
} }
private static Task<Validation<BaseError, Unit>> Validate(UpdatePlayoutDaysToBuild request) => private static Task<Validation<BaseError, Unit>> Validate(UpdatePlayoutSettings request) =>
Optional(request.DaysToBuild) Optional(request.PlayoutSettings.DaysToBuild)
.Where(days => days > 0) .Where(days => days > 0)
.Map(_ => Unit.Default) .Map(_ => Unit.Default)
.ToValidation<BaseError>("Days to build must be greater than zero") .ToValidation<BaseError>("Days to build must be greater than zero")

7
ErsatzTV.Application/Configuration/PlayoutSettingsViewModel.cs

@ -0,0 +1,7 @@
namespace ErsatzTV.Application.Configuration;
public class PlayoutSettingsViewModel
{
public int DaysToBuild { get; set; }
public bool SkipMissingItems { get; set; }
}

3
ErsatzTV.Application/Configuration/Queries/GetPlayoutDaysToBuild.cs

@ -1,3 +0,0 @@
namespace ErsatzTV.Application.Configuration;
public record GetPlayoutDaysToBuild : IRequest<int>;

16
ErsatzTV.Application/Configuration/Queries/GetPlayoutDaysToBuildHandler.cs

@ -1,16 +0,0 @@
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Repositories;
namespace ErsatzTV.Application.Configuration;
public class GetPlayoutDaysToBuildHandler : IRequestHandler<GetPlayoutDaysToBuild, int>
{
private readonly IConfigElementRepository _configElementRepository;
public GetPlayoutDaysToBuildHandler(IConfigElementRepository configElementRepository) =>
_configElementRepository = configElementRepository;
public Task<int> Handle(GetPlayoutDaysToBuild request, CancellationToken cancellationToken) =>
_configElementRepository.GetValue<int>(ConfigElementKey.PlayoutDaysToBuild)
.Map(result => result.IfNone(2));
}

3
ErsatzTV.Application/Configuration/Queries/GetPlayoutSettings.cs

@ -0,0 +1,3 @@
namespace ErsatzTV.Application.Configuration;
public record GetPlayoutSettings : IRequest<PlayoutSettingsViewModel>;

26
ErsatzTV.Application/Configuration/Queries/GetPlayoutSettingsHandler.cs

@ -0,0 +1,26 @@
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Repositories;
namespace ErsatzTV.Application.Configuration;
public class GetPlayoutSettingsHandler : IRequestHandler<GetPlayoutSettings, PlayoutSettingsViewModel>
{
private readonly IConfigElementRepository _configElementRepository;
public GetPlayoutSettingsHandler(IConfigElementRepository configElementRepository) =>
_configElementRepository = configElementRepository;
public async Task<PlayoutSettingsViewModel> Handle(GetPlayoutSettings request, CancellationToken cancellationToken)
{
Option<int> daysToBuild = await _configElementRepository.GetValue<int>(ConfigElementKey.PlayoutDaysToBuild);
Option<bool> skipMissingItems =
await _configElementRepository.GetValue<bool>(ConfigElementKey.PlayoutSkipMissingItems);
return new PlayoutSettingsViewModel
{
DaysToBuild = await daysToBuild.IfNoneAsync(2),
SkipMissingItems = await skipMissingItems.IfNoneAsync(false)
};
}
}

190
ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs

@ -70,6 +70,180 @@ public class PlayoutBuilderTests
result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6));
} }
[Test]
[Timeout(2000)]
public async Task OnlyFileNotFoundItem_Should_Abort()
{
var mediaItems = new List<MediaItem>
{
TestMovie(1, TimeSpan.FromHours(1), DateTime.Today)
};
mediaItems[0].State = MediaItemState.FileNotFound;
var configRepo = new Mock<IConfigElementRepository>();
configRepo.Setup(
repo => repo.GetValue<bool>(
It.Is<ConfigElementKey>(k => k.Key == ConfigElementKey.PlayoutSkipMissingItems.Key)))
.ReturnsAsync(Some(true));
(PlayoutBuilder builder, Playout playout) =
TestDataFloodForItems(mediaItems, PlaybackOrder.Random, configRepo);
Playout result = await builder.Build(playout, PlayoutBuildMode.Reset);
configRepo.Verify();
result.Items.Should().BeEmpty();
}
[Test]
public async Task FileNotFoundItem_Should_BeSkipped()
{
var mediaItems = new List<MediaItem>
{
TestMovie(1, TimeSpan.FromHours(1), DateTime.Today),
TestMovie(2, TimeSpan.FromHours(6), DateTime.Today)
};
mediaItems[0].State = MediaItemState.FileNotFound;
var configRepo = new Mock<IConfigElementRepository>();
configRepo.Setup(
repo => repo.GetValue<bool>(
It.Is<ConfigElementKey>(k => k.Key == ConfigElementKey.PlayoutSkipMissingItems.Key)))
.ReturnsAsync(Some(true));
(PlayoutBuilder builder, Playout playout) =
TestDataFloodForItems(mediaItems, PlaybackOrder.Random, configRepo);
DateTimeOffset start = HoursAfterMidnight(0);
DateTimeOffset finish = start + TimeSpan.FromHours(6);
Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish);
configRepo.Verify();
result.Items.Count.Should().Be(1);
result.Items.Head().MediaItemId.Should().Be(2);
result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero);
result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6));
}
[Test]
[Timeout(2000)]
public async Task OnlyUnavailableItem_Should_Abort()
{
var mediaItems = new List<MediaItem>
{
TestMovie(1, TimeSpan.FromHours(1), DateTime.Today)
};
mediaItems[0].State = MediaItemState.Unavailable;
var configRepo = new Mock<IConfigElementRepository>();
configRepo.Setup(
repo => repo.GetValue<bool>(
It.Is<ConfigElementKey>(k => k.Key == ConfigElementKey.PlayoutSkipMissingItems.Key)))
.ReturnsAsync(Some(true));
(PlayoutBuilder builder, Playout playout) =
TestDataFloodForItems(mediaItems, PlaybackOrder.Random, configRepo);
Playout result = await builder.Build(playout, PlayoutBuildMode.Reset);
configRepo.Verify();
result.Items.Should().BeEmpty();
}
[Test]
public async Task UnavailableItem_Should_BeSkipped()
{
var mediaItems = new List<MediaItem>
{
TestMovie(1, TimeSpan.FromHours(1), DateTime.Today),
TestMovie(2, TimeSpan.FromHours(6), DateTime.Today)
};
mediaItems[0].State = MediaItemState.Unavailable;
var configRepo = new Mock<IConfigElementRepository>();
configRepo.Setup(
repo => repo.GetValue<bool>(
It.Is<ConfigElementKey>(k => k.Key == ConfigElementKey.PlayoutSkipMissingItems.Key)))
.ReturnsAsync(Some(true));
(PlayoutBuilder builder, Playout playout) =
TestDataFloodForItems(mediaItems, PlaybackOrder.Random, configRepo);
DateTimeOffset start = HoursAfterMidnight(0);
DateTimeOffset finish = start + TimeSpan.FromHours(6);
Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish);
configRepo.Verify();
result.Items.Count.Should().Be(1);
result.Items.Head().MediaItemId.Should().Be(2);
result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero);
result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6));
}
[Test]
public async Task FileNotFound_Should_NotBeSkippedIfConfigured()
{
var mediaItems = new List<MediaItem>
{
TestMovie(1, TimeSpan.FromHours(6), DateTime.Today)
};
mediaItems[0].State = MediaItemState.FileNotFound;
var configRepo = new Mock<IConfigElementRepository>();
configRepo.Setup(
repo => repo.GetValue<bool>(
It.Is<ConfigElementKey>(k => k.Key == ConfigElementKey.PlayoutSkipMissingItems.Key)))
.ReturnsAsync(Some(false));
(PlayoutBuilder builder, Playout playout) =
TestDataFloodForItems(mediaItems, PlaybackOrder.Random, configRepo);
DateTimeOffset start = HoursAfterMidnight(0);
DateTimeOffset finish = start + TimeSpan.FromHours(6);
Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish);
result.Items.Count.Should().Be(1);
result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero);
result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6));
}
[Test]
public async Task Unavailable_Should_NotBeSkippedIfConfigured()
{
var mediaItems = new List<MediaItem>
{
TestMovie(1, TimeSpan.FromHours(6), DateTime.Today)
};
mediaItems[0].State = MediaItemState.Unavailable;
var configRepo = new Mock<IConfigElementRepository>();
configRepo.Setup(
repo => repo.GetValue<bool>(
It.Is<ConfigElementKey>(k => k.Key == ConfigElementKey.PlayoutSkipMissingItems.Key)))
.ReturnsAsync(Some(false));
(PlayoutBuilder builder, Playout playout) =
TestDataFloodForItems(mediaItems, PlaybackOrder.Random, configRepo);
DateTimeOffset start = HoursAfterMidnight(0);
DateTimeOffset finish = start + TimeSpan.FromHours(6);
Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish);
result.Items.Count.Should().Be(1);
result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero);
result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6));
}
[Test] [Test]
public async Task InitialFlood_Should_StartAtMidnight() public async Task InitialFlood_Should_StartAtMidnight()
{ {
@ -2142,11 +2316,20 @@ public class PlayoutBuilderTests
MovieMetadata = new List<MovieMetadata> { new() { ReleaseDate = aired } }, MovieMetadata = new List<MovieMetadata> { new() { ReleaseDate = aired } },
MediaVersions = new List<MediaVersion> MediaVersions = new List<MediaVersion>
{ {
new() { Duration = duration } new()
{
Duration = duration, MediaFiles = new List<MediaFile>
{
new() { Path = $"/fake/path/{id}" }
}
}
} }
}; };
private TestData TestDataFloodForItems(List<MediaItem> mediaItems, PlaybackOrder playbackOrder) private TestData TestDataFloodForItems(
List<MediaItem> mediaItems,
PlaybackOrder playbackOrder,
Mock<IConfigElementRepository> configMock = null)
{ {
var mediaCollection = new Collection var mediaCollection = new Collection
{ {
@ -2154,7 +2337,8 @@ public class PlayoutBuilderTests
MediaItems = mediaItems MediaItems = mediaItems
}; };
var configRepo = new Mock<IConfigElementRepository>(); Mock<IConfigElementRepository> configRepo = configMock ?? new Mock<IConfigElementRepository>();
var collectionRepo = new FakeMediaCollectionRepository(Map((mediaCollection.Id, mediaItems))); var collectionRepo = new FakeMediaCollectionRepository(Map((mediaCollection.Id, mediaItems)));
var televisionRepo = new FakeTelevisionRepository(); var televisionRepo = new FakeTelevisionRepository();
var artistRepo = new Mock<IArtistRepository>(); var artistRepo = new Mock<IArtistRepository>();

1
ErsatzTV.Core/Domain/ConfigElementKey.cs

@ -33,4 +33,5 @@ public class ConfigElementKey
public static ConfigElementKey FillerPresetsPageSize => new("pages.filler_presets.page_size"); public static ConfigElementKey FillerPresetsPageSize => new("pages.filler_presets.page_size");
public static ConfigElementKey LibraryRefreshInterval => new("scanner.library_refresh_interval"); public static ConfigElementKey LibraryRefreshInterval => new("scanner.library_refresh_interval");
public static ConfigElementKey PlayoutDaysToBuild => new("playout.days_to_build"); public static ConfigElementKey PlayoutDaysToBuild => new("playout.days_to_build");
public static ConfigElementKey PlayoutSkipMissingItems => new("playout.skip_missing_items");
} }

39
ErsatzTV.Core/Scheduling/PlayoutBuilder.cs

@ -1,4 +1,5 @@
using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Extensions;
using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Interfaces.Scheduling; using ErsatzTV.Core.Interfaces.Scheduling;
using LanguageExt.UnsafeValueAccess; using LanguageExt.UnsafeValueAccess;
@ -234,7 +235,13 @@ public class PlayoutBuilder : IPlayoutBuilder
return None; return None;
} }
Option<CollectionKey> maybeEmptyCollection = await CheckForEmptyCollections(collectionMediaItems); Option<bool> skipMissingItems =
await _configElementRepository.GetValue<bool>(ConfigElementKey.PlayoutSkipMissingItems);
Option<CollectionKey> maybeEmptyCollection = await CheckForEmptyCollections(
collectionMediaItems,
await skipMissingItems.IfNoneAsync(false));
foreach (CollectionKey emptyCollection in maybeEmptyCollection) foreach (CollectionKey emptyCollection in maybeEmptyCollection)
{ {
Option<string> maybeName = await _mediaCollectionRepository.GetNameFromKey(emptyCollection); Option<string> maybeName = await _mediaCollectionRepository.GetNameFromKey(emptyCollection);
@ -496,12 +503,13 @@ public class PlayoutBuilder : IPlayoutBuilder
} }
private async Task<Option<CollectionKey>> CheckForEmptyCollections( private async Task<Option<CollectionKey>> CheckForEmptyCollections(
Map<CollectionKey, List<MediaItem>> collectionMediaItems) Map<CollectionKey, List<MediaItem>> collectionMediaItems,
bool skipMissingItems)
{ {
foreach ((CollectionKey _, List<MediaItem> items) in collectionMediaItems) foreach ((CollectionKey _, List<MediaItem> items) in collectionMediaItems)
{ {
var zeroItems = new List<MediaItem>(); var zeroItems = new List<MediaItem>();
// var missingItems = new List<MediaItem>(); var missingItems = new List<MediaItem>();
foreach (MediaItem item in items) foreach (MediaItem item in items)
{ {
@ -520,18 +528,17 @@ public class PlayoutBuilder : IPlayoutBuilder
_ => true _ => true
}; };
// if (item.State == MediaItemState.FileNotFound) if (skipMissingItems && item.State is MediaItemState.FileNotFound or MediaItemState.Unavailable)
// { {
// _logger.LogWarning( _logger.LogWarning(
// "Skipping media item that does not exist on disk {MediaItem} - {MediaItemTitle} - {Path}", "Skipping media item that does not exist on disk {MediaItem} - {MediaItemTitle} - {Path}",
// item.Id, item.Id,
// DisplayTitle(item), DisplayTitle(item),
// item.GetHeadVersion().MediaFiles.Head().Path); item.GetHeadVersion().MediaFiles.Head().Path);
//
// missingItems.Add(item); missingItems.Add(item);
// } }
// else else if (isZero)
if (isZero)
{ {
_logger.LogWarning( _logger.LogWarning(
"Skipping media item with zero duration {MediaItem} - {MediaItemTitle}", "Skipping media item with zero duration {MediaItem} - {MediaItemTitle}",
@ -542,7 +549,7 @@ public class PlayoutBuilder : IPlayoutBuilder
} }
} }
// items.RemoveAll(missingItems.Contains); items.RemoveAll(missingItems.Contains);
items.RemoveAll(zeroItems.Contains); items.RemoveAll(zeroItems.Contains);
} }

19
ErsatzTV/Pages/Settings.razor

@ -5,8 +5,8 @@
@using ErsatzTV.Application.MediaItems @using ErsatzTV.Application.MediaItems
@using ErsatzTV.Application.Watermarks @using ErsatzTV.Application.Watermarks
@using System.Globalization @using System.Globalization
@using ErsatzTV.Core.Domain.Filler
@using ErsatzTV.Application.Configuration @using ErsatzTV.Application.Configuration
@using ErsatzTV.Core.Domain.Filler
@implements IDisposable @implements IDisposable
@inject IMediator _mediator @inject IMediator _mediator
@inject ISnackbar _snackbar @inject ISnackbar _snackbar
@ -147,12 +147,19 @@
<MudForm @bind-IsValid="@_playoutSuccess"> <MudForm @bind-IsValid="@_playoutSuccess">
<MudTextField T="int" <MudTextField T="int"
Label="Days To Build" Label="Days To Build"
@bind-Value="_playoutDaysToBuild" @bind-Value="_playoutSettings.DaysToBuild"
Validation="@(new Func<int, string>(ValidatePlayoutDaysToBuild))" Validation="@(new Func<int, string>(ValidatePlayoutDaysToBuild))"
Required="true" Required="true"
RequiredError="Days to build is required!" RequiredError="Days to build is required!"
Adornment="Adornment.End" Adornment="Adornment.End"
AdornmentText="Days"/> AdornmentText="Days"/>
<MudElement HtmlTag="div" Class="mt-3">
<MudTooltip Text="Controls whether file-not-found or unavailable items should be included in playouts">
<MudCheckBox Label="Skip Missing Items"
@bind-Checked="_playoutSettings.SkipMissingItems"
For="@(() => _playoutSettings.SkipMissingItems)"/>
</MudTooltip>
</MudElement>
</MudForm> </MudForm>
</MudCardContent> </MudCardContent>
<MudCardActions> <MudCardActions>
@ -176,7 +183,7 @@
private List<FillerPresetViewModel> _fillerPresets; private List<FillerPresetViewModel> _fillerPresets;
private int _tunerCount; private int _tunerCount;
private int _libraryRefreshInterval; private int _libraryRefreshInterval;
private int _playoutDaysToBuild; private PlayoutSettingsViewModel _playoutSettings;
public void Dispose() public void Dispose()
{ {
@ -198,8 +205,8 @@
_hdhrSuccess = string.IsNullOrWhiteSpace(ValidateTunerCount(_tunerCount)); _hdhrSuccess = string.IsNullOrWhiteSpace(ValidateTunerCount(_tunerCount));
_libraryRefreshInterval = await _mediator.Send(new GetLibraryRefreshInterval(), _cts.Token); _libraryRefreshInterval = await _mediator.Send(new GetLibraryRefreshInterval(), _cts.Token);
_scannerSuccess = _libraryRefreshInterval > 0; _scannerSuccess = _libraryRefreshInterval > 0;
_playoutDaysToBuild = await _mediator.Send(new GetPlayoutDaysToBuild(), _cts.Token); _playoutSettings = await _mediator.Send(new GetPlayoutSettings(), _cts.Token);
_playoutSuccess = _playoutDaysToBuild > 0; _playoutSuccess = _playoutSettings.DaysToBuild > 0;
} }
private static string ValidatePathExists(string path) => !File.Exists(path) ? "Path does not exist" : null; private static string ValidatePathExists(string path) => !File.Exists(path) ? "Path does not exist" : null;
@ -257,7 +264,7 @@
private async Task SavePlayoutSettings() private async Task SavePlayoutSettings()
{ {
Either<BaseError, Unit> result = await _mediator.Send(new UpdatePlayoutDaysToBuild(_playoutDaysToBuild), _cts.Token); Either<BaseError, Unit> result = await _mediator.Send(new UpdatePlayoutSettings(_playoutSettings), _cts.Token);
result.Match( result.Match(
Left: error => Left: error =>
{ {

Loading…
Cancel
Save