Improved statuses, add more actions.
This commit is contained in:
parent
a27bd37991
commit
8f35952f90
11 changed files with 115 additions and 52 deletions
|
|
@ -2,15 +2,32 @@
|
||||||
<td>
|
<td>
|
||||||
{{ torrent.rdSize | filesize }}
|
{{ torrent.rdSize | filesize }}
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ torrent.files.length | number }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ torrent.downloads.length | number }}
|
||||||
|
</td>
|
||||||
|
<td class="auto">
|
||||||
|
<i class="fas fa-download" *ngIf="!torrent.autoDownload" title="Auto download"></i>
|
||||||
|
<i class="fas fa-box-open" *ngIf="!torrent.autoUnpack" title="Auto unpack"></i>
|
||||||
|
<i class="fas fa-trash" *ngIf="!torrent.autoDelete" title="Auto delete"></i>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ torrent | status }}
|
{{ torrent | status }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="icon download-icon" (click)="download($event)" title="Download to disk" *ngIf="!loading">
|
<span
|
||||||
|
class="icon download-icon"
|
||||||
|
(click)="download($event)"
|
||||||
|
title="Download to disk"
|
||||||
|
*ngIf="!loading && canDownload()"
|
||||||
|
>
|
||||||
<i class="fas fa-download"></i>
|
<i class="fas fa-download"></i>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
<span class="icon download-icon" (click)="unpack($event)" title="Unpack" *ngIf="!loading && canUnpack()">
|
||||||
<td>
|
<i class="fas fa-box-open"></i>
|
||||||
|
</span>
|
||||||
<span class="icon delete-icon" (click)="delete1($event)" title="Delete torrent" *ngIf="!loading">
|
<span class="icon delete-icon" (click)="delete1($event)" title="Delete torrent" *ngIf="!loading">
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-times"></i>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,7 @@
|
||||||
color: red;
|
color: red;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.auto .fas {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
import { Torrent } from 'src/app/models/torrent.model';
|
import { RealDebridStatus, Torrent } from 'src/app/models/torrent.model';
|
||||||
import { TorrentService } from 'src/app/torrent.service';
|
import { TorrentService } from 'src/app/torrent.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
@ -24,13 +24,42 @@ export class TorrentRowComponent implements OnInit {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.torrentService.download(this.torrent.torrentId).subscribe(() => {
|
this.torrentService.download(this.torrent.torrentId).subscribe(
|
||||||
this.loading = false;
|
() => {
|
||||||
});
|
this.loading = false;
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public unpack(event: Event): void {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
this.loading = true;
|
||||||
|
this.torrentService.unpack(this.torrent.torrentId).subscribe(
|
||||||
|
() => {
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public delete1(event: Event): void {
|
public delete1(event: Event): void {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
this.delete.emit(this.torrent.torrentId);
|
this.delete.emit(this.torrent.torrentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public canDownload(): boolean {
|
||||||
|
return this.torrent.rdStatus === RealDebridStatus.Finished && this.torrent.downloads.length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public canUnpack(): boolean {
|
||||||
|
const downloadsDone = this.torrent.downloads.any((m) => m.downloadFinished != null);
|
||||||
|
const downloadsUnpacked = this.torrent.downloads.any((m) => m.unpackingQueued != null);
|
||||||
|
return downloadsDone && !downloadsUnpacked;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,16 @@ export class TorrentStatusPipe implements PipeTransform {
|
||||||
return 'Finished';
|
return 'Finished';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const errors = torrent.downloads.where((m) => m.error != null);
|
||||||
const downloading = torrent.downloads.where((m) => m.downloadStarted && !m.downloadFinished);
|
const downloading = torrent.downloads.where((m) => m.downloadStarted && !m.downloadFinished);
|
||||||
|
const downloaded = torrent.downloads.where((m) => m.downloadFinished != null);
|
||||||
const unpacking = torrent.downloads.where((m) => m.unpackingStarted && !m.unpackingFinished);
|
const unpacking = torrent.downloads.where((m) => m.unpackingStarted && !m.unpackingFinished);
|
||||||
|
const queuedForDownload = torrent.downloads.where((m) => m.downloadQueued && !m.downloadStarted);
|
||||||
|
const queuedForUnpacking = torrent.downloads.where((m) => m.unpackingQueued && !m.unpackingStarted);
|
||||||
|
|
||||||
let downloadText = '';
|
if (errors.length > 0) {
|
||||||
let unpackText = '';
|
return 'Error';
|
||||||
|
}
|
||||||
|
|
||||||
if (downloading.length > 0) {
|
if (downloading.length > 0) {
|
||||||
const bytesDone = downloading.sum((m) => m.bytesDone);
|
const bytesDone = downloading.sum((m) => m.bytesDone);
|
||||||
|
|
@ -35,7 +40,7 @@ export class TorrentStatusPipe implements PipeTransform {
|
||||||
if (allSpeeds > 0) {
|
if (allSpeeds > 0) {
|
||||||
speed = this.pipe.transform(allSpeeds, 'filesize');
|
speed = this.pipe.transform(allSpeeds, 'filesize');
|
||||||
|
|
||||||
downloadText = `Downloading (${progress.toFixed(2)}% - ${speed}/s)`;
|
return `Downloading (${progress.toFixed(2)}% - ${speed}/s)`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,20 +51,20 @@ export class TorrentStatusPipe implements PipeTransform {
|
||||||
let allSpeeds = unpacking.sum((m) => m.speed) / unpacking.length;
|
let allSpeeds = unpacking.sum((m) => m.speed) / unpacking.length;
|
||||||
|
|
||||||
if (allSpeeds > 0) {
|
if (allSpeeds > 0) {
|
||||||
downloadText = `Extracting (${progress.toFixed(2)}%)`;
|
return `Extracting (${progress.toFixed(2)}%)`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let result: string[] = [];
|
if (queuedForUnpacking.length > 0) {
|
||||||
if (downloadText) {
|
return `Queued for unpacking`;
|
||||||
result.push(downloadText);
|
|
||||||
}
|
|
||||||
if (unpackText) {
|
|
||||||
result.push(unpackText);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.length > 0) {
|
if (queuedForDownload.length > 0) {
|
||||||
return result.join('\r\n');
|
return `Queued for downloading`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downloaded.length > 0) {
|
||||||
|
return `Files downloaded to host`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,23 @@
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<table class="table is-fullwidth is-hoverable">
|
<table class="table is-fullwidth is-hoverable">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
<col style="width: 50%" />
|
<col style="width: calc(65% - 550px)" />
|
||||||
<col style="width: 15%" />
|
<col style="width: 15%" />
|
||||||
<col style="width: 35%" />
|
<col style="width: 150px" />
|
||||||
<col style="width: 50px" />
|
<col style="width: 150px" />
|
||||||
<col style="width: 50px" />
|
<col style="width: 150px" />
|
||||||
|
<col style="width: 20%" />
|
||||||
|
<col style="width: 100px" />
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Size</th>
|
<th>Size</th>
|
||||||
|
<th>Files</th>
|
||||||
|
<th>Downloads</th>
|
||||||
|
<th>Auto</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th></th>
|
<th>Action</th>
|
||||||
<th></th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
@ -28,15 +32,12 @@
|
||||||
(click)="selectTorrent(torrent)"
|
(click)="selectTorrent(torrent)"
|
||||||
(delete)="showDeleteModal($event)"
|
(delete)="showDeleteModal($event)"
|
||||||
></tr>
|
></tr>
|
||||||
|
|
||||||
<ng-container *ngIf="showFiles[torrent.torrentId] && torrent?.files.length === 0">
|
<ng-container *ngIf="showFiles[torrent.torrentId] && torrent?.files.length === 0">
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="20">
|
<td colspan="20">
|
||||||
<i class="fas fa-spinner fa-pulse"></i>
|
<i class="fas fa-spinner fa-pulse"></i>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="showFiles[torrent.torrentId] && torrent?.files.length > 0">
|
|
||||||
<tr app-torrent-file [file]="file" *ngFor="let file of torrent.files"></tr>
|
<tr app-torrent-file [file]="file" *ngFor="let file of torrent.files"></tr>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,10 @@ export class TorrentService {
|
||||||
return this.http.get<void>(`/Api/Torrents/Download/${torrentId}`);
|
return this.http.get<void>(`/Api/Torrents/Download/${torrentId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unpack(torrentId: string): Observable<void> {
|
||||||
|
return this.http.get<void>(`/Api/Torrents/Unpack/${torrentId}`);
|
||||||
|
}
|
||||||
|
|
||||||
public delete(
|
public delete(
|
||||||
torrentId: string,
|
torrentId: string,
|
||||||
deleteData: boolean,
|
deleteData: boolean,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ namespace RdtClient.Service
|
||||||
services.AddScoped<ISettings, Settings>();
|
services.AddScoped<ISettings, Settings>();
|
||||||
services.AddScoped<ITorrents, Torrents>();
|
services.AddScoped<ITorrents, Torrents>();
|
||||||
services.AddScoped<ITorrentRunner, TorrentRunner>();
|
services.AddScoped<ITorrentRunner, TorrentRunner>();
|
||||||
services.AddScoped<ITorrentDownloadManager, TorrentDownloadManager>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace RdtClient.Service.Services
|
|
||||||
{
|
|
||||||
public interface ITorrentDownloadManager
|
|
||||||
{
|
|
||||||
Task Tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TorrentDownloadManager : ITorrentDownloadManager
|
|
||||||
{
|
|
||||||
public async Task Tick()
|
|
||||||
{
|
|
||||||
throw new System.NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -163,6 +163,15 @@ namespace RdtClient.Service.Services
|
||||||
|
|
||||||
if (torrent != null)
|
if (torrent != null)
|
||||||
{
|
{
|
||||||
|
if (deleteLocalFiles)
|
||||||
|
{
|
||||||
|
var settingDownloadFolder = await _settings.GetString("DownloadFolder");
|
||||||
|
|
||||||
|
var torrentPath = Path.Combine(settingDownloadFolder, torrent.RdName);
|
||||||
|
|
||||||
|
Directory.Delete(torrentPath, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (deleteData)
|
if (deleteData)
|
||||||
{
|
{
|
||||||
await _downloads.DeleteForTorrent(torrent.TorrentId);
|
await _downloads.DeleteForTorrent(torrent.TorrentId);
|
||||||
|
|
@ -173,11 +182,6 @@ namespace RdtClient.Service.Services
|
||||||
{
|
{
|
||||||
await GetRdNetClient().DeleteTorrentAsync(torrent.RdId);
|
await GetRdNetClient().DeleteTorrentAsync(torrent.RdId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deleteLocalFiles)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,12 @@ namespace RdtClient.Web.Controllers
|
||||||
public class TorrentsController : Controller
|
public class TorrentsController : Controller
|
||||||
{
|
{
|
||||||
private readonly ITorrents _torrents;
|
private readonly ITorrents _torrents;
|
||||||
|
private readonly IDownloads _downloads;
|
||||||
|
|
||||||
public TorrentsController(ITorrents torrents)
|
public TorrentsController(ITorrents torrents, IDownloads downloads)
|
||||||
{
|
{
|
||||||
_torrents = torrents;
|
_torrents = torrents;
|
||||||
|
_downloads = downloads;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
|
@ -102,6 +104,20 @@ namespace RdtClient.Web.Controllers
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[Route("Unpack/{id}")]
|
||||||
|
public async Task<ActionResult> Unpack(Guid id)
|
||||||
|
{
|
||||||
|
var downloads = await _downloads.GetForTorrent(id);
|
||||||
|
|
||||||
|
foreach (var download in downloads)
|
||||||
|
{
|
||||||
|
await _torrents.Unpack(download.DownloadId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TorrentControllerUploadFileRequest
|
public class TorrentControllerUploadFileRequest
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ namespace RdtClient.Web
|
||||||
.Enrich.FromLogContext()
|
.Enrich.FromLogContext()
|
||||||
.Enrich.WithExceptionDetails()
|
.Enrich.WithExceptionDetails()
|
||||||
.WriteTo.File(appSettings.Logging.File.Path, logLevel, rollOnFileSizeLimit: true, fileSizeLimitBytes: appSettings.Logging.File.FileSizeLimitBytes, retainedFileCountLimit: appSettings.Logging.File.MaxRollingFiles)
|
.WriteTo.File(appSettings.Logging.File.Path, logLevel, rollOnFileSizeLimit: true, fileSizeLimitBytes: appSettings.Logging.File.FileSizeLimitBytes, retainedFileCountLimit: appSettings.Logging.File.MaxRollingFiles)
|
||||||
|
.WriteTo.Console()
|
||||||
.MinimumLevel.Information()
|
.MinimumLevel.Information()
|
||||||
.CreateLogger();
|
.CreateLogger();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue