diff --git a/backend/config/default.json b/backend/config/default.json index 4e79b75..687dd66 100644 --- a/backend/config/default.json +++ b/backend/config/default.json @@ -18,7 +18,8 @@ "title_top": "Youtube Downloader", "file_manager_enabled": true, "allow_quality_select": true, - "download_only_mode": false + "download_only_mode": false, + "allow_multi_download_mode": true }, "API": { "use_youtube_API": false, diff --git a/backend/config/encrypted.json b/backend/config/encrypted.json index 57d03f0..59d5d0e 100644 --- a/backend/config/encrypted.json +++ b/backend/config/encrypted.json @@ -18,7 +18,8 @@ "title_top": "Youtube Downloader", "file_manager_enabled": true, "allow_quality_select": true, - "download_only_mode": false + "download_only_mode": false, + "allow_multi_download_mode": true }, "API": { "use_youtube_API": false, diff --git a/backend/consts.js b/backend/consts.js index e645a53..af05249 100644 --- a/backend/consts.js +++ b/backend/consts.js @@ -56,6 +56,11 @@ let CONFIG_ITEMS = { 'key': 'ytdl_download_only_mode', 'path': 'YoutubeDLMaterial.Extra.download_only_mode' }, + 'ytdl_allow_multi_download_mode': { + 'key': 'ytdl_allow_multi_download_mode', + 'path': 'YoutubeDLMaterial.Extra.allow_multi_download_mode' + }, + // API 'ytdl_use_youtube_api': { diff --git a/docker-compose.yml b/docker-compose.yml index e17b85c..bb6eabe 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,6 +17,7 @@ services: ytdl_file_manager_enabled: 'true' ytdl_allow_quality_select: 'true' ytdl_download_only_mode: 'false' + ytdl_allow_multi_download_mode: true ytdl_use_youtube_api: 'false' ytdl_youtube_api_key: 'false' ytdl_default_theme: default diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 68ae9af..6ffecfe 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -25,11 +25,12 @@ import {VgBufferingModule} from 'videogular2/compiled/buffering'; import { InputDialogComponent } from './input-dialog/input-dialog.component'; import { LazyLoadImageModule, IsVisibleProps } from 'ng-lazyload-image'; import { NgxContentLoadingModule } from 'ngx-content-loading'; -import { audioFilesMouseHovering, videoFilesMouseHovering } from './main/main.component'; +import { audioFilesMouseHovering, videoFilesMouseHovering, audioFilesOpened, videoFilesOpened } from './main/main.component'; import { CreatePlaylistComponent } from './create-playlist/create-playlist.component'; +import { DownloadItemComponent } from './download-item/download-item.component'; export function isVisible({ event, element, scrollContainer, offset }: IsVisibleProps) { - return (element.id === 'video' ? videoFilesMouseHovering : audioFilesMouseHovering); + return (element.id === 'video' ? videoFilesMouseHovering || videoFilesOpened : audioFilesMouseHovering || audioFilesOpened); } @NgModule({ @@ -39,7 +40,8 @@ export function isVisible({ event, element, scrollContainer, offset }: IsVisible MainComponent, PlayerComponent, InputDialogComponent, - CreatePlaylistComponent + CreatePlaylistComponent, + DownloadItemComponent ], imports: [ BrowserModule, diff --git a/src/app/download-item/download-item.component.html b/src/app/download-item/download-item.component.html new file mode 100644 index 0000000..3ca4144 --- /dev/null +++ b/src/app/download-item/download-item.component.html @@ -0,0 +1,16 @@ +
+ + +
{{queueNumber}}.
+
+ +
ID: {{url_id}}
+
+ + + + + + +
+
\ No newline at end of file diff --git a/src/app/download-item/download-item.component.scss b/src/app/download-item/download-item.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/download-item/download-item.component.spec.ts b/src/app/download-item/download-item.component.spec.ts new file mode 100644 index 0000000..1e731c4 --- /dev/null +++ b/src/app/download-item/download-item.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DownloadItemComponent } from './download-item.component'; + +describe('DownloadItemComponent', () => { + let component: DownloadItemComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DownloadItemComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DownloadItemComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/download-item/download-item.component.ts b/src/app/download-item/download-item.component.ts new file mode 100644 index 0000000..6795d11 --- /dev/null +++ b/src/app/download-item/download-item.component.ts @@ -0,0 +1,41 @@ +import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core'; +import { Download } from 'app/main/main.component'; + + +@Component({ + selector: 'app-download-item', + templateUrl: './download-item.component.html', + styleUrls: ['./download-item.component.scss'] +}) +export class DownloadItemComponent implements OnInit { + + @Input() download: Download = { + uid: null, + type: 'audio', + percent_complete: 0, + url: 'http://youtube.com/watch?v=17848rufj', + downloading: true, + is_playlist: false + }; + @Output() cancelDownload = new EventEmitter(); + + @Input() queueNumber = null; + + url_id = null; + + constructor() { } + + ngOnInit() { + if (this.download && this.download.url && this.download.url.includes('youtube')) { + const string_id = (this.download.is_playlist ? '?list=' : '?v=') + const index_offset = (this.download.is_playlist ? 6 : 3); + const end_index = this.download.url.indexOf(string_id) + index_offset; + this.url_id = this.download.url.substring(end_index, this.download.url.length); + } + } + + cancelTheDownload() { + this.cancelDownload.emit(this.download); + } + +} diff --git a/src/app/main/main.component.html b/src/app/main/main.component.html index c280c09..ead7729 100644 --- a/src/app/main/main.component.html +++ b/src/app/main/main.component.html @@ -50,6 +50,7 @@
Only Audio + Multi-download mode @@ -60,6 +61,18 @@ +
+ +
+
+ + + + +
+
+
+

@@ -81,7 +94,7 @@
- + Audio @@ -116,7 +129,7 @@
- + Video diff --git a/src/app/main/main.component.ts b/src/app/main/main.component.ts index 490ef32..ebaa27e 100644 --- a/src/app/main/main.component.ts +++ b/src/app/main/main.component.ts @@ -22,6 +22,8 @@ import { v4 as uuid } from 'uuid'; export let audioFilesMouseHovering = false; export let videoFilesMouseHovering = false; +export let audioFilesOpened = false; +export let videoFilesOpened = false; export interface Download { uid: string; @@ -44,6 +46,7 @@ export class MainComponent implements OnInit { determinateProgress = false; downloadingfile = false; audioOnly: boolean; + multiDownloadMode = false; urlError = false; path = ''; url = ''; @@ -179,11 +182,19 @@ export class MainComponent implements OnInit { last_valid_url = ''; last_url_check = 0; + test_download: Download = { + uid: null, + type: 'audio', + percent_complete: 0, + url: 'http://youtube.com/watch?v=17848rufj', + downloading: true, + is_playlist: false + }; + constructor(private postsService: PostsService, private youtubeSearch: YoutubeSearchService, public snackBar: MatSnackBar, private router: Router, public dialog: MatDialog, private platform: Platform) { this.audioOnly = false; - // loading config this.postsService.loadNavItems().subscribe(result => { // loads settings const backendUrl = result['YoutubeDLMaterial']['Host']['backendurl']; @@ -350,6 +361,10 @@ export class MainComponent implements OnInit { if (localStorage.getItem('audioOnly') !== null) { this.audioOnly = localStorage.getItem('audioOnly') === 'true'; } + + if (localStorage.getItem('multiDownloadMode') !== null) { + this.multiDownloadMode = localStorage.getItem('multiDownloadMode') === 'true'; + } } // download helpers @@ -359,7 +374,7 @@ export class MainComponent implements OnInit { if (new_download && this.current_download !== new_download) { // console.log('mismatched downloads'); - } else { + } else if (!this.multiDownloadMode) { // if download only mode, just download the file. no redirect if (forceView === false && this.downloadOnlyMode && !this.iOS) { if (is_playlist) { @@ -379,9 +394,17 @@ export class MainComponent implements OnInit { } } + // remove download from current downloads + this.removeDownloadFromCurrentDownloads(new_download); + // reloads mp3s if (this.fileManagerEnabled) { this.getMp3s(); + setTimeout(() => { + this.audioFileCards.forEach(filecard => { + filecard.onHoverResponse(); + }); + }, 200); } } @@ -390,7 +413,7 @@ export class MainComponent implements OnInit { if (new_download && this.current_download !== new_download) { // console.log('mismatched downloads'); - } else { + } else if (!this.multiDownloadMode) { // if download only mode, just download the file. no redirect if (forceView === false && this.downloadOnlyMode) { if (is_playlist) { @@ -410,9 +433,17 @@ export class MainComponent implements OnInit { } } + // remove download from current downloads + this.removeDownloadFromCurrentDownloads(new_download); + // reloads mp4s if (this.fileManagerEnabled) { this.getMp4s(); + setTimeout(() => { + this.videoFileCards.forEach(filecard => { + filecard.onHoverResponse(); + }); + }, 200); } } @@ -433,7 +464,7 @@ export class MainComponent implements OnInit { is_playlist: this.url.includes('playlist') }; this.downloads.push(new_download); - if (!this.current_download) { this.current_download = new_download }; + if (!this.current_download && !this.multiDownloadMode) { this.current_download = new_download }; this.downloadingfile = true; let customQualityConfiguration = null; @@ -471,7 +502,7 @@ export class MainComponent implements OnInit { is_playlist: this.url.includes('playlist') }; this.downloads.push(new_download); - if (!this.current_download) { this.current_download = new_download }; + if (!this.current_download && !this.multiDownloadMode) { this.current_download = new_download }; this.downloadingfile = true; let customQualityConfiguration = null; @@ -500,13 +531,23 @@ export class MainComponent implements OnInit { this.openSnackBar('Download failed!', 'OK.'); }); } + + if (this.multiDownloadMode) { + this.url = ''; + this.downloadingfile = false; + } } else { this.urlError = true; } } // download canceled handler - cancelDownload() { + cancelDownload(download_to_cancel = null) { + // if one is provided, cancel that one. otherwise, remove the current one + if (download_to_cancel) { + this.removeDownloadFromCurrentDownloads(download_to_cancel) + return; + } this.downloadingfile = false; this.current_download.downloading = false; this.current_download = null; @@ -521,6 +562,16 @@ export class MainComponent implements OnInit { } } + removeDownloadFromCurrentDownloads(download_to_remove) { + const index = this.downloads.indexOf(download_to_remove); + if (index !== -1) { + this.downloads.splice(index, 1); + return true; + } else { + return false; + } + } + downloadAudioFile(name) { this.downloading_content['audio'][name] = true; this.postsService.downloadFileFromServer(name, 'audio').subscribe(res => { @@ -687,6 +738,10 @@ export class MainComponent implements OnInit { localStorage.setItem('audioOnly', new_val.checked.toString()); } + multiDownloadModeChanged(new_val) { + localStorage.setItem('multiDownloadMode', new_val.checked.toString()); + } + getAudioAndVideoFormats(formats): any[] { const audio_formats = {}; const video_formats = {}; @@ -770,6 +825,22 @@ export class MainComponent implements OnInit { } } + accordionOpened(type) { + if (type === 'audio') { + audioFilesOpened = true; + } else if (type === 'video') { + videoFilesOpened = true; + } + } + + accordionClosed(type) { + if (type === 'audio') { + audioFilesOpened = false; + } else if (type === 'video') { + videoFilesOpened = false; + } + } + // creating a playlist openCreatePlaylistDialog(type) { const dialogRef = this.dialog.open(CreatePlaylistComponent, { diff --git a/src/assets/default.json b/src/assets/default.json index f3bdb00..a404a12 100644 --- a/src/assets/default.json +++ b/src/assets/default.json @@ -18,7 +18,8 @@ "title_top": "Youtube Downloader", "file_manager_enabled": true, "allow_quality_select": true, - "download_only_mode": false + "download_only_mode": false, + "allow_multi_download_mode": true }, "API": { "use_youtube_API": false, diff --git a/src/index.html b/src/index.html index 74a83f4..69fa759 100644 --- a/src/index.html +++ b/src/index.html @@ -10,7 +10,7 @@ - +