@using ErsatzTV.Application.MediaSources @implements IDisposable @inject IMediator _mediator @inject NavigationManager _navigationManager @inject ILogger _logger @inject ISnackbar _snackbar @inject IEntityLocker _locker @_source.Name Libraries Name Media Kind Synchronize @context.Name @context.MediaKind Save Changes @code { private readonly CancellationTokenSource _cts = new(); [Parameter] public int Id { get; set; } [Parameter] public string Name { get; set; } [Parameter] public Func>> GetMediaSourceById { get; set; } [Parameter] public Func>> GetLibrariesBySourceId { get; set; } [Parameter] public Func, IRequest>> GetUpdateLibraryRequest { get; set; } [Parameter] public Func> SynchronizeLibraryByIdIfNeeded { get; set; } private RemoteMediaSourceViewModel _source; private List _libraries; public record SynchronizeParameters(int LibraryId, int MediaSourceId); public void Dispose() { _cts.Cancel(); _cts.Dispose(); } protected override Task OnParametersSetAsync() => LoadData(); private async Task LoadData() { Option maybeSource = await GetMediaSourceById(Id); await maybeSource.Match( async source => { _source = source; _libraries = await GetLibrariesBySourceId(Id); }, () => { _navigationManager.NavigateTo("404"); return Task.CompletedTask; }); } private async Task SaveChanges() { IRequest> request = GetUpdateLibraryRequest(_libraries); 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); return Task.CompletedTask; }, async () => { foreach (int libraryId in _libraries.Filter(l => l.ShouldSyncItems).Map(l => l.Id)) { if (_locker.LockLibrary(libraryId)) { await SynchronizeLibraryByIdIfNeeded(new SynchronizeParameters(libraryId, Id)); } } _navigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}"); }); } }