mirror of
https://github.com/Tzahi12345/YoutubeDL-Material.git
synced 2026-03-07 12:00:01 +03:00
Converted downloads page to new downloads schema
This commit is contained in:
@@ -15,12 +15,6 @@ const utils = require('./utils');
|
||||
|
||||
let db_api = null;
|
||||
|
||||
const STEP_INDEX_TO_LABEL = {
|
||||
0: 'Creating download',
|
||||
1: 'Getting info',
|
||||
2: 'Downloading file'
|
||||
}
|
||||
|
||||
const archivePath = path.join(__dirname, 'appdata', 'archives');
|
||||
|
||||
function setDB(input_db_api) { db_api = input_db_api }
|
||||
@@ -62,7 +56,7 @@ async function checkDownloads() {
|
||||
logger.verbose('Checking downloads');
|
||||
const downloads = await db_api.getRecords('download_queue');
|
||||
downloads.sort((download1, download2) => download1.timestamp_start - download2.timestamp_start);
|
||||
const running_downloads = downloads.filter(download => !download.paused);
|
||||
const running_downloads = downloads.filter(download => !download['paused'] && download['finished_step']);
|
||||
for (let i = 0; i < running_downloads.length; i++) {
|
||||
const running_download = running_downloads[i];
|
||||
if (i === 5/*config_api.getConfigItem('ytdl_max_concurrent_downloads')*/) break;
|
||||
@@ -259,7 +253,7 @@ async function downloadQueuedFile(download_uid) {
|
||||
}
|
||||
|
||||
const file_uids = file_objs.map(file_obj => file_obj.uid);
|
||||
await db_api.updateRecord('download_queue', {uid: download_uid}, {finished_step: true, finished: true, percent_complete: 100, file_uids: file_uids, container: container});
|
||||
await db_api.updateRecord('download_queue', {uid: download_uid}, {finished_step: true, finished: true, step_index: 3, percent_complete: 100, file_uids: file_uids, container: container});
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,27 +1,57 @@
|
||||
<div style="padding: 20px;">
|
||||
<div *ngFor="let session_downloads of downloads">
|
||||
<ng-container *ngIf="keys(session_downloads).length > 2">
|
||||
<mat-card style="padding-bottom: 30px; margin-bottom: 15px;">
|
||||
<h4 style="text-align: center;"><ng-container i18n="Session ID">Session ID:</ng-container> {{session_downloads['session_id']}}
|
||||
<span *ngIf="session_downloads['session_id'] === postsService.session_id"> <ng-container i18n="Current session">(current)</ng-container></span>
|
||||
</h4>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div *ngFor="let download of session_downloads | keyvalue: sort_downloads; let i = index;" class="col-12 my-1">
|
||||
<mat-card *ngIf="download.key !== 'session_id' && download.key !== '_id' && download.value" class="mat-elevation-z3">
|
||||
<app-download-item [download]="download.value" [queueNumber]="i+1" (cancelDownload)="clearDownload(session_downloads['session_id'], download.value.uid)"></app-download-item>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button style="top: 15px;" (click)="clearDownloads(session_downloads['session_id'])" mat-stroked-button color="warn"><ng-container i18n="clear all downloads action button">Clear all downloads</ng-container></button>
|
||||
</div>
|
||||
</mat-card>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div *ngIf="downloads">
|
||||
<div class="mat-elevation-z8">
|
||||
<mat-table [dataSource]="dataSource">
|
||||
|
||||
<!-- Date Column -->
|
||||
<ng-container matColumnDef="date">
|
||||
<mat-header-cell *matHeaderCellDef> <ng-container i18n="Date">Date</ng-container> </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.timestamp_start | date: 'short'}} </mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title Column -->
|
||||
<ng-container matColumnDef="title">
|
||||
<mat-header-cell *matHeaderCellDef> <ng-container i18n="Title">Title</ng-container> </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element">
|
||||
<span class="one-line" *ngIf="element.container">
|
||||
{{element.container.title ? element?.container.title : element.container.name}}
|
||||
</span>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Stage Column -->
|
||||
<ng-container matColumnDef="stage">
|
||||
<mat-header-cell *matHeaderCellDef> <ng-container i18n="Stage">Stage</ng-container> </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{STEP_INDEX_TO_LABEL[element.step_index]}} </mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Progress Column -->
|
||||
<ng-container matColumnDef="progress">
|
||||
<mat-header-cell *matHeaderCellDef> <ng-container i18n="Progress">Progress</ng-container> </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{+(element.percent_complete) > 100 ? '100' : element.percent_complete}}% </mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<div *ngIf="downloads && !downloadsValid()">
|
||||
<h4 style="text-align: center;" i18n="No downloads label">No downloads available!</h4>
|
||||
</div>
|
||||
<!-- Actions Column -->
|
||||
<ng-container matColumnDef="actions">
|
||||
<mat-header-cell *matHeaderCellDef> <ng-container i18n="Actions">Actions</ng-container> </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element">
|
||||
<div *ngIf="!element.finished">
|
||||
<button mat-icon-button><mat-icon>pause</mat-icon></button>
|
||||
<button mat-icon-button><mat-icon>cancel</mat-icon></button>
|
||||
</div>
|
||||
<div *ngIf="element.finished">
|
||||
<button mat-icon-button><mat-icon>restart_alt</mat-icon></button>
|
||||
<button mat-icon-button><mat-icon>delete</mat-icon></button>
|
||||
</div>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
|
||||
</mat-table>
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[5, 10, 20]"
|
||||
showFirstLastButtons
|
||||
aria-label="Select page of downloads">
|
||||
</mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
mat-header-cell, mat-cell {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.one-line {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Component, OnInit, ViewChildren, QueryList, ElementRef, OnDestroy } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { PostsService } from 'app/posts.services';
|
||||
import { trigger, transition, animateChild, stagger, query, style, animate } from '@angular/animations';
|
||||
import { Router } from '@angular/router';
|
||||
import { MatPaginator } from '@angular/material/paginator';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
|
||||
@Component({
|
||||
selector: 'app-downloads',
|
||||
@@ -36,12 +38,24 @@ export class DownloadsComponent implements OnInit, OnDestroy {
|
||||
|
||||
downloads_check_interval = 1000;
|
||||
downloads = [];
|
||||
finished_downloads = [];
|
||||
interval_id = null;
|
||||
|
||||
keys = Object.keys;
|
||||
|
||||
valid_sessions_length = 0;
|
||||
|
||||
STEP_INDEX_TO_LABEL = {
|
||||
0: 'Creating download',
|
||||
1: 'Getting info',
|
||||
2: 'Downloading file'
|
||||
}
|
||||
|
||||
displayedColumns: string[] = ['date', 'title', 'stage', 'progress', 'actions'];
|
||||
dataSource = null; // new MatTableDataSource<Download>();
|
||||
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
|
||||
sort_downloads = (a, b) => {
|
||||
const result = b.value.timestamp_start - a.value.timestamp_start;
|
||||
return result;
|
||||
@@ -64,108 +78,37 @@ export class DownloadsComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
ngOnDestroy(): void {
|
||||
if (this.interval_id) { clearInterval(this.interval_id) }
|
||||
}
|
||||
|
||||
getCurrentDownloads() {
|
||||
getCurrentDownloads(): void {
|
||||
this.postsService.getCurrentDownloads().subscribe(res => {
|
||||
if (res['downloads']) {
|
||||
this.assignNewValues(res['downloads']);
|
||||
if (res['downloads'] !== null
|
||||
&& res['downloads'] !== undefined
|
||||
&& JSON.stringify(this.downloads) !== JSON.stringify(res['downloads'])) {
|
||||
this.downloads = res['downloads'];
|
||||
this.dataSource = new MatTableDataSource<Download>(this.downloads);
|
||||
this.dataSource.paginator = this.paginator;
|
||||
} else {
|
||||
// failed to get downloads
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
clearDownload(session_id, download_uid) {
|
||||
this.postsService.clearDownloads(false, session_id, download_uid).subscribe(res => {
|
||||
if (res['success']) {
|
||||
// this.downloads = res['downloads'];
|
||||
} else {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
clearDownloads(session_id) {
|
||||
this.postsService.clearDownloads(false, session_id).subscribe(res => {
|
||||
clearFinishedDownloads(): void {
|
||||
this.postsService.clearDownloads(false).subscribe(res => {
|
||||
if (res['success']) {
|
||||
this.downloads = res['downloads'];
|
||||
} else {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
clearAllDownloads() {
|
||||
this.postsService.clearDownloads(true).subscribe(res => {
|
||||
if (res['success']) {
|
||||
this.downloads = res['downloads'];
|
||||
} else {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
assignNewValues(new_downloads_by_session) {
|
||||
const session_keys = Object.keys(new_downloads_by_session);
|
||||
|
||||
// remove missing session IDs
|
||||
const current_session_ids = Object.keys(this.downloads);
|
||||
const missing_session_ids = current_session_ids.filter(session => session_keys.indexOf(session) === -1)
|
||||
|
||||
for (const missing_session_id of missing_session_ids) {
|
||||
delete this.downloads[missing_session_id];
|
||||
}
|
||||
|
||||
// loop through sessions
|
||||
for (let i = 0; i < session_keys.length; i++) {
|
||||
const session_id = session_keys[i];
|
||||
const session_downloads_by_id = new_downloads_by_session[session_id];
|
||||
const session_download_ids = Object.keys(session_downloads_by_id);
|
||||
|
||||
if (this.downloads[session_id]) {
|
||||
// remove missing download IDs
|
||||
const current_download_ids = Object.keys(this.downloads[session_id]);
|
||||
const missing_download_ids = current_download_ids.filter(download => session_download_ids.indexOf(download) === -1)
|
||||
|
||||
for (const missing_download_id of missing_download_ids) {
|
||||
console.log('removing missing download id');
|
||||
delete this.downloads[session_id][missing_download_id];
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.downloads[session_id]) {
|
||||
this.downloads[session_id] = session_downloads_by_id;
|
||||
} else {
|
||||
for (let j = 0; j < session_download_ids.length; j++) {
|
||||
if (session_download_ids[j] === 'session_id' || session_download_ids[j] === '_id') continue;
|
||||
const download_id = session_download_ids[j];
|
||||
const download = new_downloads_by_session[session_id][download_id]
|
||||
if (!this.downloads[session_id][download_id]) {
|
||||
this.downloads[session_id][download_id] = download;
|
||||
} else {
|
||||
const download_to_update = this.downloads[session_id][download_id];
|
||||
download_to_update['percent_complete'] = download['percent_complete'];
|
||||
download_to_update['complete'] = download['complete'];
|
||||
download_to_update['timestamp_end'] = download['timestamp_end'];
|
||||
download_to_update['downloading'] = download['downloading'];
|
||||
download_to_update['error'] = download['error'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
downloadsValid() {
|
||||
let valid = false;
|
||||
for (let i = 0; i < this.downloads.length; i++) {
|
||||
const session_downloads = this.downloads[i];
|
||||
if (!session_downloads) continue;
|
||||
if (this.keys(session_downloads).length > 2) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export interface Download {
|
||||
timestamp_start: number;
|
||||
title: string;
|
||||
step_index: number;
|
||||
progress: string;
|
||||
}
|
||||
Reference in New Issue
Block a user