add option to auto refresh trakt lists (#2169)
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
@page "/media/trakt/lists/{Id:int}"
|
||||
@using ErsatzTV.Application.MediaCollections
|
||||
@implements IDisposable
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ILogger<ScheduleEditor> Logger
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IMediator Mediator
|
||||
|
||||
<MudForm @ref="_form" @bind-IsValid="@_success" Style="max-height: 100%">
|
||||
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-6" OnClick="@HandleSubmitAsync" StartIcon="@Icons.Material.Filled.Save">
|
||||
Save Trakt List
|
||||
</MudButton>
|
||||
</MudPaper>
|
||||
<div class="d-flex flex-column" style="height: 100vh; overflow-x: auto">
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
||||
<MudText Typo="Typo.h5" Class="mb-2">Trakt List</MudText>
|
||||
<MudDivider Class="mb-6"/>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Id</MudText>
|
||||
</div>
|
||||
<MudTextField Value="_model.Slug" Disabled="true" />
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Automatic Refresh</MudText>
|
||||
</div>
|
||||
<MudCheckBox @bind-Value="@_model.AutoRefresh" For="@(() => _model.AutoRefresh)" Dense="true">
|
||||
<MudText Typo="Typo.caption" Style="font-weight: normal">Update list from trakt.tv once each day</MudText>
|
||||
</MudCheckBox>
|
||||
</MudStack>
|
||||
</MudContainer>
|
||||
</div>
|
||||
</MudForm>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
private readonly TraktListEditViewModel _model = new();
|
||||
private MudForm _form;
|
||||
private bool _success;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
Option<TraktListViewModel> maybeTraktList = await Mediator.Send(new GetTraktListById(Id), _cts.Token);
|
||||
maybeTraktList.Match(
|
||||
viewModel =>
|
||||
{
|
||||
_model.Id = viewModel.Id;
|
||||
_model.Slug = viewModel.Slug;
|
||||
_model.AutoRefresh = viewModel.AutoRefresh;
|
||||
},
|
||||
() => NavigationManager.NavigateTo("404"));
|
||||
}
|
||||
|
||||
private async Task HandleSubmitAsync()
|
||||
{
|
||||
await _form.Validate();
|
||||
if (_success)
|
||||
{
|
||||
var request = new UpdateTraktList(_model.Id, _model.AutoRefresh);
|
||||
Option<BaseError> result = await Mediator.Send(request, _cts.Token);
|
||||
foreach (BaseError error in result)
|
||||
{
|
||||
Snackbar.Add(error.Value, Severity.Error);
|
||||
Logger.LogError("Unexpected error saving trakt list: {Error}", error.Value);
|
||||
}
|
||||
|
||||
if (result.IsNone)
|
||||
{
|
||||
NavigationManager.NavigateTo("/media/trakt/lists");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@
|
||||
<col/>
|
||||
<col/>
|
||||
<col/>
|
||||
<col style="width: 180px;"/>
|
||||
<col style="width: 240px;"/>
|
||||
</MudHidden>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
@@ -47,6 +47,12 @@
|
||||
<MudTd>@context.MatchCount of @context.ItemCount</MudTd>
|
||||
<MudTd>
|
||||
<div style="align-items: center; display: flex;">
|
||||
<MudTooltip Text="Edit Trakt List Properties">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Disabled="@Locker.IsTraktLocked()"
|
||||
Href="@($"media/trakt/lists/{context.Id}")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Search Trakt List">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Search"
|
||||
Disabled="@Locker.IsTraktLocked()"
|
||||
@@ -160,7 +166,7 @@
|
||||
DialogResult result = await dialog.Result;
|
||||
if (result is { Canceled: false, Data: string url })
|
||||
{
|
||||
await WorkerChannel.WriteAsync(new AddTraktList(url), _cts.Token);
|
||||
await WorkerChannel.WriteAsync(Application.MediaCollections.AddTraktList.FromUrl(url), _cts.Token);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -125,6 +125,7 @@ public class SchedulerService : BackgroundService
|
||||
await ScanJellyfinMediaSources(cancellationToken);
|
||||
await ScanEmbyMediaSources(cancellationToken);
|
||||
#endif
|
||||
await RefreshTraktLists(cancellationToken);
|
||||
await MatchTraktLists(cancellationToken);
|
||||
|
||||
await ReleaseMemory(cancellationToken);
|
||||
@@ -320,12 +321,38 @@ public class SchedulerService : BackgroundService
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RefreshTraktLists(CancellationToken cancellationToken)
|
||||
{
|
||||
using IServiceScope scope = _serviceScopeFactory.CreateScope();
|
||||
TvContext dbContext = scope.ServiceProvider.GetRequiredService<TvContext>();
|
||||
|
||||
DateTime target = DateTime.UtcNow.AddDays(-1);
|
||||
|
||||
List<TraktList> traktLists = await dbContext.TraktLists
|
||||
.Filter(tl => tl.AutoRefresh && (tl.LastUpdate == null || tl.LastUpdate <= target))
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (traktLists.Count != 0 && _entityLocker.LockTrakt())
|
||||
{
|
||||
TraktList last = traktLists.Last();
|
||||
foreach (TraktList list in traktLists)
|
||||
{
|
||||
await _workerChannel.WriteAsync(
|
||||
AddTraktList.Existing(list.User, list.List, list == last),
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task MatchTraktLists(CancellationToken cancellationToken)
|
||||
{
|
||||
using IServiceScope scope = _serviceScopeFactory.CreateScope();
|
||||
TvContext dbContext = scope.ServiceProvider.GetRequiredService<TvContext>();
|
||||
|
||||
DateTime target = DateTime.UtcNow.AddHours(-1);
|
||||
|
||||
List<TraktList> traktLists = await dbContext.TraktLists
|
||||
.Filter(tl => tl.LastMatch == null || tl.LastMatch <= target)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (traktLists.Count != 0 && _entityLocker.LockTrakt())
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ErsatzTV.ViewModels;
|
||||
|
||||
public class TraktListEditViewModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public bool AutoRefresh { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user