use cancellation tokens in ui (#666)
* use cancellation tokens in pages * use cancellation token in shared ui * use cancellation tokens in artwork controller
This commit is contained in:
@@ -8,8 +8,10 @@
|
||||
@using ErsatzTV.Application.ProgramSchedules
|
||||
@using ErsatzTV.Application.ProgramSchedules.Commands
|
||||
@using System.Globalization
|
||||
@using System.Threading
|
||||
@using ErsatzTV.Extensions
|
||||
@using Unit = LanguageExt.Unit
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
@inject IDialogService _dialog
|
||||
@inject NavigationManager _navigationManager
|
||||
@@ -185,6 +187,7 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int ArtistId { get; set; }
|
||||
@@ -195,12 +198,18 @@
|
||||
private List<string> _sortedStyles = new();
|
||||
private List<string> _sortedMoods = new();
|
||||
private MusicVideoCardResultsViewModel _musicVideos;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override Task OnParametersSetAsync() => RefreshData();
|
||||
|
||||
private async Task RefreshData()
|
||||
{
|
||||
await _mediator.Send(new GetArtistById(ArtistId)).IfSomeAsync(vm =>
|
||||
await _mediator.Send(new GetArtistById(ArtistId), _cts.Token).IfSomeAsync(vm =>
|
||||
{
|
||||
_artist = vm;
|
||||
_sortedLanguages = _artist.Languages.OrderBy(ci => ci.EnglishName).ToList();
|
||||
@@ -209,7 +218,7 @@
|
||||
_sortedMoods = _artist.Moods.OrderBy(m => m).ToList();
|
||||
});
|
||||
|
||||
_musicVideos = await _mediator.Send(new GetMusicVideoCards(ArtistId, 1, 100));
|
||||
_musicVideos = await _mediator.Send(new GetMusicVideoCards(ArtistId, 1, 100), _cts.Token);
|
||||
}
|
||||
|
||||
private async Task AddToCollection()
|
||||
@@ -221,7 +230,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
await _mediator.Send(new AddArtistToCollection(collection.Id, ArtistId));
|
||||
await _mediator.Send(new AddArtistToCollection(collection.Id, ArtistId), _cts.Token);
|
||||
_navigationManager.NavigateTo($"/media/collections/{collection.Id}");
|
||||
}
|
||||
}
|
||||
@@ -235,7 +244,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled && result.Data is ProgramScheduleViewModel schedule)
|
||||
{
|
||||
await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.Artist, null, null, null, ArtistId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null));
|
||||
await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.Artist, null, null, null, ArtistId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null), _cts.Token);
|
||||
_navigationManager.NavigateTo($"/schedules/{schedule.Id}/items");
|
||||
}
|
||||
}
|
||||
@@ -250,7 +259,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddMusicVideoToCollection(collection.Id, musicVideo.MusicVideoId);
|
||||
Either<BaseError, Unit> addResult = await _mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await _mediator.Send(request, _cts.Token);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
protected override async Task RefreshData()
|
||||
{
|
||||
string searchQuery = string.IsNullOrWhiteSpace(_query) ? "type:artist" : $"type:artist AND ({_query})";
|
||||
_data = await Mediator.Send(new QuerySearchIndexArtists(searchQuery, PageNumber, PageSize));
|
||||
_data = await Mediator.Send(new QuerySearchIndexArtists(searchQuery, PageNumber, PageSize), CancellationToken);
|
||||
}
|
||||
|
||||
private void PrevPage()
|
||||
@@ -144,7 +144,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddArtistToCollection(collection.Id, artist.ArtistId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
@using ErsatzTV.Application.Images.Commands
|
||||
@using ErsatzTV.Application.MediaItems.Queries
|
||||
@using System.Globalization
|
||||
@using System.Threading
|
||||
@using ErsatzTV.Application.Channels
|
||||
@using ErsatzTV.Application.Channels.Queries
|
||||
@using ErsatzTV.Application.Filler
|
||||
@@ -13,6 +14,7 @@
|
||||
@using ErsatzTV.Application.Watermarks
|
||||
@using ErsatzTV.Application.Watermarks.Queries
|
||||
@using ErsatzTV.Core.Domain.Filler
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<ChannelEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -107,6 +109,7 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int? Id { get; set; }
|
||||
@@ -119,17 +122,23 @@
|
||||
private List<CultureInfo> _availableCultures;
|
||||
private List<WatermarkViewModel> _watermarks;
|
||||
private List<FillerPresetViewModel> _fillerPresets;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await LoadFFmpegProfiles();
|
||||
_availableCultures = await _mediator.Send(new GetAllLanguageCodes());
|
||||
await LoadWatermarks();
|
||||
await LoadFillerPresets();
|
||||
await LoadFFmpegProfiles(_cts.Token);
|
||||
_availableCultures = await _mediator.Send(new GetAllLanguageCodes(), _cts.Token);
|
||||
await LoadWatermarks(_cts.Token);
|
||||
await LoadFillerPresets(_cts.Token);
|
||||
|
||||
if (Id.HasValue)
|
||||
{
|
||||
Option<ChannelViewModel> maybeChannel = await _mediator.Send(new GetChannelById(Id.Value));
|
||||
Option<ChannelViewModel> maybeChannel = await _mediator.Send(new GetChannelById(Id.Value), _cts.Token);
|
||||
maybeChannel.Match(
|
||||
channelViewModel =>
|
||||
{
|
||||
@@ -149,10 +158,10 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
FFmpegSettingsViewModel ffmpegSettings = await _mediator.Send(new GetFFmpegSettings());
|
||||
FFmpegSettingsViewModel ffmpegSettings = await _mediator.Send(new GetFFmpegSettings(), _cts.Token);
|
||||
|
||||
// TODO: command for new channel
|
||||
IEnumerable<int> channelNumbers = await _mediator.Send(new GetAllChannels())
|
||||
IEnumerable<int> channelNumbers = await _mediator.Send(new GetAllChannels(), _cts.Token)
|
||||
.Map(list => list.Map(c => int.TryParse(c.Number.Split(".").Head(), out int result) ? result : 0));
|
||||
int maxNumber = Optional(channelNumbers).Flatten().DefaultIfEmpty(0).Max();
|
||||
_model.Number = (maxNumber + 1).ToString();
|
||||
@@ -171,14 +180,14 @@
|
||||
|
||||
private bool IsEdit => Id.HasValue;
|
||||
|
||||
private async Task LoadFFmpegProfiles() =>
|
||||
_ffmpegProfiles = await _mediator.Send(new GetAllFFmpegProfiles());
|
||||
private async Task LoadFFmpegProfiles(CancellationToken cancellationToken) =>
|
||||
_ffmpegProfiles = await _mediator.Send(new GetAllFFmpegProfiles(), cancellationToken);
|
||||
|
||||
private async Task LoadWatermarks() =>
|
||||
_watermarks = await _mediator.Send(new GetAllWatermarks());
|
||||
private async Task LoadWatermarks(CancellationToken cancellationToken) =>
|
||||
_watermarks = await _mediator.Send(new GetAllWatermarks(), cancellationToken);
|
||||
|
||||
private async Task LoadFillerPresets() =>
|
||||
_fillerPresets = await _mediator.Send(new GetAllFillerPresets())
|
||||
private async Task LoadFillerPresets(CancellationToken cancellationToken) =>
|
||||
_fillerPresets = await _mediator.Send(new GetAllFillerPresets(), cancellationToken)
|
||||
.Map(list => list.Filter(vm => vm.FillerKind == FillerKind.Fallback).ToList());
|
||||
|
||||
private async Task HandleSubmitAsync()
|
||||
@@ -187,8 +196,8 @@
|
||||
if (_editContext.Validate())
|
||||
{
|
||||
Seq<BaseError> errorMessage = IsEdit ?
|
||||
(await _mediator.Send(_model.ToUpdate())).LeftToSeq() :
|
||||
(await _mediator.Send(_model.ToCreate())).LeftToSeq();
|
||||
(await _mediator.Send(_model.ToUpdate(), _cts.Token)).LeftToSeq() :
|
||||
(await _mediator.Send(_model.ToCreate(), _cts.Token)).LeftToSeq();
|
||||
|
||||
errorMessage.HeadOrNone().Match(
|
||||
error =>
|
||||
@@ -205,7 +214,7 @@
|
||||
try
|
||||
{
|
||||
Either<BaseError, string> maybeCacheFileName =
|
||||
await _mediator.Send(new SaveArtworkToDisk(e.File.OpenReadStream(maxAllowedSize: 10 * 1024 * 1024), ArtworkKind.Logo));
|
||||
await _mediator.Send(new SaveArtworkToDisk(e.File.OpenReadStream(maxAllowedSize: 10 * 1024 * 1024), ArtworkKind.Logo), _cts.Token);
|
||||
maybeCacheFileName.Match(
|
||||
relativeFileName =>
|
||||
{
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
@using ErsatzTV.Application.FFmpegProfiles
|
||||
@using ErsatzTV.Application.FFmpegProfiles.Queries
|
||||
@using System.Globalization
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IDialogService _dialog
|
||||
@inject IMediator _mediator
|
||||
|
||||
@@ -82,15 +84,23 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private MudTable<ChannelViewModel> _table;
|
||||
private List<FFmpegProfileViewModel> _ffmpegProfiles;
|
||||
|
||||
private int _rowsPerPage;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_ffmpegProfiles = await _mediator.Send(new GetAllFFmpegProfiles());
|
||||
_rowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.ChannelsPageSize))
|
||||
_ffmpegProfiles = await _mediator.Send(new GetAllFFmpegProfiles(), _cts.Token);
|
||||
_rowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.ChannelsPageSize), _cts.Token)
|
||||
.Map(maybeRows => maybeRows.Match(ce => int.TryParse(ce.Value, out int rows) ? rows : 10, () => 10));
|
||||
}
|
||||
|
||||
@@ -103,16 +113,16 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await _mediator.Send(new DeleteChannel(channel.Id));
|
||||
await _mediator.Send(new DeleteChannel(channel.Id), _cts.Token);
|
||||
await _table.ReloadServerData();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<TableData<ChannelViewModel>> ServerReload(TableState state)
|
||||
{
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.ChannelsPageSize, state.PageSize.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.ChannelsPageSize, state.PageSize.ToString()), _cts.Token);
|
||||
|
||||
List<ChannelViewModel> channels = await _mediator.Send(new GetAllChannels());
|
||||
List<ChannelViewModel> channels = await _mediator.Send(new GetAllChannels(), _cts.Token);
|
||||
IOrderedEnumerable<ChannelViewModel> sorted = channels.OrderBy(c => decimal.Parse(c.Number));
|
||||
|
||||
CultureInfo[] allCultures = CultureInfo.GetCultures(CultureTypes.NeutralCultures);
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
@using ErsatzTV.Application.MediaCollections
|
||||
@using ErsatzTV.Application.MediaCollections.Commands
|
||||
@using ErsatzTV.Application.MediaCollections.Queries
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<CollectionEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -29,19 +31,26 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
|
||||
private readonly CollectionEditViewModel _model = new();
|
||||
private EditContext _editContext;
|
||||
private ValidationMessageStore _messageStore;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (IsEdit)
|
||||
{
|
||||
Option<MediaCollectionViewModel> maybeCollection = await _mediator.Send(new GetCollectionById(Id));
|
||||
Option<MediaCollectionViewModel> maybeCollection = await _mediator.Send(new GetCollectionById(Id), _cts.Token);
|
||||
maybeCollection.IfSome(collection =>
|
||||
{
|
||||
_model.Id = collection.Id;
|
||||
@@ -68,8 +77,8 @@
|
||||
if (_editContext.Validate())
|
||||
{
|
||||
Seq<BaseError> errorMessage = IsEdit ?
|
||||
(await _mediator.Send(new UpdateCollection(Id, _model.Name))).LeftToSeq() :
|
||||
(await _mediator.Send(new CreateCollection(_model.Name))).LeftToSeq();
|
||||
(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 =>
|
||||
|
||||
@@ -294,7 +294,7 @@
|
||||
protected override async Task RefreshData()
|
||||
{
|
||||
Either<BaseError, CollectionCardResultsViewModel> maybeResult =
|
||||
await Mediator.Send(new GetCollectionCards(Id));
|
||||
await Mediator.Send(new GetCollectionCards(Id), CancellationToken);
|
||||
|
||||
maybeResult.Match(
|
||||
result => _data = result,
|
||||
@@ -459,7 +459,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await Mediator.Send(request);
|
||||
await Mediator.Send(request, CancellationToken);
|
||||
await RefreshData();
|
||||
}
|
||||
}
|
||||
@@ -468,7 +468,7 @@
|
||||
{
|
||||
_data.UseCustomPlaybackOrder = !_data.UseCustomPlaybackOrder;
|
||||
var request = new UpdateCollection(Id, _data.Name) { UseCustomPlaybackOrder = _data.UseCustomPlaybackOrder };
|
||||
await Mediator.Send(request);
|
||||
await Mediator.Send(request, CancellationToken);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
@using ErsatzTV.Application.Configuration.Queries
|
||||
@using ErsatzTV.Application.Configuration.Commands
|
||||
@using ErsatzTV.Extensions
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IDialogService _dialog
|
||||
@inject IMediator _mediator
|
||||
|
||||
@@ -134,6 +136,8 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private MudTable<MediaCollectionViewModel> _collectionsTable;
|
||||
private MudTable<MultiCollectionViewModel> _multiCollectionsTable;
|
||||
private MudTable<SmartCollectionViewModel> _smartCollectionsTable;
|
||||
@@ -141,16 +145,22 @@
|
||||
private int _collectionsRowsPerPage;
|
||||
private int _multiCollectionsRowsPerPage;
|
||||
private int _smartCollectionsRowsPerPage;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_collectionsRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.CollectionsPageSize))
|
||||
_collectionsRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.CollectionsPageSize), _cts.Token)
|
||||
.Map(maybeRows => maybeRows.Match(ce => int.TryParse(ce.Value, out int rows) ? rows : 10, () => 10));
|
||||
|
||||
_multiCollectionsRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.MultiCollectionsPageSize))
|
||||
_multiCollectionsRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.MultiCollectionsPageSize), _cts.Token)
|
||||
.Map(maybeRows => maybeRows.Match(ce => int.TryParse(ce.Value, out int rows) ? rows : 10, () => 10));
|
||||
|
||||
_smartCollectionsRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.SmartCollectionsPageSize))
|
||||
_smartCollectionsRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.SmartCollectionsPageSize), _cts.Token)
|
||||
.Map(maybeRows => maybeRows.Match(ce => int.TryParse(ce.Value, out int rows) ? rows : 10, () => 10));
|
||||
}
|
||||
|
||||
@@ -163,7 +173,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await _mediator.Send(new DeleteCollection(collection.Id));
|
||||
await _mediator.Send(new DeleteCollection(collection.Id), _cts.Token);
|
||||
await _collectionsTable.ReloadServerData();
|
||||
}
|
||||
}
|
||||
@@ -177,7 +187,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await _mediator.Send(new DeleteMultiCollection(collection.Id));
|
||||
await _mediator.Send(new DeleteMultiCollection(collection.Id), _cts.Token);
|
||||
await _multiCollectionsTable.ReloadServerData();
|
||||
}
|
||||
}
|
||||
@@ -191,32 +201,32 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await _mediator.Send(new DeleteSmartCollection(collection.Id));
|
||||
await _mediator.Send(new DeleteSmartCollection(collection.Id), _cts.Token);
|
||||
await _smartCollectionsTable.ReloadServerData();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<TableData<MediaCollectionViewModel>> ServerReloadCollections(TableState state)
|
||||
{
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.CollectionsPageSize, state.PageSize.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.CollectionsPageSize, state.PageSize.ToString()), _cts.Token);
|
||||
|
||||
PagedMediaCollectionsViewModel data = await _mediator.Send(new GetPagedCollections(state.Page, state.PageSize));
|
||||
PagedMediaCollectionsViewModel data = await _mediator.Send(new GetPagedCollections(state.Page, state.PageSize), _cts.Token);
|
||||
return new TableData<MediaCollectionViewModel> { TotalItems = data.TotalCount, Items = data.Page };
|
||||
}
|
||||
|
||||
private async Task<TableData<MultiCollectionViewModel>> ServerReloadMultiCollections(TableState state)
|
||||
{
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.MultiCollectionsPageSize, state.PageSize.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.MultiCollectionsPageSize, state.PageSize.ToString()), _cts.Token);
|
||||
|
||||
PagedMultiCollectionsViewModel data = await _mediator.Send(new GetPagedMultiCollections(state.Page, state.PageSize));
|
||||
PagedMultiCollectionsViewModel data = await _mediator.Send(new GetPagedMultiCollections(state.Page, state.PageSize), _cts.Token);
|
||||
return new TableData<MultiCollectionViewModel> { TotalItems = data.TotalCount, Items = data.Page };
|
||||
}
|
||||
|
||||
private async Task<TableData<SmartCollectionViewModel>> ServerReloadSmartCollections(TableState state)
|
||||
{
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.SmartCollectionsPageSize, state.PageSize.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.SmartCollectionsPageSize, state.PageSize.ToString()), _cts.Token);
|
||||
|
||||
PagedSmartCollectionsViewModel data = await _mediator.Send(new GetPagedSmartCollections(state.Page, state.PageSize));
|
||||
PagedSmartCollectionsViewModel data = await _mediator.Send(new GetPagedSmartCollections(state.Page, state.PageSize), _cts.Token);
|
||||
return new TableData<SmartCollectionViewModel> { TotalItems = data.TotalCount, Items = data.Page };
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
@using ErsatzTV.Application.Emby.Queries
|
||||
@using ErsatzTV.Application.MediaSources
|
||||
@using ErsatzTV.Application.Emby
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
@inject ChannelWriter<IEmbyBackgroundServiceRequest> _channel
|
||||
|
||||
@@ -16,10 +18,17 @@
|
||||
SynchronizeLibraryByIdIfNeeded="SynchronizeLibraryByIdIfNeeded"/>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
private IRequest<Either<BaseError, Unit>> GetUpdateLibraryRequest(List<RemoteMediaSourceLibraryEditViewModel> libraries) =>
|
||||
new UpdateEmbyLibraryPreferences(
|
||||
libraries.Map(l => new EmbyLibraryPreference(l.Id, l.ShouldSyncItems)).ToList());
|
||||
@@ -42,7 +51,7 @@
|
||||
|
||||
private async Task<Unit> SynchronizeLibraryByIdIfNeeded(int libraryId)
|
||||
{
|
||||
await _channel.WriteAsync(new SynchronizeEmbyLibraryByIdIfNeeded(libraryId));
|
||||
await _channel.WriteAsync(new SynchronizeEmbyLibraryByIdIfNeeded(libraryId), _cts.Token);
|
||||
return Unit.Default;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
@using ErsatzTV.Core.Emby
|
||||
@using ErsatzTV.Application.Emby.Queries
|
||||
@using ErsatzTV.Application.Emby.Commands
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -14,10 +16,17 @@
|
||||
SaveSecrets="SaveSecrets"/>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
private async Task<Unit> LoadSecrets(RemoteMediaSourceEditViewModel viewModel)
|
||||
{
|
||||
EmbySecrets secrets = await _mediator.Send(new GetEmbySecrets());
|
||||
EmbySecrets secrets = await _mediator.Send(new GetEmbySecrets(), _cts.Token);
|
||||
viewModel.Address = secrets.Address;
|
||||
viewModel.ApiKey = secrets.ApiKey;
|
||||
return Unit.Default;
|
||||
@@ -26,7 +35,7 @@
|
||||
private async Task<Either<BaseError, Unit>> SaveSecrets(RemoteMediaSourceEditViewModel viewModel)
|
||||
{
|
||||
var secrets = new EmbySecrets { Address = viewModel.Address, ApiKey = viewModel.ApiKey };
|
||||
return await _mediator.Send(new SaveEmbySecrets(secrets));
|
||||
return await _mediator.Send(new SaveEmbySecrets(secrets), _cts.Token);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
@using ErsatzTV.Core.Interfaces.Emby
|
||||
@using ErsatzTV.Application.Emby.Commands
|
||||
@using ErsatzTV.Application.Emby.Queries
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IEmbySecretStore _embySecretStore
|
||||
@inject ChannelWriter<IEmbyBackgroundServiceRequest> _channel
|
||||
|
||||
@@ -16,8 +18,15 @@
|
||||
SecretStore="@_embySecretStore"/>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
private async Task RefreshLibraries(int mediaSourceId) =>
|
||||
await _channel.WriteAsync(new SynchronizeEmbyLibraries(mediaSourceId));
|
||||
await _channel.WriteAsync(new SynchronizeEmbyLibraries(mediaSourceId), _cts.Token);
|
||||
|
||||
}
|
||||
@@ -4,6 +4,8 @@
|
||||
@using ErsatzTV.Application.Emby
|
||||
@using ErsatzTV.Application.Emby.Commands
|
||||
@using Unit = LanguageExt.Unit
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<ScheduleItemsEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -17,16 +19,23 @@
|
||||
GetPathReplacementsBySourceId="GetPathReplacementsBySourceId"/>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
private Task<Option<RemoteMediaSourceViewModel>> GetMediaSourceById(int id) =>
|
||||
_mediator.Send(new GetEmbyMediaSourceById(Id))
|
||||
_mediator.Send(new GetEmbyMediaSourceById(Id), _cts.Token)
|
||||
.MapT(vm => new RemoteMediaSourceViewModel(vm.Id, vm.Name, vm.Address));
|
||||
|
||||
private Task<List<RemoteMediaSourcePathReplacementEditViewModel>> GetPathReplacementsBySourceId(int mediaSourceId) =>
|
||||
_mediator.Send(new GetEmbyPathReplacementsBySourceId(Id))
|
||||
_mediator.Send(new GetEmbyPathReplacementsBySourceId(Id), _cts.Token)
|
||||
.Map(list => list.Map(ProjectToEditViewModel).ToList());
|
||||
|
||||
private RemoteMediaSourcePathReplacementEditViewModel ProjectToEditViewModel(EmbyPathReplacementViewModel item) =>
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
protected override async Task RefreshData()
|
||||
{
|
||||
string searchQuery = string.IsNullOrWhiteSpace(_query) ? "type:episode" : $"type:episode AND ({_query})";
|
||||
_data = await Mediator.Send(new QuerySearchIndexEpisodes(searchQuery, PageNumber, PageSize));
|
||||
_data = await Mediator.Send(new QuerySearchIndexEpisodes(searchQuery, PageNumber, PageSize), CancellationToken);
|
||||
}
|
||||
|
||||
private void PrevPage()
|
||||
@@ -144,7 +144,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddEpisodeToCollection(collection.Id, episode.EpisodeId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
@using ErsatzTV.Application.FFmpegProfiles
|
||||
@using ErsatzTV.Application.FFmpegProfiles.Commands
|
||||
@using ErsatzTV.Application.FFmpegProfiles.Queries
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IDialogService _dialog
|
||||
@inject IMediator _mediator
|
||||
@inject ILogger<FFmpeg> _logger
|
||||
@@ -78,12 +80,20 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private List<FFmpegProfileViewModel> _ffmpegProfiles;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync() => await LoadFFmpegProfilesAsync();
|
||||
protected override async Task OnParametersSetAsync() => await LoadFFmpegProfilesAsync(_cts.Token);
|
||||
|
||||
private async Task LoadFFmpegProfilesAsync() =>
|
||||
_ffmpegProfiles = await _mediator.Send(new GetAllFFmpegProfiles());
|
||||
private async Task LoadFFmpegProfilesAsync(CancellationToken cancellationToken) =>
|
||||
_ffmpegProfiles = await _mediator.Send(new GetAllFFmpegProfiles(), cancellationToken);
|
||||
|
||||
private async Task DeleteProfileAsync(FFmpegProfileViewModel ffmpegProfile)
|
||||
{
|
||||
@@ -94,8 +104,8 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await _mediator.Send(new DeleteFFmpegProfile(ffmpegProfile.Id));
|
||||
await LoadFFmpegProfilesAsync();
|
||||
await _mediator.Send(new DeleteFFmpegProfile(ffmpegProfile.Id), _cts.Token);
|
||||
await LoadFFmpegProfilesAsync(_cts.Token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
@using ErsatzTV.Core.FFmpeg
|
||||
@using Microsoft.AspNetCore.Components
|
||||
@using Microsoft.Extensions.Caching.Memory
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<FFmpegEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -121,6 +123,7 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
@@ -132,20 +135,26 @@
|
||||
private List<ResolutionViewModel> _resolutions;
|
||||
private List<string> _vaapiDevices;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_resolutions = await _mediator.Send(new GetAllResolutions());
|
||||
_resolutions = await _mediator.Send(new GetAllResolutions(), _cts.Token);
|
||||
|
||||
if (IsEdit)
|
||||
{
|
||||
Option<FFmpegProfileViewModel> profile = await _mediator.Send(new GetFFmpegProfileById(Id));
|
||||
Option<FFmpegProfileViewModel> profile = await _mediator.Send(new GetFFmpegProfileById(Id), _cts.Token);
|
||||
profile.Match(
|
||||
ffmpegProfileViewModel => _model = new FFmpegProfileEditViewModel(ffmpegProfileViewModel),
|
||||
() => _navigationManager.NavigateTo("404"));
|
||||
}
|
||||
else
|
||||
{
|
||||
_model = new FFmpegProfileEditViewModel(await _mediator.Send(new NewFFmpegProfile()));
|
||||
_model = new FFmpegProfileEditViewModel(await _mediator.Send(new NewFFmpegProfile(), _cts.Token));
|
||||
}
|
||||
|
||||
_editContext = new EditContext(_model);
|
||||
@@ -167,8 +176,8 @@
|
||||
if (_editContext.Validate())
|
||||
{
|
||||
Seq<BaseError> errorMessage = IsEdit ?
|
||||
(await _mediator.Send(_model.ToUpdate())).LeftToSeq() :
|
||||
(await _mediator.Send(_model.ToCreate())).LeftToSeq();
|
||||
(await _mediator.Send(_model.ToUpdate(), _cts.Token)).LeftToSeq() :
|
||||
(await _mediator.Send(_model.ToCreate(), _cts.Token)).LeftToSeq();
|
||||
|
||||
errorMessage.HeadOrNone().Match(
|
||||
error =>
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
@using ErsatzTV.Application.MediaItems
|
||||
@using ErsatzTV.Core.Domain.Filler
|
||||
@using Microsoft.AspNetCore.Components
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<FillerPresetEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -134,6 +136,8 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
@@ -148,24 +152,30 @@
|
||||
private List<NamedMediaItemViewModel> _televisionSeasons;
|
||||
private List<NamedMediaItemViewModel> _artists;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_mediaCollections = await _mediator.Send(new GetAllCollections())
|
||||
_mediaCollections = await _mediator.Send(new GetAllCollections(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
_multiCollections = await _mediator.Send(new GetAllMultiCollections())
|
||||
_multiCollections = await _mediator.Send(new GetAllMultiCollections(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
_smartCollections = await _mediator.Send(new GetAllSmartCollections())
|
||||
_smartCollections = await _mediator.Send(new GetAllSmartCollections(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
_televisionShows = await _mediator.Send(new GetAllTelevisionShows())
|
||||
_televisionShows = await _mediator.Send(new GetAllTelevisionShows(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
_televisionSeasons = await _mediator.Send(new GetAllTelevisionSeasons())
|
||||
_televisionSeasons = await _mediator.Send(new GetAllTelevisionSeasons(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
_artists = await _mediator.Send(new GetAllArtists())
|
||||
_artists = await _mediator.Send(new GetAllArtists(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
|
||||
if (IsEdit)
|
||||
{
|
||||
Option<FillerPresetViewModel> maybeFillerPreset = await _mediator.Send(new GetFillerPresetById(Id));
|
||||
Option<FillerPresetViewModel> maybeFillerPreset = await _mediator.Send(new GetFillerPresetById(Id), _cts.Token);
|
||||
maybeFillerPreset.IfSome(fillerPreset =>
|
||||
{
|
||||
_model.Id = fillerPreset.Id;
|
||||
@@ -212,7 +222,7 @@
|
||||
{
|
||||
IRequest<Either<BaseError, LanguageExt.Unit>> request = IsEdit ? _model.ToEdit() : _model.ToUpdate();
|
||||
|
||||
Seq<BaseError> errorMessage = await _mediator.Send(request)
|
||||
Seq<BaseError> errorMessage = await _mediator.Send(request, _cts.Token)
|
||||
.Map(result => result.LeftToSeq());
|
||||
|
||||
errorMessage.HeadOrNone().Match(
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
@using ErsatzTV.Application.Filler.Commands
|
||||
@using ErsatzTV.Application.Filler.Queries
|
||||
@using ErsatzTV.Core.Domain.Filler
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IDialogService _dialog
|
||||
@inject IMediator _mediator
|
||||
|
||||
@@ -69,13 +71,21 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private MudTable<FillerPresetViewModel> _fillerPresetsTable;
|
||||
|
||||
private int _fillerPresetsRowsPerPage;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_fillerPresetsRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.FillerPresetsPageSize))
|
||||
_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));
|
||||
}
|
||||
|
||||
@@ -88,16 +98,17 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await _mediator.Send(new DeleteFillerPreset(fillerPreset.Id));
|
||||
await _mediator.Send(new DeleteFillerPreset(fillerPreset.Id), _cts.Token);
|
||||
await _fillerPresetsTable.ReloadServerData();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<TableData<FillerPresetViewModel>> ServerReloadFillerPresets(TableState state)
|
||||
{
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.FillerPresetsPageSize, state.PageSize.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.FillerPresetsPageSize, state.PageSize.ToString()), _cts.Token);
|
||||
|
||||
PagedFillerPresetsViewModel data = await _mediator.Send(new GetPagedFillerPresets(state.Page, state.PageSize));
|
||||
PagedFillerPresetsViewModel data = await _mediator.Send(new GetPagedFillerPresets(state.Page, state.PageSize), _cts.Token);
|
||||
return new TableData<FillerPresetViewModel> { TotalItems = data.TotalCount, Items = data.Page };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ErsatzTV.Extensions;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@@ -10,13 +11,23 @@ namespace ErsatzTV.Pages
|
||||
{
|
||||
public class FragmentNavigationBase : ComponentBase, IDisposable
|
||||
{
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
protected CancellationToken CancellationToken => _cts.Token;
|
||||
|
||||
[Inject]
|
||||
private NavigationManager NavManager { get; set; }
|
||||
|
||||
[Inject]
|
||||
private IJSRuntime JsRuntime { get; set; }
|
||||
|
||||
public void Dispose() => NavManager.LocationChanged -= TryFragmentNavigation;
|
||||
public void Dispose()
|
||||
{
|
||||
NavManager.LocationChanged -= TryFragmentNavigation;
|
||||
|
||||
_cts?.Cancel();
|
||||
_cts?.Dispose();
|
||||
}
|
||||
|
||||
protected override void OnInitialized() => NavManager.LocationChanged += TryFragmentNavigation;
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
@page "/"
|
||||
@using Microsoft.Extensions.Caching.Memory
|
||||
@using System.Reflection
|
||||
@using System.Threading
|
||||
@using ErsatzTV.Application.Health.Queries
|
||||
@using ErsatzTV.Core.Health
|
||||
@using ErsatzTV.Core.Interfaces.GitHub
|
||||
@implements IDisposable
|
||||
@inject IGitHubApiClient _gitHubApiClient
|
||||
@inject IMemoryCache _memoryCache
|
||||
@inject IMediator _mediator
|
||||
@@ -71,9 +73,16 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private string _releaseNotes;
|
||||
private MudTable<HealthCheckResult> _table;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
@@ -101,12 +110,12 @@
|
||||
gitHubVersion = $"v{gitHubVersion}";
|
||||
}
|
||||
|
||||
maybeNotes = await _gitHubApiClient.GetReleaseNotes(gitHubVersion);
|
||||
maybeNotes = await _gitHubApiClient.GetReleaseNotes(gitHubVersion, _cts.Token);
|
||||
maybeNotes.IfRight(notes => _releaseNotes = notes);
|
||||
}
|
||||
else
|
||||
{
|
||||
maybeNotes = await _gitHubApiClient.GetLatestReleaseNotes();
|
||||
maybeNotes = await _gitHubApiClient.GetLatestReleaseNotes(_cts.Token);
|
||||
maybeNotes.IfRight(notes => _releaseNotes = notes);
|
||||
}
|
||||
}
|
||||
@@ -126,7 +135,7 @@
|
||||
|
||||
private async Task<TableData<HealthCheckResult>> ServerReload(TableState state)
|
||||
{
|
||||
List<HealthCheckResult> healthCheckResults = await _mediator.Send(new GetAllHealthCheckResults());
|
||||
List<HealthCheckResult> healthCheckResults = await _mediator.Send(new GetAllHealthCheckResults(), _cts.Token);
|
||||
|
||||
return new TableData<HealthCheckResult>
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
@using ErsatzTV.Application.Jellyfin.Queries
|
||||
@using ErsatzTV.Application.MediaSources
|
||||
@using ErsatzTV.Application.Jellyfin
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
@inject ChannelWriter<IJellyfinBackgroundServiceRequest> _channel
|
||||
|
||||
@@ -16,20 +18,27 @@
|
||||
SynchronizeLibraryByIdIfNeeded="SynchronizeLibraryByIdIfNeeded"/>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
private IRequest<Either<BaseError, Unit>> GetUpdateLibraryRequest(List<RemoteMediaSourceLibraryEditViewModel> libraries) =>
|
||||
new UpdateJellyfinLibraryPreferences(
|
||||
libraries.Map(l => new JellyfinLibraryPreference(l.Id, l.ShouldSyncItems)).ToList());
|
||||
|
||||
private Task<List<RemoteMediaSourceLibraryEditViewModel>> GetLibrariesBySourceId(int mediaSourceId) =>
|
||||
_mediator.Send(new GetJellyfinLibrariesBySourceId(Id))
|
||||
private async Task<List<RemoteMediaSourceLibraryEditViewModel>> GetLibrariesBySourceId(int mediaSourceId) =>
|
||||
await _mediator.Send(new GetJellyfinLibrariesBySourceId(Id), _cts.Token)
|
||||
.Map(list => list.Map(ProjectToEditViewModel).OrderBy(x => x.MediaKind).ThenBy(x => x.Name).ToList());
|
||||
|
||||
private Task<Option<RemoteMediaSourceViewModel>> GetMediaSourceById(int mediaSourceId) =>
|
||||
_mediator.Send(new GetJellyfinMediaSourceById(Id))
|
||||
private async Task<Option<RemoteMediaSourceViewModel>> GetMediaSourceById(int mediaSourceId) =>
|
||||
await _mediator.Send(new GetJellyfinMediaSourceById(Id), _cts.Token)
|
||||
.MapT(vm => new RemoteMediaSourceViewModel(vm.Id, vm.Name, vm.Address));
|
||||
|
||||
private RemoteMediaSourceLibraryEditViewModel ProjectToEditViewModel(JellyfinLibraryViewModel library) => new()
|
||||
@@ -42,7 +51,7 @@
|
||||
|
||||
private async Task<Unit> SynchronizeLibraryByIdIfNeeded(int libraryId)
|
||||
{
|
||||
await _channel.WriteAsync(new SynchronizeJellyfinLibraryByIdIfNeeded(libraryId));
|
||||
await _channel.WriteAsync(new SynchronizeJellyfinLibraryByIdIfNeeded(libraryId), _cts.Token);
|
||||
return Unit.Default;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
@using ErsatzTV.Core.Jellyfin
|
||||
@using ErsatzTV.Application.Jellyfin.Queries
|
||||
@using ErsatzTV.Application.Jellyfin.Commands
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -14,10 +16,17 @@
|
||||
SaveSecrets="SaveSecrets"/>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
private async Task<Unit> LoadSecrets(RemoteMediaSourceEditViewModel viewModel)
|
||||
{
|
||||
JellyfinSecrets secrets = await _mediator.Send(new GetJellyfinSecrets());
|
||||
JellyfinSecrets secrets = await _mediator.Send(new GetJellyfinSecrets(), _cts.Token);
|
||||
viewModel.Address = secrets.Address;
|
||||
viewModel.ApiKey = secrets.ApiKey;
|
||||
return Unit.Default;
|
||||
@@ -26,7 +35,7 @@
|
||||
private async Task<Either<BaseError, Unit>> SaveSecrets(RemoteMediaSourceEditViewModel viewModel)
|
||||
{
|
||||
var secrets = new JellyfinSecrets { Address = viewModel.Address, ApiKey = viewModel.ApiKey };
|
||||
return await _mediator.Send(new SaveJellyfinSecrets(secrets));
|
||||
return await _mediator.Send(new SaveJellyfinSecrets(secrets), _cts.Token);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
@using ErsatzTV.Core.Interfaces.Jellyfin
|
||||
@using ErsatzTV.Application.Jellyfin.Commands
|
||||
@using ErsatzTV.Application.Jellyfin.Queries
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IJellyfinSecretStore _jellyfinSecretStore
|
||||
@inject ChannelWriter<IJellyfinBackgroundServiceRequest> _channel
|
||||
|
||||
@@ -16,8 +18,15 @@
|
||||
SecretStore="@_jellyfinSecretStore"/>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
private async Task RefreshLibraries(int mediaSourceId) =>
|
||||
await _channel.WriteAsync(new SynchronizeJellyfinLibraries(mediaSourceId));
|
||||
await _channel.WriteAsync(new SynchronizeJellyfinLibraries(mediaSourceId), _cts.Token);
|
||||
|
||||
}
|
||||
@@ -4,6 +4,8 @@
|
||||
@using ErsatzTV.Application.Jellyfin
|
||||
@using ErsatzTV.Application.Jellyfin.Commands
|
||||
@using Unit = LanguageExt.Unit
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<ScheduleItemsEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -17,16 +19,23 @@
|
||||
GetPathReplacementsBySourceId="GetPathReplacementsBySourceId"/>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
private Task<Option<RemoteMediaSourceViewModel>> GetMediaSourceById(int id) =>
|
||||
_mediator.Send(new GetJellyfinMediaSourceById(Id))
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
private async Task<Option<RemoteMediaSourceViewModel>> GetMediaSourceById(int id) =>
|
||||
await _mediator.Send(new GetJellyfinMediaSourceById(Id), _cts.Token)
|
||||
.MapT(vm => new RemoteMediaSourceViewModel(vm.Id, vm.Name, vm.Address));
|
||||
|
||||
private Task<List<RemoteMediaSourcePathReplacementEditViewModel>> GetPathReplacementsBySourceId(int mediaSourceId) =>
|
||||
_mediator.Send(new GetJellyfinPathReplacementsBySourceId(Id))
|
||||
private async Task<List<RemoteMediaSourcePathReplacementEditViewModel>> GetPathReplacementsBySourceId(int mediaSourceId) =>
|
||||
await _mediator.Send(new GetJellyfinPathReplacementsBySourceId(Id), _cts.Token)
|
||||
.Map(list => list.Map(ProjectToEditViewModel).ToList());
|
||||
|
||||
private RemoteMediaSourcePathReplacementEditViewModel ProjectToEditViewModel(JellyfinPathReplacementViewModel item) =>
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private IList<LibraryViewModel> _libraries;
|
||||
private Dictionary<int, int> _progressByLibrary;
|
||||
|
||||
@@ -87,11 +89,11 @@
|
||||
_courier.Subscribe<LibraryScanProgress>(HandleScanProgress);
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync() => await LoadLibraries();
|
||||
protected override async Task OnParametersSetAsync() => await LoadLibraries(_cts.Token);
|
||||
|
||||
private async Task LoadLibraries()
|
||||
private async Task LoadLibraries(CancellationToken cancellationToken)
|
||||
{
|
||||
_libraries = await _mediator.Send(new GetConfiguredLibraries());
|
||||
_libraries = await _mediator.Send(new GetConfiguredLibraries(), cancellationToken);
|
||||
_progressByLibrary = _libraries.ToDictionary(vm => vm.Id, _ => 0);
|
||||
}
|
||||
|
||||
@@ -102,16 +104,16 @@
|
||||
switch (library)
|
||||
{
|
||||
case LocalLibraryViewModel:
|
||||
await _workerChannel.WriteAsync(new ForceScanLocalLibrary(library.Id));
|
||||
await _workerChannel.WriteAsync(new ForceScanLocalLibrary(library.Id), _cts.Token);
|
||||
break;
|
||||
case PlexLibraryViewModel:
|
||||
await _plexWorkerChannel.WriteAsync(new ForceSynchronizePlexLibraryById(library.Id));
|
||||
await _plexWorkerChannel.WriteAsync(new ForceSynchronizePlexLibraryById(library.Id), _cts.Token);
|
||||
break;
|
||||
case JellyfinLibraryViewModel:
|
||||
await _jellyfinWorkerChannel.WriteAsync(new ForceSynchronizeJellyfinLibraryById(library.Id));
|
||||
await _jellyfinWorkerChannel.WriteAsync(new ForceSynchronizeJellyfinLibraryById(library.Id), _cts.Token);
|
||||
break;
|
||||
case EmbyLibraryViewModel:
|
||||
await _embyWorkerChannel.WriteAsync(new ForceSynchronizeEmbyLibraryById(library.Id));
|
||||
await _embyWorkerChannel.WriteAsync(new ForceSynchronizeEmbyLibraryById(library.Id), _cts.Token);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -142,6 +144,9 @@
|
||||
{
|
||||
_locker.OnLibraryChanged -= LockChanged;
|
||||
_courier.UnSubscribe<LibraryScanProgress>(HandleScanProgress);
|
||||
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
@using ErsatzTV.Application.Libraries
|
||||
@using ErsatzTV.Application.Libraries.Commands
|
||||
@using ErsatzTV.Application.Libraries.Queries
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IDialogService _dialog
|
||||
@inject IMediator _mediator
|
||||
@@ -53,6 +54,8 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private IList<LocalLibraryViewModel> _libraries;
|
||||
|
||||
protected override void OnInitialized()
|
||||
@@ -60,11 +63,11 @@
|
||||
_locker.OnLibraryChanged += LockChanged;
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync() => await LoadLibraries();
|
||||
protected override async Task OnParametersSetAsync() => await LoadLibraries(_cts.Token);
|
||||
|
||||
private async Task LoadLibraries()
|
||||
private async Task LoadLibraries(CancellationToken cancellationToken)
|
||||
{
|
||||
_libraries = await _mediator.Send(new GetAllLocalLibraries());
|
||||
_libraries = await _mediator.Send(new GetAllLocalLibraries(), cancellationToken);
|
||||
}
|
||||
|
||||
private void LockChanged(object sender, EventArgs e) =>
|
||||
@@ -72,7 +75,7 @@
|
||||
|
||||
private async Task DeleteLibrary(LocalLibraryViewModel library)
|
||||
{
|
||||
int count = await _mediator.Send(new CountMediaItemsByLibrary(library.Id));
|
||||
int count = await _mediator.Send(new CountMediaItemsByLibrary(library.Id), _cts.Token);
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
{ "EntityType", "library" },
|
||||
@@ -86,14 +89,17 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await _mediator.Send(new DeleteLocalLibrary(library.Id));
|
||||
await LoadLibraries();
|
||||
await _mediator.Send(new DeleteLocalLibrary(library.Id), _cts.Token);
|
||||
await LoadLibraries(_cts.Token);
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
_locker.OnLibraryChanged -= LockChanged;
|
||||
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
@using ErsatzTV.Application.Libraries.Commands
|
||||
@using ErsatzTV.Application.Libraries.Queries
|
||||
@using Unit = LanguageExt.Unit
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IDialogService _dialog
|
||||
@inject IEntityLocker _locker
|
||||
@@ -76,6 +77,7 @@
|
||||
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
@@ -91,7 +93,7 @@
|
||||
{
|
||||
if (IsEdit)
|
||||
{
|
||||
Option<LocalLibraryViewModel> maybeLibrary = await _mediator.Send(new GetLocalLibraryById(Id));
|
||||
Option<LocalLibraryViewModel> maybeLibrary = await _mediator.Send(new GetLocalLibraryById(Id), _cts.Token);
|
||||
await maybeLibrary.Match(
|
||||
async library =>
|
||||
{
|
||||
@@ -130,7 +132,7 @@
|
||||
private async Task LoadLibraryPaths()
|
||||
{
|
||||
_model.HasChanges = false;
|
||||
_model.Paths = await _mediator.Send(new GetLocalLibraryPaths(Id))
|
||||
_model.Paths = await _mediator.Send(new GetLocalLibraryPaths(Id), _cts.Token)
|
||||
.Map(list => list.Map(vm => new LocalLibraryPathEditViewModel
|
||||
{
|
||||
Id = vm.Id,
|
||||
@@ -148,7 +150,7 @@
|
||||
if (!result.Cancelled && result.Data is LocalLibraryViewModel library)
|
||||
{
|
||||
var request = new MoveLocalLibraryPath(libraryPath.Id, library.Id);
|
||||
Either<BaseError, Unit> moveResult = await _mediator.Send(request);
|
||||
Either<BaseError, Unit> moveResult = await _mediator.Send(request, _cts.Token);
|
||||
moveResult.Match(
|
||||
_ => _navigationManager.NavigateTo($"/media/sources/local/{library.Id}/edit"),
|
||||
error =>
|
||||
@@ -167,7 +169,7 @@
|
||||
_model.Paths.Remove(libraryPath);
|
||||
}
|
||||
|
||||
int count = await _mediator.Send(new CountMediaItemsByLibraryPath(libraryPath.Id));
|
||||
int count = await _mediator.Send(new CountMediaItemsByLibraryPath(libraryPath.Id), _cts.Token);
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
{ "EntityType", "library path" },
|
||||
@@ -209,11 +211,11 @@
|
||||
? await _mediator.Send(new UpdateLocalLibrary(
|
||||
_model.Id,
|
||||
_model.Name,
|
||||
_model.Paths.Map(p => new UpdateLocalLibraryPath(p.Id, p.Path)).ToList()))
|
||||
_model.Paths.Map(p => new UpdateLocalLibraryPath(p.Id, p.Path)).ToList()), _cts.Token)
|
||||
: await _mediator.Send(new CreateLocalLibrary(
|
||||
_model.Name,
|
||||
_model.MediaKind,
|
||||
_model.Paths.Map(p => p.Path).ToList()));
|
||||
_model.Paths.Map(p => p.Path).ToList()), _cts.Token);
|
||||
|
||||
result.Match(
|
||||
_ => _navigationManager.NavigateTo("/media/sources/local"),
|
||||
@@ -235,6 +237,9 @@
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
_locker.OnLibraryChanged -= LockChanged;
|
||||
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
@using ErsatzTV.Application.Libraries.Commands
|
||||
@using ErsatzTV.Application.Libraries.Queries
|
||||
@using ErsatzTV.Application.MediaSources.Commands
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<LocalLibraryPathEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -32,6 +34,7 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
@@ -41,10 +44,16 @@
|
||||
private ValidationMessageStore _messageStore;
|
||||
|
||||
private LocalLibraryViewModel _library;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
Option<LocalLibraryViewModel> maybeLibrary = await _mediator.Send(new GetLocalLibraryById(Id));
|
||||
Option<LocalLibraryViewModel> maybeLibrary = await _mediator.Send(new GetLocalLibraryById(Id), _cts.Token);
|
||||
maybeLibrary.Match(
|
||||
library => _library = library,
|
||||
() => _navigationManager.NavigateTo("404"));
|
||||
@@ -62,7 +71,7 @@
|
||||
if (_editContext.Validate())
|
||||
{
|
||||
var command = new CreateLocalLibraryPath(_library.Id, _model.Path);
|
||||
Either<BaseError, LocalLibraryPathViewModel> result = await _mediator.Send(command);
|
||||
Either<BaseError, LocalLibraryPathViewModel> result = await _mediator.Send(command, _cts.Token);
|
||||
await result.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -74,7 +83,7 @@
|
||||
{
|
||||
if (_locker.LockLibrary(_library.Id))
|
||||
{
|
||||
await _channel.WriteAsync(new ScanLocalLibraryIfNeeded(_library.Id));
|
||||
await _channel.WriteAsync(new ScanLocalLibraryIfNeeded(_library.Id), _cts.Token);
|
||||
_navigationManager.NavigateTo("/media/libraries");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
@using ErsatzTV.Application.Logs.Queries
|
||||
@using ErsatzTV.Application.Configuration.Queries
|
||||
@using ErsatzTV.Application.Configuration.Commands
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
||||
@@ -36,15 +38,24 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private MudTable<LogEntryViewModel> _table;
|
||||
private int _rowsPerPage;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync() => _rowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.LogsPageSize))
|
||||
protected override async Task OnParametersSetAsync() => _rowsPerPage =
|
||||
await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.LogsPageSize), _cts.Token)
|
||||
.Map(maybeRows => maybeRows.Match(ce => int.TryParse(ce.Value, out int rows) ? rows : 10, () => 10));
|
||||
|
||||
private async Task<TableData<LogEntryViewModel>> ServerReload(TableState state)
|
||||
{
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.LogsPageSize, state.PageSize.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.LogsPageSize, state.PageSize.ToString()), _cts.Token);
|
||||
|
||||
PagedLogEntriesViewModel data;
|
||||
|
||||
@@ -57,7 +68,7 @@
|
||||
SortDescending = state.SortDirection == SortDirection.None
|
||||
? Option<bool>.None
|
||||
: state.SortDirection == SortDirection.Descending
|
||||
});
|
||||
}, _cts.Token);
|
||||
break;
|
||||
case "level":
|
||||
data = await _mediator.Send(new GetRecentLogEntries(state.Page, state.PageSize)
|
||||
@@ -66,13 +77,13 @@
|
||||
SortDescending = state.SortDirection == SortDirection.None
|
||||
? Option<bool>.None
|
||||
: state.SortDirection == SortDirection.Descending
|
||||
});
|
||||
}, _cts.Token);
|
||||
break;
|
||||
default:
|
||||
data = await _mediator.Send(new GetRecentLogEntries(state.Page, state.PageSize)
|
||||
{
|
||||
SortDescending = Option<bool>.None
|
||||
});
|
||||
}, _cts.Token);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
@using ErsatzTV.Application.MediaCollections
|
||||
@using ErsatzTV.Application.MediaCollections.Commands
|
||||
@using ErsatzTV.Extensions
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
@inject IDialogService _dialog
|
||||
@inject NavigationManager _navigationManager
|
||||
@@ -187,6 +189,7 @@
|
||||
}
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int MovieId { get; set; }
|
||||
@@ -200,10 +203,16 @@
|
||||
private List<string> _sortedGenres = new();
|
||||
private List<string> _sortedTags = new();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override Task OnParametersSetAsync() => RefreshData();
|
||||
|
||||
private Task RefreshData() =>
|
||||
_mediator.Send(new GetMovieById(MovieId)).IfSomeAsync(vm =>
|
||||
private async Task RefreshData() =>
|
||||
await _mediator.Send(new GetMovieById(MovieId), _cts.Token).IfSomeAsync(vm =>
|
||||
{
|
||||
_movie = vm;
|
||||
_sortedContentRatings = _movie.ContentRatings.OrderBy(cr => cr).ToList();
|
||||
@@ -224,7 +233,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
await _mediator.Send(new AddMovieToCollection(collection.Id, MovieId));
|
||||
await _mediator.Send(new AddMovieToCollection(collection.Id, MovieId), _cts.Token);
|
||||
_navigationManager.NavigateTo($"/media/collections/{collection.Id}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
@page "/media/movies"
|
||||
@page "/media/movies/page/{PageNumber:int}"
|
||||
@using LanguageExt.UnsafeValueAccess
|
||||
@using Microsoft.AspNetCore.WebUtilities
|
||||
@using ErsatzTV.Application.MediaCards
|
||||
@using ErsatzTV.Application.MediaCollections
|
||||
@using ErsatzTV.Application.MediaCollections.Commands
|
||||
@@ -81,7 +80,7 @@
|
||||
|
||||
private MovieCardResultsViewModel _data;
|
||||
private string _query;
|
||||
|
||||
|
||||
protected override Task OnParametersSetAsync()
|
||||
{
|
||||
if (PageNumber == 0)
|
||||
@@ -96,12 +95,12 @@
|
||||
protected override async Task RefreshData()
|
||||
{
|
||||
string searchQuery = string.IsNullOrWhiteSpace(_query) ? "type:movie" : $"type:movie AND ({_query})";
|
||||
_data = await Mediator.Send(new QuerySearchIndexMovies(searchQuery, PageNumber, PageSize));
|
||||
_data = await Mediator.Send(new QuerySearchIndexMovies(searchQuery, PageNumber, PageSize), CancellationToken);
|
||||
}
|
||||
|
||||
private void PrevPage()
|
||||
{
|
||||
var uri = $"/media/movies/page/{PageNumber - 1}";
|
||||
string uri = $"/media/movies/page/{PageNumber - 1}";
|
||||
if (!string.IsNullOrWhiteSpace(_query))
|
||||
{
|
||||
(string key, string value) = _query.EncodeQuery();
|
||||
@@ -112,7 +111,7 @@
|
||||
|
||||
private void NextPage()
|
||||
{
|
||||
var uri = $"/media/movies/page/{PageNumber + 1}";
|
||||
string uri = $"/media/movies/page/{PageNumber + 1}";
|
||||
if (!string.IsNullOrWhiteSpace(_query))
|
||||
{
|
||||
(string key, string value) = _query.EncodeQuery();
|
||||
@@ -143,7 +142,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddMovieToCollection(collection.Id, movie.MovieId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
@using ErsatzTV.Application.MediaCollections
|
||||
@using ErsatzTV.Application.MediaCollections.Commands
|
||||
@using ErsatzTV.Application.MediaCollections.Queries
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -104,6 +106,8 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
@@ -117,17 +121,23 @@
|
||||
private MudSelect<MediaCollectionViewModel> _collectionSelect;
|
||||
private MudSelect<SmartCollectionViewModel> _smartCollectionSelect;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_collections = await _mediator.Send(new GetAllCollections())
|
||||
_collections = await _mediator.Send(new GetAllCollections(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
|
||||
_smartCollections = await _mediator.Send(new GetAllSmartCollections())
|
||||
_smartCollections = await _mediator.Send(new GetAllSmartCollections(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
|
||||
if (IsEdit)
|
||||
{
|
||||
Option<MultiCollectionViewModel> maybeCollection = await _mediator.Send(new GetMultiCollectionById(Id));
|
||||
Option<MultiCollectionViewModel> maybeCollection = await _mediator.Send(new GetMultiCollectionById(Id), _cts.Token);
|
||||
maybeCollection.IfSome(collection =>
|
||||
{
|
||||
_model.Id = collection.Id;
|
||||
@@ -170,8 +180,8 @@
|
||||
if (_editContext.Validate())
|
||||
{
|
||||
Seq<BaseError> errorMessage = IsEdit ?
|
||||
(await _mediator.Send(new UpdateMultiCollection(Id, _model.Name, GetUpdateItems()))).LeftToSeq() :
|
||||
(await _mediator.Send(new CreateMultiCollection(_model.Name, GetCreateItems()))).LeftToSeq();
|
||||
(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 =>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ErsatzTV.Application.MediaCards;
|
||||
using ErsatzTV.Application.MediaCollections;
|
||||
@@ -137,7 +138,7 @@ namespace ErsatzTV.Pages
|
||||
otherVideoIds,
|
||||
songIds);
|
||||
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -173,7 +174,8 @@ namespace ErsatzTV.Pages
|
||||
new RemoveItemsFromCollection(collectionId)
|
||||
{
|
||||
MediaItemIds = itemIds
|
||||
});
|
||||
},
|
||||
CancellationToken);
|
||||
|
||||
await RefreshData();
|
||||
ClearSelection();
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
protected override async Task RefreshData()
|
||||
{
|
||||
string searchQuery = string.IsNullOrWhiteSpace(_query) ? "type:music_video" : $"type:music_video AND ({_query})";
|
||||
_data = await Mediator.Send(new QuerySearchIndexMusicVideos(searchQuery, PageNumber, PageSize));
|
||||
_data = await Mediator.Send(new QuerySearchIndexMusicVideos(searchQuery, PageNumber, PageSize), CancellationToken);
|
||||
}
|
||||
|
||||
private void PrevPage()
|
||||
@@ -144,7 +144,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddMusicVideoToCollection(collection.Id, musicVideo.MusicVideoId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
protected override async Task RefreshData()
|
||||
{
|
||||
string searchQuery = string.IsNullOrWhiteSpace(_query) ? "type:other_video" : $"type:other_video AND ({_query})";
|
||||
_data = await Mediator.Send(new QuerySearchIndexOtherVideos(searchQuery, PageNumber, PageSize));
|
||||
_data = await Mediator.Send(new QuerySearchIndexOtherVideos(searchQuery, PageNumber, PageSize), CancellationToken);
|
||||
}
|
||||
|
||||
private void PrevPage()
|
||||
@@ -143,7 +143,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddOtherVideoToCollection(collection.Id, otherVideo.OtherVideoId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
@using ErsatzTV.Application.Channels.Queries
|
||||
@using ErsatzTV.Application.ProgramSchedules
|
||||
@using ErsatzTV.Application.ProgramSchedules.Queries
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<PlayoutEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -48,6 +50,7 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private readonly PlayoutEditViewModel _model = new();
|
||||
private List<ChannelViewModel> _channels;
|
||||
@@ -55,12 +58,18 @@
|
||||
|
||||
private EditContext _editContext;
|
||||
private ValidationMessageStore _messageStore;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_channels = await _mediator.Send(new GetAllChannels())
|
||||
_channels = await _mediator.Send(new GetAllChannels(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => decimal.Parse(vm.Number)).ToList());
|
||||
_programSchedules = await _mediator.Send(new GetAllProgramSchedules())
|
||||
_programSchedules = await _mediator.Send(new GetAllProgramSchedules(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name).ToList());
|
||||
}
|
||||
|
||||
@@ -75,7 +84,7 @@
|
||||
_messageStore.Clear();
|
||||
if (_editContext.Validate())
|
||||
{
|
||||
Seq<BaseError> errorMessage = (await _mediator.Send(_model.ToCreate())).LeftToSeq();
|
||||
Seq<BaseError> errorMessage = (await _mediator.Send(_model.ToCreate(), _cts.Token)).LeftToSeq();
|
||||
|
||||
errorMessage.HeadOrNone().Match(
|
||||
error =>
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
@using ErsatzTV.Application.Playouts.Queries
|
||||
@using ErsatzTV.Application.Configuration.Commands
|
||||
@using ErsatzTV.Application.Configuration.Queries
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IDialogService _dialog
|
||||
@inject IMediator _mediator
|
||||
|
||||
@@ -99,6 +101,8 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private MudTable<PlayoutNameViewModel> _table;
|
||||
private MudTable<PlayoutItemViewModel> _detailTable;
|
||||
private int _rowsPerPage;
|
||||
@@ -118,14 +122,20 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_rowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.PlayoutsPageSize))
|
||||
_rowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.PlayoutsPageSize), _cts.Token)
|
||||
.Map(maybeRows => maybeRows.Match(ce => int.TryParse(ce.Value, out int rows) ? rows : 10, () => 10));
|
||||
_detailRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.PlayoutsDetailPageSize))
|
||||
_detailRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.PlayoutsDetailPageSize), _cts.Token)
|
||||
.Map(maybeRows => maybeRows.Match(ce => int.TryParse(ce.Value, out int rows) ? rows : 10, () => 10));
|
||||
_showFiller = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.PlayoutsDetailShowFiller))
|
||||
_showFiller = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.PlayoutsDetailShowFiller), _cts.Token)
|
||||
.Map(maybeShow => maybeShow.Match(ce => bool.TryParse(ce.Value, out bool show) && show, () => false));
|
||||
}
|
||||
|
||||
@@ -152,7 +162,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await _mediator.Send(new DeletePlayout(playout.PlayoutId));
|
||||
await _mediator.Send(new DeletePlayout(playout.PlayoutId), _cts.Token);
|
||||
await _table.ReloadServerData();
|
||||
if (_selectedPlayoutId == playout.PlayoutId)
|
||||
{
|
||||
@@ -163,7 +173,7 @@
|
||||
|
||||
private async Task RebuildPlayout(PlayoutNameViewModel playout)
|
||||
{
|
||||
await _mediator.Send(new BuildPlayout(playout.PlayoutId, true));
|
||||
await _mediator.Send(new BuildPlayout(playout.PlayoutId, true), _cts.Token);
|
||||
await _table.ReloadServerData();
|
||||
if (_selectedPlayoutId == playout.PlayoutId)
|
||||
{
|
||||
@@ -188,9 +198,9 @@
|
||||
|
||||
private async Task<TableData<PlayoutNameViewModel>> ServerReload(TableState state)
|
||||
{
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.PlayoutsPageSize, state.PageSize.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.PlayoutsPageSize, state.PageSize.ToString()), _cts.Token);
|
||||
|
||||
List<PlayoutNameViewModel> playouts = await _mediator.Send(new GetAllPlayouts());
|
||||
List<PlayoutNameViewModel> playouts = await _mediator.Send(new GetAllPlayouts(), _cts.Token);
|
||||
IOrderedEnumerable<PlayoutNameViewModel> sorted = playouts.OrderBy(p => decimal.Parse(p.ChannelNumber));
|
||||
|
||||
// TODO: properly page this data
|
||||
@@ -203,13 +213,13 @@
|
||||
|
||||
private async Task<TableData<PlayoutItemViewModel>> DetailServerReload(TableState state)
|
||||
{
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.PlayoutsDetailPageSize, state.PageSize.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.PlayoutsDetailShowFiller, _showFiller.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.PlayoutsDetailPageSize, state.PageSize.ToString()), _cts.Token);
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.PlayoutsDetailShowFiller, _showFiller.ToString()), _cts.Token);
|
||||
|
||||
if (_selectedPlayoutId.HasValue)
|
||||
{
|
||||
PagedPlayoutItemsViewModel data =
|
||||
await _mediator.Send(new GetFuturePlayoutItemsById(_selectedPlayoutId.Value, _showFiller, state.Page, state.PageSize));
|
||||
await _mediator.Send(new GetFuturePlayoutItemsById(_selectedPlayoutId.Value, _showFiller, state.Page, state.PageSize), _cts.Token);
|
||||
return new TableData<PlayoutItemViewModel>
|
||||
{
|
||||
TotalItems = data.TotalCount,
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
@using ErsatzTV.Application.Plex.Queries
|
||||
@using ErsatzTV.Application.MediaSources
|
||||
@using ErsatzTV.Application.Plex
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
@inject ChannelWriter<IPlexBackgroundServiceRequest> _channel
|
||||
|
||||
@@ -16,6 +18,7 @@
|
||||
SynchronizeLibraryByIdIfNeeded="SynchronizeLibraryByIdIfNeeded"/>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
@@ -24,14 +27,20 @@
|
||||
new UpdatePlexLibraryPreferences(
|
||||
libraries.Map(l => new PlexLibraryPreference(l.Id, l.ShouldSyncItems)).ToList());
|
||||
|
||||
private Task<List<RemoteMediaSourceLibraryEditViewModel>> GetLibrariesBySourceId(int mediaSourceId) =>
|
||||
_mediator.Send(new GetPlexLibrariesBySourceId(Id))
|
||||
private async Task<List<RemoteMediaSourceLibraryEditViewModel>> GetLibrariesBySourceId(int mediaSourceId) =>
|
||||
await _mediator.Send(new GetPlexLibrariesBySourceId(Id), _cts.Token)
|
||||
.Map(list => list.Map(ProjectToEditViewModel).OrderBy(x => x.MediaKind).ThenBy(x => x.Name).ToList());
|
||||
|
||||
private Task<Option<RemoteMediaSourceViewModel>> GetMediaSourceById(int mediaSourceId) =>
|
||||
_mediator.Send(new GetPlexMediaSourceById(Id))
|
||||
private async Task<Option<RemoteMediaSourceViewModel>> GetMediaSourceById(int mediaSourceId) =>
|
||||
await _mediator.Send(new GetPlexMediaSourceById(Id), _cts.Token)
|
||||
.MapT(vm => new RemoteMediaSourceViewModel(vm.Id, vm.Name, vm.Address));
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
private RemoteMediaSourceLibraryEditViewModel ProjectToEditViewModel(PlexLibraryViewModel library) => new()
|
||||
{
|
||||
Id = library.Id,
|
||||
@@ -42,7 +51,7 @@
|
||||
|
||||
private async Task<Unit> SynchronizeLibraryByIdIfNeeded(int libraryId)
|
||||
{
|
||||
await _channel.WriteAsync(new SynchronizePlexLibraryByIdIfNeeded(libraryId));
|
||||
await _channel.WriteAsync(new SynchronizePlexLibraryByIdIfNeeded(libraryId), _cts.Token);
|
||||
return Unit.Default;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
@using ErsatzTV.Application.Plex
|
||||
@using ErsatzTV.Application.Plex.Commands
|
||||
@using ErsatzTV.Application.Plex.Queries
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IDialogService _dialog
|
||||
@inject IMediator _mediator
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
@using ErsatzTV.Application.Plex.Commands
|
||||
@using ErsatzTV.Application.Plex.Queries
|
||||
@using Unit = LanguageExt.Unit
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<ScheduleItemsEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -17,16 +19,23 @@
|
||||
GetPathReplacementsBySourceId="GetPathReplacementsBySourceId"/>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
private Task<Option<RemoteMediaSourceViewModel>> GetMediaSourceById(int id) =>
|
||||
_mediator.Send(new GetPlexMediaSourceById(Id))
|
||||
private async Task<Option<RemoteMediaSourceViewModel>> GetMediaSourceById(int id) =>
|
||||
await _mediator.Send(new GetPlexMediaSourceById(Id), _cts.Token)
|
||||
.MapT(vm => new RemoteMediaSourceViewModel(vm.Id, vm.Name, vm.Address));
|
||||
|
||||
private Task<List<RemoteMediaSourcePathReplacementEditViewModel>> GetPathReplacementsBySourceId(int mediaSourceId) =>
|
||||
_mediator.Send(new GetPlexPathReplacementsBySourceId(Id))
|
||||
private async Task<List<RemoteMediaSourcePathReplacementEditViewModel>> GetPathReplacementsBySourceId(int mediaSourceId) =>
|
||||
await _mediator.Send(new GetPlexPathReplacementsBySourceId(Id), _cts.Token)
|
||||
.Map(list => list.Map(ProjectToEditViewModel).ToList());
|
||||
|
||||
private RemoteMediaSourcePathReplacementEditViewModel ProjectToEditViewModel(PlexPathReplacementViewModel item) =>
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
@page "/schedules/add"
|
||||
@using ErsatzTV.Application.ProgramSchedules
|
||||
@using ErsatzTV.Application.ProgramSchedules.Queries
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<ScheduleEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -50,6 +52,7 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
@@ -57,12 +60,18 @@
|
||||
private readonly ProgramScheduleEditViewModel _model = new();
|
||||
private EditContext _editContext;
|
||||
private ValidationMessageStore _messageStore;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (IsEdit)
|
||||
{
|
||||
Option<ProgramScheduleViewModel> maybeProgramSchedule = await _mediator.Send(new GetProgramScheduleById(Id));
|
||||
Option<ProgramScheduleViewModel> maybeProgramSchedule = await _mediator.Send(new GetProgramScheduleById(Id), _cts.Token);
|
||||
maybeProgramSchedule.Match(
|
||||
viewModel =>
|
||||
{
|
||||
@@ -93,9 +102,9 @@
|
||||
_messageStore.Clear();
|
||||
if (_editContext.Validate())
|
||||
{
|
||||
Either<BaseError, EntityIdResult> result = IsEdit ?
|
||||
await _mediator.Send(_model.ToUpdate()).MapT(r => r as EntityIdResult) :
|
||||
await _mediator.Send(_model.ToCreate()).MapT(r => r as EntityIdResult);
|
||||
Either<BaseError, EntityIdResult> result = IsEdit
|
||||
? await _mediator.Send(_model.ToUpdate(), _cts.Token).MapT(r => r as EntityIdResult)
|
||||
: await _mediator.Send(_model.ToCreate(), _cts.Token).MapT(r => r as EntityIdResult);
|
||||
|
||||
result.Match(
|
||||
programSchedule =>
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
@using ErsatzTV.Application.Filler
|
||||
@using ErsatzTV.Application.Filler.Queries
|
||||
@using ErsatzTV.Core.Domain.Filler
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<ScheduleItemsEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -289,6 +291,7 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
@@ -303,37 +306,43 @@
|
||||
private List<FillerPresetViewModel> _fillerPresets;
|
||||
|
||||
private ProgramScheduleItemEditViewModel _selectedItem;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override Task OnParametersSetAsync() => LoadScheduleItems();
|
||||
|
||||
private async Task LoadScheduleItems()
|
||||
{
|
||||
// TODO: fix performance
|
||||
_mediaCollections = await _mediator.Send(new GetAllCollections())
|
||||
_mediaCollections = await _mediator.Send(new GetAllCollections(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
_multiCollections = await _mediator.Send(new GetAllMultiCollections())
|
||||
_multiCollections = await _mediator.Send(new GetAllMultiCollections(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
_smartCollections = await _mediator.Send(new GetAllSmartCollections())
|
||||
_smartCollections = await _mediator.Send(new GetAllSmartCollections(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
_televisionShows = await _mediator.Send(new GetAllTelevisionShows())
|
||||
_televisionShows = await _mediator.Send(new GetAllTelevisionShows(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
_televisionSeasons = await _mediator.Send(new GetAllTelevisionSeasons())
|
||||
_televisionSeasons = await _mediator.Send(new GetAllTelevisionSeasons(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
_artists = await _mediator.Send(new GetAllArtists())
|
||||
_artists = await _mediator.Send(new GetAllArtists(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
_fillerPresets = await _mediator.Send(new GetAllFillerPresets())
|
||||
_fillerPresets = await _mediator.Send(new GetAllFillerPresets(), _cts.Token)
|
||||
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
||||
|
||||
string name = string.Empty;
|
||||
var shuffleScheduleItems = false;
|
||||
Option<ProgramScheduleViewModel> maybeSchedule = await _mediator.Send(new GetProgramScheduleById(Id));
|
||||
Option<ProgramScheduleViewModel> maybeSchedule = await _mediator.Send(new GetProgramScheduleById(Id), _cts.Token);
|
||||
foreach (ProgramScheduleViewModel schedule in maybeSchedule)
|
||||
{
|
||||
name = schedule.Name;
|
||||
shuffleScheduleItems = schedule.ShuffleScheduleItems;
|
||||
}
|
||||
|
||||
Option<IEnumerable<ProgramScheduleItemViewModel>> maybeResults = await _mediator.Send(new GetProgramScheduleItems(Id));
|
||||
Option<IEnumerable<ProgramScheduleItemViewModel>> maybeResults = await _mediator.Send(new GetProgramScheduleItems(Id), _cts.Token);
|
||||
foreach (IEnumerable<ProgramScheduleItemViewModel> items in maybeResults)
|
||||
{
|
||||
_schedule = new ProgramScheduleItemsEditViewModel
|
||||
@@ -450,7 +459,7 @@
|
||||
item.TailFiller?.Id,
|
||||
item.FallbackFiller?.Id)).ToList();
|
||||
|
||||
Seq<BaseError> errorMessages = await _mediator.Send(new ReplaceProgramScheduleItems(Id, items)).Map(e => e.LeftToSeq());
|
||||
Seq<BaseError> errorMessages = await _mediator.Send(new ReplaceProgramScheduleItems(Id, items), _cts.Token).Map(e => e.LeftToSeq());
|
||||
|
||||
errorMessages.HeadOrNone().Match(
|
||||
error =>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
@using ErsatzTV.Application.Configuration.Queries
|
||||
@using ErsatzTV.Application.Configuration.Commands
|
||||
@using NaturalSort.Extension
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IDialogService _dialog
|
||||
@inject IMediator _mediator
|
||||
|
||||
@@ -90,17 +92,25 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private MudTable<ProgramScheduleViewModel> _table;
|
||||
private MudTable<ProgramScheduleItemViewModel> _detailTable;
|
||||
private int _rowsPerPage;
|
||||
private int _detailRowsPerPage;
|
||||
private ProgramScheduleViewModel _selectedSchedule;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_rowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.SchedulesPageSize))
|
||||
_rowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.SchedulesPageSize), _cts.Token)
|
||||
.Map(maybeRows => maybeRows.Match(ce => int.TryParse(ce.Value, out int rows) ? rows : 10, () => 10));
|
||||
_detailRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.SchedulesDetailPageSize))
|
||||
_detailRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.SchedulesDetailPageSize), _cts.Token)
|
||||
.Map(maybeRows => maybeRows.Match(ce => int.TryParse(ce.Value, out int rows) ? rows : 10, () => 10));
|
||||
}
|
||||
|
||||
@@ -119,7 +129,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await _mediator.Send(new DeleteProgramSchedule(programSchedule.Id));
|
||||
await _mediator.Send(new DeleteProgramSchedule(programSchedule.Id), _cts.Token);
|
||||
await _table.ReloadServerData();
|
||||
if (_selectedSchedule == programSchedule)
|
||||
{
|
||||
@@ -130,9 +140,9 @@
|
||||
|
||||
private async Task<TableData<ProgramScheduleViewModel>> ServerReload(TableState state)
|
||||
{
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.SchedulesPageSize, state.PageSize.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.SchedulesPageSize, state.PageSize.ToString()), _cts.Token);
|
||||
|
||||
List<ProgramScheduleViewModel> schedules = await _mediator.Send(new GetAllProgramSchedules());
|
||||
List<ProgramScheduleViewModel> schedules = await _mediator.Send(new GetAllProgramSchedules(), _cts.Token);
|
||||
IOrderedEnumerable<ProgramScheduleViewModel> sorted = schedules.OrderBy(s => s.Name, new NaturalSortComparer(StringComparison.CurrentCultureIgnoreCase));
|
||||
|
||||
// TODO: properly page this data
|
||||
@@ -145,9 +155,9 @@
|
||||
|
||||
private async Task<TableData<ProgramScheduleItemViewModel>> DetailServerReload(TableState state)
|
||||
{
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.SchedulesDetailPageSize, state.PageSize.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.SchedulesDetailPageSize, state.PageSize.ToString()), _cts.Token);
|
||||
|
||||
List<ProgramScheduleItemViewModel> scheduleItems = await _mediator.Send(new GetProgramScheduleItems(_selectedSchedule.Id));
|
||||
List<ProgramScheduleItemViewModel> scheduleItems = await _mediator.Send(new GetProgramScheduleItems(_selectedSchedule.Id), _cts.Token);
|
||||
IOrderedEnumerable<ProgramScheduleItemViewModel> sorted = scheduleItems.OrderBy(s => s.Index);
|
||||
|
||||
// TODO: properly page this data
|
||||
|
||||
+16
-16
@@ -333,14 +333,14 @@
|
||||
_query = _navigationManager.Uri.GetSearchQuery();
|
||||
if (!string.IsNullOrWhiteSpace(_query))
|
||||
{
|
||||
_movies = await Mediator.Send(new QuerySearchIndexMovies($"type:movie AND ({_query})", 1, 50));
|
||||
_shows = await Mediator.Send(new QuerySearchIndexShows($"type:show AND ({_query})", 1, 50));
|
||||
_seasons = await Mediator.Send(new QuerySearchIndexSeasons($"type:season AND ({_query})", 1, 50));
|
||||
_episodes = await Mediator.Send(new QuerySearchIndexEpisodes($"type:episode AND ({_query})", 1, 50));
|
||||
_musicVideos = await Mediator.Send(new QuerySearchIndexMusicVideos($"type:music_video AND ({_query})", 1, 50));
|
||||
_otherVideos = await Mediator.Send(new QuerySearchIndexOtherVideos($"type:other_video AND ({_query})", 1, 50));
|
||||
_songs = await Mediator.Send(new QuerySearchIndexSongs($"type:song AND ({_query})", 1, 50));
|
||||
_artists = await Mediator.Send(new QuerySearchIndexArtists($"type:artist AND ({_query})", 1, 50));
|
||||
_movies = await Mediator.Send(new QuerySearchIndexMovies($"type:movie AND ({_query})", 1, 50), CancellationToken);
|
||||
_shows = await Mediator.Send(new QuerySearchIndexShows($"type:show AND ({_query})", 1, 50), CancellationToken);
|
||||
_seasons = await Mediator.Send(new QuerySearchIndexSeasons($"type:season AND ({_query})", 1, 50), CancellationToken);
|
||||
_episodes = await Mediator.Send(new QuerySearchIndexEpisodes($"type:episode AND ({_query})", 1, 50), CancellationToken);
|
||||
_musicVideos = await Mediator.Send(new QuerySearchIndexMusicVideos($"type:music_video AND ({_query})", 1, 50), CancellationToken);
|
||||
_otherVideos = await Mediator.Send(new QuerySearchIndexOtherVideos($"type:other_video AND ({_query})", 1, 50), CancellationToken);
|
||||
_songs = await Mediator.Send(new QuerySearchIndexSongs($"type:song AND ({_query})", 1, 50), CancellationToken);
|
||||
_artists = await Mediator.Send(new QuerySearchIndexArtists($"type:artist AND ({_query})", 1, 50), CancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddMovieToCollection(collection.Id, movie.MovieId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -395,7 +395,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddShowToCollection(collection.Id, show.TelevisionShowId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -416,7 +416,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddEpisodeToCollection(collection.Id, episode.EpisodeId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -437,7 +437,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddArtistToCollection(collection.Id, artist.ArtistId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -458,7 +458,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddMusicVideoToCollection(collection.Id, musicVideo.MusicVideoId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -479,7 +479,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddOtherVideoToCollection(collection.Id, otherVideo.OtherVideoId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -581,7 +581,7 @@
|
||||
|
||||
private async Task AddAllToCollection(MouseEventArgs _)
|
||||
{
|
||||
SearchResultAllItemsViewModel results = await Mediator.Send(new QuerySearchIndexAllItems(_query));
|
||||
SearchResultAllItemsViewModel results = await Mediator.Send(new QuerySearchIndexAllItems(_query), CancellationToken);
|
||||
await AddItemsToCollection(
|
||||
results.MovieIds,
|
||||
results.ShowIds,
|
||||
@@ -606,7 +606,7 @@
|
||||
collection.Id,
|
||||
_query);
|
||||
|
||||
Either<BaseError, Unit> updateResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> updateResult = await Mediator.Send(request, CancellationToken);
|
||||
updateResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
@using ErsatzTV.Core.Domain.Filler
|
||||
@using ErsatzTV.Core.FFmpeg
|
||||
@using Microsoft.AspNetCore.Components
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
@inject ISnackbar _snackbar
|
||||
@inject ILogger<Settings> _logger
|
||||
@@ -177,6 +179,8 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private bool _success;
|
||||
private bool _hdhrSuccess;
|
||||
private bool _scannerSuccess;
|
||||
@@ -189,22 +193,28 @@
|
||||
private int _tunerCount;
|
||||
private int _libraryRefreshInterval;
|
||||
private int _playoutDaysToBuild;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await LoadFFmpegProfilesAsync();
|
||||
|
||||
_ffmpegSettings = await _mediator.Send(new GetFFmpegSettings());
|
||||
_ffmpegSettings = await _mediator.Send(new GetFFmpegSettings(), _cts.Token);
|
||||
_success = File.Exists(_ffmpegSettings.FFmpegPath) && File.Exists(_ffmpegSettings.FFprobePath);
|
||||
_availableCultures = await _mediator.Send(new GetAllLanguageCodes());
|
||||
_watermarks = await _mediator.Send(new GetAllWatermarks());
|
||||
_fillerPresets = await _mediator.Send(new GetAllFillerPresets())
|
||||
_availableCultures = await _mediator.Send(new GetAllLanguageCodes(), _cts.Token);
|
||||
_watermarks = await _mediator.Send(new GetAllWatermarks(), _cts.Token);
|
||||
_fillerPresets = await _mediator.Send(new GetAllFillerPresets(), _cts.Token)
|
||||
.Map(list => list.Filter(fp => fp.FillerKind == FillerKind.Fallback).ToList());
|
||||
_tunerCount = await _mediator.Send(new GetHDHRTunerCount());
|
||||
_tunerCount = await _mediator.Send(new GetHDHRTunerCount(), _cts.Token);
|
||||
_hdhrSuccess = string.IsNullOrWhiteSpace(ValidateTunerCount(_tunerCount));
|
||||
_libraryRefreshInterval = await _mediator.Send(new GetLibraryRefreshInterval());
|
||||
_libraryRefreshInterval = await _mediator.Send(new GetLibraryRefreshInterval(), _cts.Token);
|
||||
_scannerSuccess = _libraryRefreshInterval > 0;
|
||||
_playoutDaysToBuild = await _mediator.Send(new GetPlayoutDaysToBuild());
|
||||
_playoutDaysToBuild = await _mediator.Send(new GetPlayoutDaysToBuild(), _cts.Token);
|
||||
_playoutSuccess = _playoutDaysToBuild > 0;
|
||||
}
|
||||
|
||||
@@ -223,11 +233,11 @@
|
||||
private static string ValidateInitialSegmentCount(int count) => count < 1 ? "HLS Segmenter initial segment count must be greater than or equal to 1" : null;
|
||||
|
||||
private async Task LoadFFmpegProfilesAsync() =>
|
||||
_ffmpegProfiles = await _mediator.Send(new GetAllFFmpegProfiles());
|
||||
_ffmpegProfiles = await _mediator.Send(new GetAllFFmpegProfiles(), _cts.Token);
|
||||
|
||||
private async Task SaveFFmpegSettings()
|
||||
{
|
||||
Either<BaseError, Unit> result = await _mediator.Send(new UpdateFFmpegSettings(_ffmpegSettings));
|
||||
Either<BaseError, Unit> result = await _mediator.Send(new UpdateFFmpegSettings(_ffmpegSettings), _cts.Token);
|
||||
result.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -239,7 +249,7 @@
|
||||
|
||||
private async Task SaveHDHRSettings()
|
||||
{
|
||||
Either<BaseError, Unit> result = await _mediator.Send(new UpdateHDHRTunerCount(_tunerCount));
|
||||
Either<BaseError, Unit> result = await _mediator.Send(new UpdateHDHRTunerCount(_tunerCount), _cts.Token);
|
||||
result.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -251,7 +261,7 @@
|
||||
|
||||
private async Task SaveScannerSettings()
|
||||
{
|
||||
Either<BaseError, Unit> result = await _mediator.Send(new UpdateLibraryRefreshInterval(_libraryRefreshInterval));
|
||||
Either<BaseError, Unit> result = await _mediator.Send(new UpdateLibraryRefreshInterval(_libraryRefreshInterval), _cts.Token);
|
||||
result.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -263,7 +273,7 @@
|
||||
|
||||
private async Task SavePlayoutSettings()
|
||||
{
|
||||
Either<BaseError, Unit> result = await _mediator.Send(new UpdatePlayoutDaysToBuild(_playoutDaysToBuild));
|
||||
Either<BaseError, Unit> result = await _mediator.Send(new UpdatePlayoutDaysToBuild(_playoutDaysToBuild), _cts.Token);
|
||||
result.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
protected override async Task RefreshData()
|
||||
{
|
||||
string searchQuery = string.IsNullOrWhiteSpace(_query) ? "type:song" : $"type:song AND ({_query})";
|
||||
_data = await Mediator.Send(new QuerySearchIndexSongs(searchQuery, PageNumber, PageSize));
|
||||
_data = await Mediator.Send(new QuerySearchIndexSongs(searchQuery, PageNumber, PageSize), CancellationToken);
|
||||
}
|
||||
|
||||
private void PrevPage()
|
||||
@@ -143,7 +143,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddSongToCollection(collection.Id, song.SongId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
@using ErsatzTV.Application.ProgramSchedules
|
||||
@using ErsatzTV.Application.ProgramSchedules.Commands
|
||||
@using Unit = LanguageExt.Unit
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
@inject ILogger<TelevisionEpisodeList> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -156,6 +158,7 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int SeasonId { get; set; }
|
||||
@@ -166,6 +169,12 @@
|
||||
private readonly int _pageNumber = 1;
|
||||
|
||||
private TelevisionEpisodeCardResultsViewModel _data;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
@@ -179,10 +188,10 @@
|
||||
|
||||
private async Task RefreshData()
|
||||
{
|
||||
await _mediator.Send(new GetTelevisionSeasonById(SeasonId))
|
||||
await _mediator.Send(new GetTelevisionSeasonById(SeasonId), _cts.Token)
|
||||
.IfSomeAsync(vm => _season = vm);
|
||||
|
||||
_data = await _mediator.Send(new GetTelevisionEpisodeCards(SeasonId, _pageNumber, _pageSize));
|
||||
_data = await _mediator.Send(new GetTelevisionEpisodeCards(SeasonId, _pageNumber, _pageSize), _cts.Token);
|
||||
}
|
||||
|
||||
private async Task AddToCollection()
|
||||
@@ -194,7 +203,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
await _mediator.Send(new AddSeasonToCollection(collection.Id, SeasonId));
|
||||
await _mediator.Send(new AddSeasonToCollection(collection.Id, SeasonId), _cts.Token);
|
||||
_navigationManager.NavigateTo($"/media/collections/{collection.Id}");
|
||||
}
|
||||
}
|
||||
@@ -209,7 +218,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled && result.Data is ProgramScheduleViewModel schedule)
|
||||
{
|
||||
await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.TelevisionSeason, null, null, null, SeasonId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null));
|
||||
await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.TelevisionSeason, null, null, null, SeasonId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null), _cts.Token);
|
||||
_navigationManager.NavigateTo($"/schedules/{schedule.Id}/items");
|
||||
}
|
||||
}
|
||||
@@ -224,7 +233,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddEpisodeToCollection(collection.Id, episode.EpisodeId);
|
||||
Either<BaseError, Unit> addResult = await _mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await _mediator.Send(request, _cts.Token);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
@using ErsatzTV.Application.ProgramSchedules.Commands
|
||||
@using ErsatzTV.Extensions
|
||||
@using Unit = LanguageExt.Unit
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IMediator _mediator
|
||||
@inject ILogger<TelevisionSeasonList> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -168,6 +170,7 @@
|
||||
}
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int ShowId { get; set; }
|
||||
@@ -183,12 +186,18 @@
|
||||
private readonly int _pageNumber = 1;
|
||||
|
||||
private TelevisionSeasonCardResultsViewModel _data;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override Task OnParametersSetAsync() => RefreshData();
|
||||
|
||||
private async Task RefreshData()
|
||||
{
|
||||
await _mediator.Send(new GetTelevisionShowById(ShowId))
|
||||
await _mediator.Send(new GetTelevisionShowById(ShowId), _cts.Token)
|
||||
.IfSomeAsync(vm =>
|
||||
{
|
||||
_show = vm;
|
||||
@@ -199,7 +208,7 @@
|
||||
_sortedTags = _show.Tags.OrderBy(t => t).ToList();
|
||||
});
|
||||
|
||||
_data = await _mediator.Send(new GetTelevisionSeasonCards(ShowId, _pageNumber, _pageSize));
|
||||
_data = await _mediator.Send(new GetTelevisionSeasonCards(ShowId, _pageNumber, _pageSize), _cts.Token);
|
||||
}
|
||||
|
||||
private async Task AddToCollection()
|
||||
@@ -211,7 +220,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
await _mediator.Send(new AddShowToCollection(collection.Id, ShowId));
|
||||
await _mediator.Send(new AddShowToCollection(collection.Id, ShowId), _cts.Token);
|
||||
_navigationManager.NavigateTo($"/media/collections/{collection.Id}");
|
||||
}
|
||||
}
|
||||
@@ -225,7 +234,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled && result.Data is ProgramScheduleViewModel schedule)
|
||||
{
|
||||
await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.TelevisionShow, null, null, null, ShowId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null));
|
||||
await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.TelevisionShow, null, null, null, ShowId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null), _cts.Token);
|
||||
_navigationManager.NavigateTo($"/schedules/{schedule.Id}/items");
|
||||
}
|
||||
}
|
||||
@@ -242,7 +251,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddSeasonToCollection(collection.Id, season.TelevisionSeasonId);
|
||||
Either<BaseError, Unit> addResult = await _mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await _mediator.Send(request, _cts.Token);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
protected override async Task RefreshData()
|
||||
{
|
||||
string searchQuery = string.IsNullOrWhiteSpace(_query) ? "type:season" : $"type:season AND ({_query})";
|
||||
_data = await Mediator.Send(new QuerySearchIndexSeasons(searchQuery, PageNumber, PageSize));
|
||||
_data = await Mediator.Send(new QuerySearchIndexSeasons(searchQuery, PageNumber, PageSize), CancellationToken);
|
||||
}
|
||||
|
||||
private void PrevPage()
|
||||
@@ -142,7 +142,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddSeasonToCollection(collection.Id, season.TelevisionSeasonId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
protected override async Task RefreshData()
|
||||
{
|
||||
string searchQuery = string.IsNullOrWhiteSpace(_query) ? "type:show" : $"type:show AND ({_query})";
|
||||
_data = await Mediator.Send(new QuerySearchIndexShows(searchQuery, PageNumber, PageSize));
|
||||
_data = await Mediator.Send(new QuerySearchIndexShows(searchQuery, PageNumber, PageSize), CancellationToken);
|
||||
}
|
||||
|
||||
private void PrevPage()
|
||||
@@ -142,7 +142,7 @@
|
||||
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
|
||||
{
|
||||
var request = new AddShowToCollection(collection.Id, show.TelevisionShowId);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
@using ErsatzTV.Application.Configuration.Queries
|
||||
@using ErsatzTV.Application.Configuration.Commands
|
||||
@using ErsatzTV.Application.MediaCollections.Commands
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IDialogService _dialog
|
||||
@inject IMediator _mediator
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -75,9 +77,17 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private MudTable<TraktListViewModel> _traktListsTable;
|
||||
|
||||
private int _traktListsRowsPerPage;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
@@ -86,7 +96,7 @@
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_traktListsRowsPerPage = await _mediator.Send(new GetConfigElementByKey(ConfigElementKey.TraktListsPageSize))
|
||||
_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));
|
||||
}
|
||||
|
||||
@@ -104,7 +114,7 @@
|
||||
{
|
||||
if (_locker.LockTrakt())
|
||||
{
|
||||
await _workerChannel.WriteAsync(new MatchTraktListItems(traktList.Id));
|
||||
await _workerChannel.WriteAsync(new MatchTraktListItems(traktList.Id), _cts.Token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,16 +129,16 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await _workerChannel.WriteAsync(new DeleteTraktList(traktList.Id));
|
||||
await _workerChannel.WriteAsync(new DeleteTraktList(traktList.Id), _cts.Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<TableData<TraktListViewModel>> ServerReloadTraktLists(TableState state)
|
||||
{
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.TraktListsPageSize, state.PageSize.ToString()));
|
||||
await _mediator.Send(new SaveConfigElementByKey(ConfigElementKey.TraktListsPageSize, state.PageSize.ToString()), _cts.Token);
|
||||
|
||||
PagedTraktListsViewModel data = await _mediator.Send(new GetPagedTraktLists(state.Page, state.PageSize));
|
||||
PagedTraktListsViewModel data = await _mediator.Send(new GetPagedTraktLists(state.Page, state.PageSize), _cts.Token);
|
||||
return new TableData<TraktListViewModel> { TotalItems = data.TotalCount, Items = data.Page };
|
||||
}
|
||||
|
||||
@@ -141,7 +151,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled && result.Data is string url)
|
||||
{
|
||||
await _workerChannel.WriteAsync(new AddTraktList(url));
|
||||
await _workerChannel.WriteAsync(new AddTraktList(url), _cts.Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -327,14 +327,14 @@
|
||||
_query = "state:FileNotFound";
|
||||
if (!string.IsNullOrWhiteSpace(_query))
|
||||
{
|
||||
_movies = await Mediator.Send(new QuerySearchIndexMovies($"type:movie AND ({_query})", 1, 50));
|
||||
_shows = await Mediator.Send(new QuerySearchIndexShows($"type:show AND ({_query})", 1, 50));
|
||||
_seasons = await Mediator.Send(new QuerySearchIndexSeasons($"type:season AND ({_query})", 1, 50));
|
||||
_episodes = await Mediator.Send(new QuerySearchIndexEpisodes($"type:episode AND ({_query})", 1, 50));
|
||||
_musicVideos = await Mediator.Send(new QuerySearchIndexMusicVideos($"type:music_video AND ({_query})", 1, 50));
|
||||
_otherVideos = await Mediator.Send(new QuerySearchIndexOtherVideos($"type:other_video AND ({_query})", 1, 50));
|
||||
_songs = await Mediator.Send(new QuerySearchIndexSongs($"type:song AND ({_query})", 1, 50));
|
||||
_artists = await Mediator.Send(new QuerySearchIndexArtists($"type:artist AND ({_query})", 1, 50));
|
||||
_movies = await Mediator.Send(new QuerySearchIndexMovies($"type:movie AND ({_query})", 1, 50), CancellationToken);
|
||||
_shows = await Mediator.Send(new QuerySearchIndexShows($"type:show AND ({_query})", 1, 50), CancellationToken);
|
||||
_seasons = await Mediator.Send(new QuerySearchIndexSeasons($"type:season AND ({_query})", 1, 50), CancellationToken);
|
||||
_episodes = await Mediator.Send(new QuerySearchIndexEpisodes($"type:episode AND ({_query})", 1, 50), CancellationToken);
|
||||
_musicVideos = await Mediator.Send(new QuerySearchIndexMusicVideos($"type:music_video AND ({_query})", 1, 50), CancellationToken);
|
||||
_otherVideos = await Mediator.Send(new QuerySearchIndexOtherVideos($"type:other_video AND ({_query})", 1, 50), CancellationToken);
|
||||
_songs = await Mediator.Send(new QuerySearchIndexSongs($"type:song AND ({_query})", 1, 50), CancellationToken);
|
||||
_artists = await Mediator.Send(new QuerySearchIndexArtists($"type:artist AND ({_query})", 1, 50), CancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,7 +486,7 @@
|
||||
.Append(songIds)
|
||||
.ToList());
|
||||
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request);
|
||||
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
|
||||
await addResult.Match(
|
||||
Left: error =>
|
||||
{
|
||||
@@ -556,7 +556,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await Mediator.Send(request);
|
||||
await Mediator.Send(request, CancellationToken);
|
||||
await RefreshData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
@using ErsatzTV.Application.Watermarks
|
||||
@using ErsatzTV.Application.Watermarks.Queries
|
||||
@using ErsatzTV.FFmpeg.State
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject ILogger<WatermarkEditor> _logger
|
||||
@inject ISnackbar _snackbar
|
||||
@@ -146,7 +148,8 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
@@ -154,11 +157,17 @@
|
||||
private EditContext _editContext;
|
||||
private ValidationMessageStore _messageStore;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (IsEdit)
|
||||
{
|
||||
Option<WatermarkViewModel> watermark = await _mediator.Send(new GetWatermarkById(Id));
|
||||
Option<WatermarkViewModel> watermark = await _mediator.Send(new GetWatermarkById(Id), _cts.Token);
|
||||
watermark.Match(
|
||||
watermarkViewModel => _model = new WatermarkEditViewModel(watermarkViewModel),
|
||||
() => _navigationManager.NavigateTo("404"));
|
||||
@@ -193,8 +202,8 @@
|
||||
if (_editContext.Validate())
|
||||
{
|
||||
Seq<BaseError> errorMessage = IsEdit ?
|
||||
(await _mediator.Send(_model.ToUpdate())).LeftToSeq() :
|
||||
(await _mediator.Send(_model.ToCreate())).LeftToSeq();
|
||||
(await _mediator.Send(_model.ToUpdate(), _cts.Token)).LeftToSeq() :
|
||||
(await _mediator.Send(_model.ToCreate(), _cts.Token)).LeftToSeq();
|
||||
|
||||
errorMessage.HeadOrNone().Match(
|
||||
error =>
|
||||
@@ -210,8 +219,9 @@
|
||||
{
|
||||
try
|
||||
{
|
||||
Either<BaseError, string> maybeCacheFileName = await _mediator
|
||||
.Send(new SaveArtworkToDisk(e.File.OpenReadStream(maxAllowedSize: 10 * 1024 * 1024), ArtworkKind.Watermark));
|
||||
Either<BaseError, string> maybeCacheFileName = await _mediator.Send(
|
||||
new SaveArtworkToDisk(e.File.OpenReadStream(maxAllowedSize: 10 * 1024 * 1024), ArtworkKind.Watermark),
|
||||
_cts.Token);
|
||||
maybeCacheFileName.Match(
|
||||
relativeFileName =>
|
||||
{
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
@using ErsatzTV.Application.Watermarks
|
||||
@using ErsatzTV.Application.Watermarks.Commands
|
||||
@using ErsatzTV.Application.Watermarks.Queries
|
||||
@using System.Threading
|
||||
@implements IDisposable
|
||||
@inject IDialogService _dialog
|
||||
@inject IMediator _mediator
|
||||
@inject ILogger<Watermarks> _logger
|
||||
@@ -72,12 +74,20 @@
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private List<WatermarkViewModel> _watermarks;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync() => await LoadWatermarksAsync();
|
||||
|
||||
private async Task LoadWatermarksAsync() =>
|
||||
_watermarks = await _mediator.Send(new GetAllWatermarks());
|
||||
_watermarks = await _mediator.Send(new GetAllWatermarks(), _cts.Token);
|
||||
|
||||
private async Task DeleteWatermarkAsync(WatermarkViewModel watermark)
|
||||
{
|
||||
@@ -88,7 +98,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Cancelled)
|
||||
{
|
||||
await _mediator.Send(new DeleteWatermark(watermark.Id));
|
||||
await _mediator.Send(new DeleteWatermark(watermark.Id), _cts.Token);
|
||||
await LoadWatermarksAsync();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user