diff --git a/backend/app.js b/backend/app.js index 9a2efcd..2d16fb2 100644 --- a/backend/app.js +++ b/backend/app.js @@ -1719,9 +1719,9 @@ app.get('/api/stream', optionalJwt, async (req, res) => { if (!fs.existsSync(file_path)) { logger.error(`File ${file_path} could not be found! UID: ${uid}, ID: ${file_obj.id}`); } - const stat = fs.statSync(file_path) - const fileSize = stat.size - const range = req.headers.range + const stat = fs.statSync(file_path); + const fileSize = stat.size; + const range = req.headers.range; if (range) { const parts = range.replace(/bytes=/, "").split("-") const start = parseInt(parts[0], 10) @@ -1761,7 +1761,7 @@ app.get('/api/thumbnail/:path', optionalJwt, async (req, res) => { else res.sendStatus(404); }); - // Downloads management +// Downloads management app.get('/api/downloads', optionalJwt, async (req, res) => { const user_uid = req.isAuthenticated() ? req.user.uid : null; @@ -1799,12 +1799,32 @@ app.post('/api/pauseDownload', optionalJwt, async (req, res) => { res.send({success: success}); }); +app.post('/api/pauseAllDownloads', optionalJwt, async (req, res) => { + const user_uid = req.isAuthenticated() ? req.user.uid : null; + let success = true; + const all_running_downloads = await db_api.getRecords('download_queue', {paused: false, finished: false, user_uid: user_uid}); + for (let i = 0; i < all_running_downloads.length; i++) { + success &= await downloader_api.pauseDownload(all_running_downloads[i]['uid']); + } + res.send({success: success}); +}); + app.post('/api/resumeDownload', optionalJwt, async (req, res) => { const download_uid = req.body.download_uid; const success = await downloader_api.resumeDownload(download_uid); res.send({success: success}); }); +app.post('/api/resumeAllDownloads', optionalJwt, async (req, res) => { + const user_uid = req.isAuthenticated() ? req.user.uid : null; + let success = true; + const all_paused_downloads = await db_api.getRecords('download_queue', {paused: true, user_uid: user_uid, error: null}); + for (let i = 0; i < all_paused_downloads.length; i++) { + success &= await downloader_api.resumeDownload(all_paused_downloads[i]['uid']); + } + res.send({success: success}); +}); + app.post('/api/restartDownload', optionalJwt, async (req, res) => { const download_uid = req.body.download_uid; const success = await downloader_api.restartDownload(download_uid); diff --git a/backend/package-lock.json b/backend/package-lock.json index a085d89..f68e7c4 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -2727,14 +2727,6 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, - "queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "requires": { - "inherits": "~2.0.3" - } - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", diff --git a/backend/package.json b/backend/package.json index 09c3aa4..8d4579d 100644 --- a/backend/package.json +++ b/backend/package.json @@ -60,7 +60,6 @@ "passport-local": "^1.0.0", "progress": "^2.0.3", "ps-node": "^0.1.6", - "queue": "^6.0.2", "read-last-lines": "^1.7.2", "shortid": "^2.2.15", "unzipper": "^0.10.10", diff --git a/src/app/components/downloads/downloads.component.html b/src/app/components/downloads/downloads.component.html index 2c336b7..db7d220 100644 --- a/src/app/components/downloads/downloads.component.html +++ b/src/app/components/downloads/downloads.component.html @@ -78,8 +78,10 @@ aria-label="Select page of downloads"> -
- +
+ + +
diff --git a/src/app/components/downloads/downloads.component.scss b/src/app/components/downloads/downloads.component.scss index e81f2d7..bb84a6d 100644 --- a/src/app/components/downloads/downloads.component.scss +++ b/src/app/components/downloads/downloads.component.scss @@ -12,4 +12,9 @@ mat-header-cell, mat-cell { position: absolute; top: 7px; left: 6px; +} + +.downloads-action-button-div { + margin-top: 10px; + margin-left: 5px; } \ No newline at end of file diff --git a/src/app/components/downloads/downloads.component.ts b/src/app/components/downloads/downloads.component.ts index e3e36c1..7ff785e 100644 --- a/src/app/components/downloads/downloads.component.ts +++ b/src/app/components/downloads/downloads.component.ts @@ -48,6 +48,9 @@ export class DownloadsComponent implements OnInit, OnDestroy { valid_sessions_length = 0; + paused_download_exists = false; + running_download_exists = false; + STEP_INDEX_TO_LABEL = { 0: 'Creating download', 1: 'Getting info', @@ -81,7 +84,7 @@ export class DownloadsComponent implements OnInit, OnDestroy { } } - getCurrentDownloadsRecurring() { + getCurrentDownloadsRecurring(): void { if (!this.postsService.config['Extra']['enable_downloads_manager']) { this.router.navigate(['/home']); return; @@ -108,6 +111,9 @@ export class DownloadsComponent implements OnInit, OnDestroy { this.dataSource = new MatTableDataSource(this.downloads); this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; + + this.paused_download_exists = this.downloads.find(download => download['paused'] && !download['error']); + this.running_download_exists = this.downloads.find(download => !download['paused'] && !download['finished']); } else { // failed to get downloads } @@ -142,6 +148,14 @@ export class DownloadsComponent implements OnInit, OnDestroy { }); } + pauseAllDownloads(): void { + this.postsService.pauseAllDownloads().subscribe(res => { + if (!res['success']) { + this.postsService.openSnackBar('Failed to pause all downloads! See server logs for more info.'); + } + }); + } + resumeDownload(download_uid: string): void { this.postsService.resumeDownload(download_uid).subscribe(res => { if (!res['success']) { @@ -150,6 +164,14 @@ export class DownloadsComponent implements OnInit, OnDestroy { }); } + resumeAllDownloads(): void { + this.postsService.resumeAllDownloads().subscribe(res => { + if (!res['success']) { + this.postsService.openSnackBar('Failed to resume all downloads! See server logs for more info.'); + } + }); + } + restartDownload(download_uid: string): void { this.postsService.restartDownload(download_uid).subscribe(res => { if (!res['success']) { diff --git a/src/app/posts.services.ts b/src/app/posts.services.ts index 858e3da..7b4aa19 100644 --- a/src/app/posts.services.ts +++ b/src/app/posts.services.ts @@ -425,10 +425,18 @@ export class PostsService implements CanActivate { return this.http.post(this.path + 'pauseDownload', {download_uid: download_uid}, this.httpOptions); } + pauseAllDownloads() { + return this.http.post(this.path + 'pauseAllDownloads', {}, this.httpOptions); + } + resumeDownload(download_uid) { return this.http.post(this.path + 'resumeDownload', {download_uid: download_uid}, this.httpOptions); } + resumeAllDownloads() { + return this.http.post(this.path + 'resumeAllDownloads', {}, this.httpOptions); + } + restartDownload(download_uid) { return this.http.post(this.path + 'restartDownload', {download_uid: download_uid}, this.httpOptions); }