add configurable library refresh interval (#184)
* add configurable library refresh interval * code cleanup
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
using ErsatzTV.Core;
|
||||||
|
using LanguageExt;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.Configuration.Commands
|
||||||
|
{
|
||||||
|
public record UpdateLibraryRefreshInterval(int LibraryRefreshInterval) : MediatR.IRequest<Either<BaseError, Unit>>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using ErsatzTV.Core;
|
||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Core.Interfaces.Repositories;
|
||||||
|
using LanguageExt;
|
||||||
|
using static LanguageExt.Prelude;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.Configuration.Commands
|
||||||
|
{
|
||||||
|
public class
|
||||||
|
UpdateLibraryRefreshIntervalHandler : MediatR.IRequestHandler<UpdateLibraryRefreshInterval,
|
||||||
|
Either<BaseError, Unit>>
|
||||||
|
{
|
||||||
|
private readonly IConfigElementRepository _configElementRepository;
|
||||||
|
|
||||||
|
public UpdateLibraryRefreshIntervalHandler(IConfigElementRepository configElementRepository) =>
|
||||||
|
_configElementRepository = configElementRepository;
|
||||||
|
|
||||||
|
public Task<Either<BaseError, Unit>> Handle(
|
||||||
|
UpdateLibraryRefreshInterval request,
|
||||||
|
CancellationToken cancellationToken) =>
|
||||||
|
Validate(request)
|
||||||
|
.MapT(_ => Upsert(ConfigElementKey.LibraryRefreshInterval, request.LibraryRefreshInterval.ToString()))
|
||||||
|
.Bind(v => v.ToEitherAsync());
|
||||||
|
|
||||||
|
private Task<Validation<BaseError, Unit>> Validate(UpdateLibraryRefreshInterval request) =>
|
||||||
|
Optional(request.LibraryRefreshInterval)
|
||||||
|
.Filter(lri => lri > 0)
|
||||||
|
.Map(_ => Unit.Default)
|
||||||
|
.ToValidation<BaseError>("Tuner count must be greater than zero")
|
||||||
|
.AsTask();
|
||||||
|
|
||||||
|
private Task<Unit> Upsert(ConfigElementKey key, string value) =>
|
||||||
|
_configElementRepository.Get(key).Match(
|
||||||
|
ce =>
|
||||||
|
{
|
||||||
|
ce.Value = value;
|
||||||
|
return _configElementRepository.Update(ce);
|
||||||
|
},
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
var ce = new ConfigElement { Key = key.Key, Value = value };
|
||||||
|
return _configElementRepository.Add(ce);
|
||||||
|
}).ToUnit();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.Configuration.Queries
|
||||||
|
{
|
||||||
|
public record GetLibraryRefreshInterval : IRequest<int>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Core.Interfaces.Repositories;
|
||||||
|
using LanguageExt;
|
||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.Configuration.Queries
|
||||||
|
{
|
||||||
|
public class GetLibraryRefreshIntervalHandler : IRequestHandler<GetLibraryRefreshInterval, int>
|
||||||
|
{
|
||||||
|
private readonly IConfigElementRepository _configElementRepository;
|
||||||
|
|
||||||
|
public GetLibraryRefreshIntervalHandler(IConfigElementRepository configElementRepository) =>
|
||||||
|
_configElementRepository = configElementRepository;
|
||||||
|
|
||||||
|
public Task<int> Handle(GetLibraryRefreshInterval request, CancellationToken cancellationToken) =>
|
||||||
|
_configElementRepository.GetValue<int>(ConfigElementKey.LibraryRefreshInterval)
|
||||||
|
.Map(result => result.IfNone(6));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -64,11 +64,13 @@ namespace ErsatzTV.Application.MediaSources.Commands
|
|||||||
|
|
||||||
private async Task<Unit> PerformScan(RequestParameters parameters)
|
private async Task<Unit> PerformScan(RequestParameters parameters)
|
||||||
{
|
{
|
||||||
(LocalLibrary localLibrary, string ffprobePath, bool forceScan) = parameters;
|
(LocalLibrary localLibrary, string ffprobePath, bool forceScan, int libraryRefreshInterval) = parameters;
|
||||||
|
|
||||||
var sw = new Stopwatch();
|
var sw = new Stopwatch();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
|
|
||||||
|
var scanned = false;
|
||||||
|
|
||||||
for (var i = 0; i < localLibrary.Paths.Count; i++)
|
for (var i = 0; i < localLibrary.Paths.Count; i++)
|
||||||
{
|
{
|
||||||
LibraryPath libraryPath = localLibrary.Paths[i];
|
LibraryPath libraryPath = localLibrary.Paths[i];
|
||||||
@@ -77,8 +79,11 @@ namespace ErsatzTV.Application.MediaSources.Commands
|
|||||||
decimal progressMax = (decimal) (i + 1) / localLibrary.Paths.Count;
|
decimal progressMax = (decimal) (i + 1) / localLibrary.Paths.Count;
|
||||||
|
|
||||||
var lastScan = new DateTimeOffset(libraryPath.LastScan ?? DateTime.MinValue, TimeSpan.Zero);
|
var lastScan = new DateTimeOffset(libraryPath.LastScan ?? DateTime.MinValue, TimeSpan.Zero);
|
||||||
if (forceScan || lastScan < DateTimeOffset.Now - TimeSpan.FromHours(6))
|
DateTimeOffset nextScan = lastScan + TimeSpan.FromHours(libraryRefreshInterval);
|
||||||
|
if (forceScan || nextScan < DateTimeOffset.Now)
|
||||||
{
|
{
|
||||||
|
scanned = true;
|
||||||
|
|
||||||
switch (localLibrary.MediaKind)
|
switch (localLibrary.MediaKind)
|
||||||
{
|
{
|
||||||
case LibraryMediaKind.Movies:
|
case LibraryMediaKind.Movies:
|
||||||
@@ -115,10 +120,20 @@ namespace ErsatzTV.Application.MediaSources.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
_logger.LogDebug(
|
|
||||||
"Scan of library {Name} completed in {Duration}",
|
if (scanned)
|
||||||
localLibrary.Name,
|
{
|
||||||
TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds));
|
_logger.LogDebug(
|
||||||
|
"Scan of library {Name} completed in {Duration}",
|
||||||
|
localLibrary.Name,
|
||||||
|
TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogDebug(
|
||||||
|
"Skipping unforced scan of local media library {Name}",
|
||||||
|
localLibrary.Name);
|
||||||
|
}
|
||||||
|
|
||||||
await _mediator.Publish(new LibraryScanProgress(localLibrary.Id, 0));
|
await _mediator.Publish(new LibraryScanProgress(localLibrary.Id, 0));
|
||||||
|
|
||||||
@@ -127,12 +142,13 @@ namespace ErsatzTV.Application.MediaSources.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Validation<BaseError, RequestParameters>> Validate(IScanLocalLibrary request) =>
|
private async Task<Validation<BaseError, RequestParameters>> Validate(IScanLocalLibrary request) =>
|
||||||
(await LocalLibraryMustExist(request), await ValidateFFprobePath())
|
(await LocalLibraryMustExist(request), await ValidateFFprobePath(), await ValidateLibraryRefreshInterval())
|
||||||
.Apply(
|
.Apply(
|
||||||
(library, ffprobePath) => new RequestParameters(
|
(library, ffprobePath, libraryRefreshInterval) => new RequestParameters(
|
||||||
library,
|
library,
|
||||||
ffprobePath,
|
ffprobePath,
|
||||||
request.ForceScan));
|
request.ForceScan,
|
||||||
|
libraryRefreshInterval));
|
||||||
|
|
||||||
private Task<Validation<BaseError, LocalLibrary>> LocalLibraryMustExist(
|
private Task<Validation<BaseError, LocalLibrary>> LocalLibraryMustExist(
|
||||||
IScanLocalLibrary request) =>
|
IScanLocalLibrary request) =>
|
||||||
@@ -147,6 +163,15 @@ namespace ErsatzTV.Application.MediaSources.Commands
|
|||||||
ffprobePath =>
|
ffprobePath =>
|
||||||
ffprobePath.ToValidation<BaseError>("FFprobe path does not exist on the file system"));
|
ffprobePath.ToValidation<BaseError>("FFprobe path does not exist on the file system"));
|
||||||
|
|
||||||
private record RequestParameters(LocalLibrary LocalLibrary, string FFprobePath, bool ForceScan);
|
private Task<Validation<BaseError, int>> ValidateLibraryRefreshInterval() =>
|
||||||
|
_configElementRepository.GetValue<int>(ConfigElementKey.LibraryRefreshInterval)
|
||||||
|
.FilterT(lri => lri > 0)
|
||||||
|
.Map(lri => lri.ToValidation<BaseError>("Library refresh interval is invalid"));
|
||||||
|
|
||||||
|
private record RequestParameters(
|
||||||
|
LocalLibrary LocalLibrary,
|
||||||
|
string FFprobePath,
|
||||||
|
bool ForceScan,
|
||||||
|
int LibraryRefreshInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace ErsatzTV.Application.Plex.Commands
|
|||||||
SynchronizePlexLibraryByIdHandler : IRequestHandler<ForceSynchronizePlexLibraryById, Either<BaseError, string>>,
|
SynchronizePlexLibraryByIdHandler : IRequestHandler<ForceSynchronizePlexLibraryById, Either<BaseError, string>>,
|
||||||
IRequestHandler<SynchronizePlexLibraryByIdIfNeeded, Either<BaseError, string>>
|
IRequestHandler<SynchronizePlexLibraryByIdIfNeeded, Either<BaseError, string>>
|
||||||
{
|
{
|
||||||
|
private readonly IConfigElementRepository _configElementRepository;
|
||||||
private readonly IEntityLocker _entityLocker;
|
private readonly IEntityLocker _entityLocker;
|
||||||
private readonly ILibraryRepository _libraryRepository;
|
private readonly ILibraryRepository _libraryRepository;
|
||||||
private readonly ILogger<SynchronizePlexLibraryByIdHandler> _logger;
|
private readonly ILogger<SynchronizePlexLibraryByIdHandler> _logger;
|
||||||
@@ -29,6 +30,7 @@ namespace ErsatzTV.Application.Plex.Commands
|
|||||||
|
|
||||||
public SynchronizePlexLibraryByIdHandler(
|
public SynchronizePlexLibraryByIdHandler(
|
||||||
IMediaSourceRepository mediaSourceRepository,
|
IMediaSourceRepository mediaSourceRepository,
|
||||||
|
IConfigElementRepository configElementRepository,
|
||||||
IPlexSecretStore plexSecretStore,
|
IPlexSecretStore plexSecretStore,
|
||||||
IPlexMovieLibraryScanner plexMovieLibraryScanner,
|
IPlexMovieLibraryScanner plexMovieLibraryScanner,
|
||||||
IPlexTelevisionLibraryScanner plexTelevisionLibraryScanner,
|
IPlexTelevisionLibraryScanner plexTelevisionLibraryScanner,
|
||||||
@@ -37,6 +39,7 @@ namespace ErsatzTV.Application.Plex.Commands
|
|||||||
ILogger<SynchronizePlexLibraryByIdHandler> logger)
|
ILogger<SynchronizePlexLibraryByIdHandler> logger)
|
||||||
{
|
{
|
||||||
_mediaSourceRepository = mediaSourceRepository;
|
_mediaSourceRepository = mediaSourceRepository;
|
||||||
|
_configElementRepository = configElementRepository;
|
||||||
_plexSecretStore = plexSecretStore;
|
_plexSecretStore = plexSecretStore;
|
||||||
_plexMovieLibraryScanner = plexMovieLibraryScanner;
|
_plexMovieLibraryScanner = plexMovieLibraryScanner;
|
||||||
_plexTelevisionLibraryScanner = plexTelevisionLibraryScanner;
|
_plexTelevisionLibraryScanner = plexTelevisionLibraryScanner;
|
||||||
@@ -62,7 +65,8 @@ namespace ErsatzTV.Application.Plex.Commands
|
|||||||
private async Task<Unit> Synchronize(RequestParameters parameters)
|
private async Task<Unit> Synchronize(RequestParameters parameters)
|
||||||
{
|
{
|
||||||
var lastScan = new DateTimeOffset(parameters.Library.LastScan ?? DateTime.MinValue, TimeSpan.Zero);
|
var lastScan = new DateTimeOffset(parameters.Library.LastScan ?? DateTime.MinValue, TimeSpan.Zero);
|
||||||
if (parameters.ForceScan || lastScan < DateTimeOffset.Now - TimeSpan.FromHours(6))
|
DateTimeOffset nextScan = lastScan + TimeSpan.FromHours(parameters.LibraryRefreshInterval);
|
||||||
|
if (parameters.ForceScan || nextScan < DateTimeOffset.Now)
|
||||||
{
|
{
|
||||||
switch (parameters.Library.MediaKind)
|
switch (parameters.Library.MediaKind)
|
||||||
{
|
{
|
||||||
@@ -95,12 +99,14 @@ namespace ErsatzTV.Application.Plex.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Validation<BaseError, RequestParameters>> Validate(ISynchronizePlexLibraryById request) =>
|
private async Task<Validation<BaseError, RequestParameters>> Validate(ISynchronizePlexLibraryById request) =>
|
||||||
(await ValidateConnection(request), await PlexLibraryMustExist(request))
|
(await ValidateConnection(request), await PlexLibraryMustExist(request),
|
||||||
|
await ValidateLibraryRefreshInterval())
|
||||||
.Apply(
|
.Apply(
|
||||||
(connectionParameters, plexLibrary) => new RequestParameters(
|
(connectionParameters, plexLibrary, libraryRefreshInterval) => new RequestParameters(
|
||||||
connectionParameters,
|
connectionParameters,
|
||||||
plexLibrary,
|
plexLibrary,
|
||||||
request.ForceScan
|
request.ForceScan,
|
||||||
|
libraryRefreshInterval
|
||||||
));
|
));
|
||||||
|
|
||||||
private Task<Validation<BaseError, ConnectionParameters>> ValidateConnection(
|
private Task<Validation<BaseError, ConnectionParameters>> ValidateConnection(
|
||||||
@@ -139,10 +145,16 @@ namespace ErsatzTV.Application.Plex.Commands
|
|||||||
_mediaSourceRepository.GetPlexLibrary(request.PlexLibraryId)
|
_mediaSourceRepository.GetPlexLibrary(request.PlexLibraryId)
|
||||||
.Map(v => v.ToValidation<BaseError>($"Plex library {request.PlexLibraryId} does not exist."));
|
.Map(v => v.ToValidation<BaseError>($"Plex library {request.PlexLibraryId} does not exist."));
|
||||||
|
|
||||||
|
private Task<Validation<BaseError, int>> ValidateLibraryRefreshInterval() =>
|
||||||
|
_configElementRepository.GetValue<int>(ConfigElementKey.LibraryRefreshInterval)
|
||||||
|
.FilterT(lri => lri > 0)
|
||||||
|
.Map(lri => lri.ToValidation<BaseError>("Library refresh interval is invalid"));
|
||||||
|
|
||||||
private record RequestParameters(
|
private record RequestParameters(
|
||||||
ConnectionParameters ConnectionParameters,
|
ConnectionParameters ConnectionParameters,
|
||||||
PlexLibrary Library,
|
PlexLibrary Library,
|
||||||
bool ForceScan);
|
bool ForceScan,
|
||||||
|
int LibraryRefreshInterval);
|
||||||
|
|
||||||
private record ConnectionParameters(PlexMediaSource PlexMediaSource, PlexConnection ActiveConnection)
|
private record ConnectionParameters(PlexMediaSource PlexMediaSource, PlexConnection ActiveConnection)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,5 +15,6 @@
|
|||||||
public static ConfigElementKey SearchIndexVersion => new("search_index.version");
|
public static ConfigElementKey SearchIndexVersion => new("search_index.version");
|
||||||
public static ConfigElementKey HDHRTunerCount => new("hdhr.tuner_count");
|
public static ConfigElementKey HDHRTunerCount => new("hdhr.tuner_count");
|
||||||
public static ConfigElementKey CollectionsPageSize => new("pages.collections.page_size");
|
public static ConfigElementKey CollectionsPageSize => new("pages.collections.page_size");
|
||||||
|
public static ConfigElementKey LibraryRefreshInterval => new("scanner.library_refresh_interval");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2269
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
public partial class Add_LibraryRefreshInterval : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder) =>
|
||||||
|
migrationBuilder.Sql(
|
||||||
|
"INSERT INTO ConfigElement (Key, Value) VALUES ('scanner.library_refresh_interval', '6')");
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,10 +6,12 @@
|
|||||||
@using ErsatzTV.Application.HDHR.Queries
|
@using ErsatzTV.Application.HDHR.Queries
|
||||||
@using ErsatzTV.Application.MediaItems.Queries
|
@using ErsatzTV.Application.MediaItems.Queries
|
||||||
@using System.Globalization
|
@using System.Globalization
|
||||||
|
@using ErsatzTV.Application.Configuration.Queries
|
||||||
@using Unit = LanguageExt.Unit
|
@using Unit = LanguageExt.Unit
|
||||||
@inject IMediator Mediator
|
@using ErsatzTV.Application.Configuration.Commands
|
||||||
@inject ISnackbar Snackbar
|
@inject IMediator _mediator
|
||||||
@inject ILogger<Settings> Logger
|
@inject ISnackbar _snackbar
|
||||||
|
@inject ILogger<Settings> _logger
|
||||||
|
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8" Style="display: flex; flex-direction: row">
|
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8" Style="display: flex; flex-direction: row">
|
||||||
<MudCard Class="mr-6" Style="max-width: 400px">
|
<MudCard Class="mr-6" Style="max-width: 400px">
|
||||||
@@ -50,7 +52,7 @@
|
|||||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Disabled="@(!_success)" OnClick="@(_ => SaveFFmpegSettings())">Save Settings</MudButton>
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" Disabled="@(!_success)" OnClick="@(_ => SaveFFmpegSettings())">Save Settings</MudButton>
|
||||||
</MudCardActions>
|
</MudCardActions>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
<MudCard Style="width: 350px">
|
<MudCard Class="mr-6" Style="width: 350px">
|
||||||
<MudCardHeader>
|
<MudCardHeader>
|
||||||
<CardHeaderContent>
|
<CardHeaderContent>
|
||||||
<MudText Typo="Typo.h6">HDHomeRun Settings</MudText>
|
<MudText Typo="Typo.h6">HDHomeRun Settings</MudText>
|
||||||
@@ -65,56 +67,96 @@
|
|||||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Disabled="@(!_hdhrSuccess)" OnClick="@(_ => SaveHDHRSettings())">Save Settings</MudButton>
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" Disabled="@(!_hdhrSuccess)" OnClick="@(_ => SaveHDHRSettings())">Save Settings</MudButton>
|
||||||
</MudCardActions>
|
</MudCardActions>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
|
<MudCard Style="width: 350px">
|
||||||
|
<MudCardHeader>
|
||||||
|
<CardHeaderContent>
|
||||||
|
<MudText Typo="Typo.h6">Scanner Settings</MudText>
|
||||||
|
</CardHeaderContent>
|
||||||
|
</MudCardHeader>
|
||||||
|
<MudCardContent>
|
||||||
|
<MudForm @bind-IsValid="@_scannerSuccess">
|
||||||
|
<MudTextField T="int"
|
||||||
|
Label="Library Refresh Interval"
|
||||||
|
@bind-Value="_libraryRefreshInterval"
|
||||||
|
Validation="@(new Func<int, string>(ValidateLibraryRefreshInterval))"
|
||||||
|
Required="true"
|
||||||
|
RequiredError="Library refresh interval is required!"
|
||||||
|
Adornment="Adornment.End"
|
||||||
|
AdornmentText="Hours"/>
|
||||||
|
</MudForm>
|
||||||
|
</MudCardContent>
|
||||||
|
<MudCardActions>
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" Disabled="@(!_scannerSuccess)" OnClick="@(_ => SaveScannerSettings())">Save Settings</MudButton>
|
||||||
|
</MudCardActions>
|
||||||
|
</MudCard>
|
||||||
</MudContainer>
|
</MudContainer>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private bool _success;
|
private bool _success;
|
||||||
private bool _hdhrSuccess;
|
private bool _hdhrSuccess;
|
||||||
|
private bool _scannerSuccess;
|
||||||
private List<FFmpegProfileViewModel> _ffmpegProfiles;
|
private List<FFmpegProfileViewModel> _ffmpegProfiles;
|
||||||
private FFmpegSettingsViewModel _ffmpegSettings;
|
private FFmpegSettingsViewModel _ffmpegSettings;
|
||||||
private List<CultureInfo> _availableCultures;
|
private List<CultureInfo> _availableCultures;
|
||||||
private int _tunerCount;
|
private int _tunerCount;
|
||||||
|
private int _libraryRefreshInterval;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
await LoadFFmpegProfilesAsync();
|
await LoadFFmpegProfilesAsync();
|
||||||
|
|
||||||
_ffmpegSettings = await Mediator.Send(new GetFFmpegSettings());
|
_ffmpegSettings = await _mediator.Send(new GetFFmpegSettings());
|
||||||
_success = File.Exists(_ffmpegSettings.FFmpegPath) && File.Exists(_ffmpegSettings.FFprobePath);
|
_success = File.Exists(_ffmpegSettings.FFmpegPath) && File.Exists(_ffmpegSettings.FFprobePath);
|
||||||
_availableCultures = await Mediator.Send(new GetAllLanguageCodes());
|
_availableCultures = await _mediator.Send(new GetAllLanguageCodes());
|
||||||
_tunerCount = await Mediator.Send(new GetHDHRTunerCount());
|
_tunerCount = await _mediator.Send(new GetHDHRTunerCount());
|
||||||
_hdhrSuccess = string.IsNullOrWhiteSpace(ValidateTunerCount(_tunerCount));
|
_hdhrSuccess = string.IsNullOrWhiteSpace(ValidateTunerCount(_tunerCount));
|
||||||
|
_libraryRefreshInterval = await _mediator.Send(new GetLibraryRefreshInterval());
|
||||||
|
_scannerSuccess = _libraryRefreshInterval > 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;
|
||||||
|
|
||||||
private static string ValidateTunerCount(int tunerCount) => tunerCount <= 0 ? "Tuner count must be greater than zero" : null;
|
private static string ValidateTunerCount(int tunerCount) => tunerCount <= 0 ? "Tuner count must be greater than zero" : null;
|
||||||
|
|
||||||
|
private static string ValidateLibraryRefreshInterval(int libraryRefreshInterval) => libraryRefreshInterval <= 0 ? "Library refresh interval must be greater than zero" : null;
|
||||||
|
|
||||||
private async Task LoadFFmpegProfilesAsync() =>
|
private async Task LoadFFmpegProfilesAsync() =>
|
||||||
_ffmpegProfiles = await Mediator.Send(new GetAllFFmpegProfiles());
|
_ffmpegProfiles = await _mediator.Send(new GetAllFFmpegProfiles());
|
||||||
|
|
||||||
private async Task SaveFFmpegSettings()
|
private async Task SaveFFmpegSettings()
|
||||||
{
|
{
|
||||||
Either<BaseError, Unit> result = await Mediator.Send(new UpdateFFmpegSettings(_ffmpegSettings));
|
Either<BaseError, Unit> result = await _mediator.Send(new UpdateFFmpegSettings(_ffmpegSettings));
|
||||||
result.Match(
|
result.Match(
|
||||||
Left: error =>
|
Left: error =>
|
||||||
{
|
{
|
||||||
Snackbar.Add(error.Value, Severity.Error);
|
_snackbar.Add(error.Value, Severity.Error);
|
||||||
Logger.LogError("Unexpected error saving FFmpeg settings: {Error}", error.Value);
|
_logger.LogError("Unexpected error saving FFmpeg settings: {Error}", error.Value);
|
||||||
},
|
},
|
||||||
Right: _ => Snackbar.Add("Successfully saved FFmpeg settings", Severity.Success));
|
Right: _ => _snackbar.Add("Successfully saved FFmpeg settings", Severity.Success));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveHDHRSettings()
|
private async Task SaveHDHRSettings()
|
||||||
{
|
{
|
||||||
Either<BaseError, Unit> result = await Mediator.Send(new UpdateHDHRTunerCount(_tunerCount));
|
Either<BaseError, Unit> result = await _mediator.Send(new UpdateHDHRTunerCount(_tunerCount));
|
||||||
result.Match(
|
result.Match(
|
||||||
Left: error =>
|
Left: error =>
|
||||||
{
|
{
|
||||||
Snackbar.Add(error.Value, Severity.Error);
|
_snackbar.Add(error.Value, Severity.Error);
|
||||||
Logger.LogError("Unexpected error saving HDHomeRun settings: {Error}", error.Value);
|
_logger.LogError("Unexpected error saving HDHomeRun settings: {Error}", error.Value);
|
||||||
},
|
},
|
||||||
Right: _ => Snackbar.Add("Successfully saved HDHomeRun settings", Severity.Success));
|
Right: _ => _snackbar.Add("Successfully saved HDHomeRun settings", Severity.Success));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveScannerSettings()
|
||||||
|
{
|
||||||
|
Either<BaseError, Unit> result = await _mediator.Send(new UpdateLibraryRefreshInterval(_libraryRefreshInterval));
|
||||||
|
result.Match(
|
||||||
|
Left: error =>
|
||||||
|
{
|
||||||
|
_snackbar.Add(error.Value, Severity.Error);
|
||||||
|
_logger.LogError("Unexpected error saving scanner settings: {Error}", error.Value);
|
||||||
|
},
|
||||||
|
Right: _ => _snackbar.Add("Successfully saved scanner settings", Severity.Success));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user