Files
qbtmud/Lantean.QBTMudBlade/Components/PeersTab.razor.cs

171 lines
6.1 KiB
C#

using Lantean.QBitTorrentClient;
using Lantean.QBTMudBlade.Models;
using Lantean.QBTMudBlade.Services;
using Microsoft.AspNetCore.Components;
using MudBlazor;
using System.Data;
using System.Net;
namespace Lantean.QBTMudBlade.Components
{
public partial class PeersTab : IAsyncDisposable
{
private bool _disposedValue;
protected string? _oldHash;
private int _requestId = 0;
private readonly CancellationTokenSource _timerCancellationToken = new();
private bool? _showFlags;
[Parameter, EditorRequired]
public string? Hash { get; set; }
[Parameter]
public bool Active { get; set; }
[CascadingParameter(Name = "RefreshInterval")]
public int RefreshInterval { get; set; }
[CascadingParameter]
public QBitTorrentClient.Models.Preferences? Preferences { get; set; }
[Inject]
protected IApiClient ApiClient { get; set; } = default!;
[Inject]
protected IDataManager DataManager { get; set; } = default!;
protected PeerList? PeerList { get; set; }
protected IEnumerable<Peer> Peers => PeerList?.Peers.Select(p => p.Value) ?? [];
protected bool ShowFlags => _showFlags.GetValueOrDefault();
protected override async Task OnParametersSetAsync()
{
if (Hash is null)
{
return;
}
if (!Active)
{
return;
}
if (Hash != _oldHash)
{
_oldHash = Hash;
_requestId = 0;
PeerList = null;
}
var peers = await ApiClient.GetTorrentPeersData(Hash, _requestId);
if (PeerList is null || peers.FullUpdate)
{
PeerList = DataManager.CreatePeerList(peers);
}
else
{
DataManager.MergeTorrentPeers(peers, PeerList);
}
_requestId = peers.RequestId;
if (Preferences is not null && _showFlags is null)
{
_showFlags = Preferences.ResolvePeerCountries;
}
if (peers.ShowFlags.HasValue)
{
_showFlags = peers.ShowFlags.Value;
}
await InvokeAsync(StateHasChanged);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
using (var timer = new PeriodicTimer(TimeSpan.FromMilliseconds(RefreshInterval)))
{
while (!_timerCancellationToken.IsCancellationRequested && await timer.WaitForNextTickAsync())
{
if (Hash is null)
{
return;
}
if (Active)
{
QBitTorrentClient.Models.TorrentPeers peers;
try
{
peers = await ApiClient.GetTorrentPeersData(Hash, _requestId);
}
catch (HttpRequestException exception) when (exception.StatusCode == HttpStatusCode.Forbidden || exception.StatusCode == HttpStatusCode.NotFound)
{
_timerCancellationToken.CancelIfNotDisposed();
return;
}
if (PeerList is null || peers.FullUpdate)
{
PeerList = DataManager.CreatePeerList(peers);
}
else
{
DataManager.MergeTorrentPeers(peers, PeerList);
}
_requestId = peers.RequestId;
}
await InvokeAsync(StateHasChanged);
}
}
}
}
protected IEnumerable<ColumnDefinition<Peer>> Columns => ColumnsDefinitions.Where(c => c.Id != "country/region" || _showFlags == true);
public static List<ColumnDefinition<Peer>> ColumnsDefinitions { get; } =
[
new ColumnDefinition<Peer>("Country/Region", p => p.Country),
new ColumnDefinition<Peer>("IP", p => p.IPAddress),
new ColumnDefinition<Peer>("Port", p => p.Port),
new ColumnDefinition<Peer>("Connection", p => p.Connection),
new ColumnDefinition<Peer>("Flags", p => p.Flags),
new ColumnDefinition<Peer>("Client", p => p.Client),
new ColumnDefinition<Peer>("Progress", p => p.Progress, p => DisplayHelpers.Percentage(p.Progress)),
new ColumnDefinition<Peer>("Download Speed", p => p.DownloadSpeed, p => DisplayHelpers.Speed(p.DownloadSpeed)),
new ColumnDefinition<Peer>("Upload Speed", p => p.UploadSpeed, p => DisplayHelpers.Speed(p.UploadSpeed)),
new ColumnDefinition<Peer>("Downloaded", p => p.Downloaded, p => @DisplayHelpers.Size(p.Downloaded)),
new ColumnDefinition<Peer>("Uploaded", p => p.Uploaded, p => @DisplayHelpers.Size(p.Uploaded)),
new ColumnDefinition<Peer>("Relevance", p => p.Relevance, p => @DisplayHelpers.Percentage(p.Relevance)),
new ColumnDefinition<Peer>("Files", p => p.Files, p => p.Files),
];
protected virtual async Task DisposeAsync(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
_timerCancellationToken.Cancel();
_timerCancellationToken.Dispose();
await Task.CompletedTask;
}
_disposedValue = true;
}
}
public async ValueTask DisposeAsync()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
await DisposeAsync(disposing: true);
GC.SuppressFinalize(this);
}
}
}